mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-06 19:35:53 -05:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 914a165d6a | |||
| 7fba2247fb | |||
| 4128731c5f | |||
| ef96426ca0 | |||
| ce1dbe8b00 | |||
| 444f043140 | |||
| 2d32c0d671 | |||
| 8dc70a5e30 | |||
| 3e4e55fbf1 | |||
| fcfedd6e15 | |||
| 6c4342690f | |||
| b8c361fcf3 | |||
| 8771a0ec91 | |||
| fc33c52133 | |||
| 75cf9293b1 | |||
| e489c6a346 | |||
| cefc2bdf60 | |||
| 78473bf3d0 | |||
| 15403c6a92 | |||
| 35b98863a4 | |||
| 65f5968fb1 | |||
| 2dfea4d72f | |||
| ff77118932 | |||
| 79a773432a | |||
| d53869f1df | |||
| fc9ddb2b0d | |||
| 6fcb6863bd | |||
| b1cee91ad9 | |||
| 60bd5cbeff | |||
| b6a3a15379 | |||
| c68f214eff | |||
| c90ee84483 | |||
| dc1ee72594 | |||
| 924132287e | |||
| e6f347aa07 | |||
| 367bc23dd4 | |||
| a1a11b2bb8 | |||
| 0653c6a59f | |||
| b6d793e109 |
@@ -20,12 +20,12 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: ./.github/actions/dangerous-git-checkout
|
||||
|
||||
- name: Cache Build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
id: cache-build
|
||||
env:
|
||||
cache-name: prod-build
|
||||
@@ -43,7 +43,7 @@ runs:
|
||||
shell: bash
|
||||
|
||||
- name: Setup Node.js 20.x
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
@@ -53,7 +53,7 @@ runs:
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 2
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
|
||||
- name: Run Chromatic
|
||||
uses: chromaui/action@4c20b95e9d3209ecfdf9cd6aace6bbde71ba1694 # v13.3.4
|
||||
|
||||
+37
-48
@@ -57,7 +57,7 @@ jobs:
|
||||
- uses: ./.github/actions/dangerous-git-checkout
|
||||
|
||||
- name: Setup Node.js 22.x
|
||||
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3.8.2
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: 22.x
|
||||
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
shell: bash
|
||||
|
||||
- name: create .env
|
||||
@@ -85,65 +85,48 @@ jobs:
|
||||
echo "S3_REGION=us-east-1" >> .env
|
||||
echo "S3_BUCKET_NAME=formbricks-e2e" >> .env
|
||||
echo "S3_ENDPOINT_URL=http://localhost:9000" >> .env
|
||||
echo "S3_ACCESS_KEY=devminio" >> .env
|
||||
echo "S3_SECRET_KEY=devminio123" >> .env
|
||||
echo "S3_ACCESS_KEY=devrustfs-service" >> .env
|
||||
echo "S3_SECRET_KEY=devrustfs-service123" >> .env
|
||||
echo "S3_FORCE_PATH_STYLE=1" >> .env
|
||||
shell: bash
|
||||
|
||||
- name: Install MinIO client (mc)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
MC_VERSION="RELEASE.2025-08-13T08-35-41Z"
|
||||
MC_BASE="https://dl.min.io/client/mc/release/linux-amd64/archive"
|
||||
MC_BIN="mc.${MC_VERSION}"
|
||||
MC_SUM="${MC_BIN}.sha256sum"
|
||||
|
||||
curl -fsSL "${MC_BASE}/${MC_BIN}" -o "${MC_BIN}"
|
||||
curl -fsSL "${MC_BASE}/${MC_SUM}" -o "${MC_SUM}"
|
||||
|
||||
sha256sum -c "${MC_SUM}"
|
||||
|
||||
chmod +x "${MC_BIN}"
|
||||
sudo mv "${MC_BIN}" /usr/local/bin/mc
|
||||
|
||||
- name: Start MinIO Server
|
||||
- name: Start RustFS Server
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Start MinIO server in background
|
||||
# Start RustFS server in background
|
||||
docker run -d \
|
||||
--name minio-server \
|
||||
--name rustfs-server \
|
||||
-p 9000:9000 \
|
||||
-p 9001:9001 \
|
||||
-e MINIO_ROOT_USER=devminio \
|
||||
-e MINIO_ROOT_PASSWORD=devminio123 \
|
||||
minio/minio:RELEASE.2025-09-07T16-13-09Z \
|
||||
server /data --console-address :9001
|
||||
-e RUSTFS_ACCESS_KEY=devrustfs \
|
||||
-e RUSTFS_SECRET_KEY=devrustfs123 \
|
||||
-e RUSTFS_ADDRESS=:9000 \
|
||||
-e RUSTFS_CONSOLE_ENABLE=true \
|
||||
-e RUSTFS_CONSOLE_ADDRESS=:9001 \
|
||||
rustfs/rustfs:1.0.0-alpha.93 \
|
||||
/data
|
||||
|
||||
echo "MinIO server started"
|
||||
echo "RustFS server started"
|
||||
|
||||
- name: Wait for MinIO and create S3 bucket
|
||||
- name: Bootstrap RustFS bucket and browser upload CORS
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "Waiting for MinIO to be ready..."
|
||||
ready=0
|
||||
for i in {1..60}; do
|
||||
if curl -fsS http://localhost:9000/minio/health/live >/dev/null; then
|
||||
echo "MinIO is up after ${i} seconds"
|
||||
ready=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ "$ready" -ne 1 ]; then
|
||||
echo "::error::MinIO did not become ready within 60 seconds"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mc alias set local http://localhost:9000 devminio devminio123
|
||||
mc mb --ignore-existing local/formbricks-e2e
|
||||
docker run --rm \
|
||||
--network host \
|
||||
--entrypoint /bin/sh \
|
||||
-e RUSTFS_ENDPOINT_URL=http://127.0.0.1:9000 \
|
||||
-e RUSTFS_ADMIN_USER=devrustfs \
|
||||
-e RUSTFS_ADMIN_PASSWORD=devrustfs123 \
|
||||
-e RUSTFS_SERVICE_USER=devrustfs-service \
|
||||
-e RUSTFS_SERVICE_PASSWORD=devrustfs-service123 \
|
||||
-e RUSTFS_BUCKET_NAME=formbricks-e2e \
|
||||
-e RUSTFS_POLICY_NAME=formbricks-e2e-policy \
|
||||
-e RUSTFS_CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000 \
|
||||
-v "$PWD/docker/rustfs-init.sh:/tmp/rustfs-init.sh:ro" \
|
||||
minio/mc@sha256:95b5f3f7969a5c5a9f3a700ba72d5c84172819e13385aaf916e237cf111ab868 \
|
||||
/tmp/rustfs-init.sh
|
||||
|
||||
- name: Build App
|
||||
run: |
|
||||
@@ -242,8 +225,14 @@ jobs:
|
||||
if: failure()
|
||||
with:
|
||||
name: app-logs
|
||||
if-no-files-found: ignore
|
||||
path: app.log
|
||||
|
||||
- name: Output App Logs
|
||||
if: failure()
|
||||
run: cat app.log
|
||||
run: |
|
||||
if [ -f app.log ]; then
|
||||
cat app.log
|
||||
else
|
||||
echo "app.log not found because the Run App step did not execute or failed before log creation."
|
||||
fi
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- uses: ./.github/actions/dangerous-git-checkout
|
||||
|
||||
- name: Setup Node.js 20.x
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
|
||||
- name: create .env
|
||||
run: cp .env.example .env
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
- name: Setup Node.js 22.x
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: 22.x
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
|
||||
- name: create .env
|
||||
run: cp .env.example .env
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- uses: ./.github/actions/dangerous-git-checkout
|
||||
|
||||
- name: Setup Node.js 20.x
|
||||
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3.8.2
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
|
||||
- name: create .env
|
||||
run: cp .env.example .env
|
||||
|
||||
@@ -2,6 +2,7 @@ name: Translation Validation
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -39,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Setup Node.js 22.x
|
||||
if: steps.changes.outputs.translations == 'true'
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: 22.x
|
||||
|
||||
@@ -49,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.changes.outputs.translations == 'true'
|
||||
run: pnpm install --config.platform=linux --config.architecture=x64
|
||||
run: pnpm install --frozen-lockfile --config.platform=linux --config.architecture=x64
|
||||
|
||||
- name: Validate translation keys
|
||||
if: steps.changes.outputs.translations == 'true'
|
||||
|
||||
@@ -12,18 +12,18 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^5.0.1",
|
||||
"@storybook/addon-a11y": "10.2.17",
|
||||
"@storybook/addon-links": "10.2.17",
|
||||
"@storybook/addon-onboarding": "10.2.17",
|
||||
"@storybook/react-vite": "10.2.17",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@storybook/addon-a11y": "10.3.5",
|
||||
"@storybook/addon-docs": "10.3.5",
|
||||
"@storybook/addon-links": "10.3.5",
|
||||
"@storybook/addon-onboarding": "10.3.5",
|
||||
"@storybook/react-vite": "10.3.5",
|
||||
"@tailwindcss/vite": "4.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@vitejs/plugin-react": "5.1.4",
|
||||
"eslint-plugin-react-refresh": "0.4.26",
|
||||
"eslint-plugin-storybook": "10.2.17",
|
||||
"storybook": "10.2.17",
|
||||
"vite": "7.3.1",
|
||||
"@storybook/addon-docs": "10.2.17"
|
||||
"eslint-plugin-storybook": "10.3.5",
|
||||
"storybook": "10.3.5",
|
||||
"vite": "7.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
@@ -32,7 +32,7 @@ describe("getTeamsByOrganizationId", () => {
|
||||
|
||||
test("throws DatabaseError on Prisma error", async () => {
|
||||
vi.mocked(prisma.team.findMany).mockRejectedValueOnce(
|
||||
new Prisma.PrismaClientKnownRequestError("fail", { code: "P2002", clientVersion: "1.0.0" })
|
||||
new PrismaClientKnownRequestError("fail", { code: "P2002", clientVersion: "1.0.0" })
|
||||
);
|
||||
await expect(getTeamsByOrganizationId("org1")).rejects.toThrow(DatabaseError);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use server";
|
||||
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
|
||||
import { cache as reactCache } from "react";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { ZId } from "@formbricks/types/common";
|
||||
@@ -27,7 +27,7 @@ export const getTeamsByOrganizationId = reactCache(
|
||||
name: team.name,
|
||||
}));
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
if (error instanceof PrismaClientKnownRequestError) {
|
||||
throw new DatabaseError(error.message);
|
||||
}
|
||||
|
||||
|
||||
@@ -409,16 +409,22 @@ export const MainNavigation = ({
|
||||
: `/environments/${environment.id}/surveys/`;
|
||||
|
||||
const handleProjectChange = (projectId: string) => {
|
||||
if (projectId === project.id) return;
|
||||
const targetPath =
|
||||
projectId === project.id ? `/environments/${environment.id}/surveys` : `/workspaces/${projectId}/`;
|
||||
startTransition(() => {
|
||||
router.push(`/workspaces/${projectId}/`);
|
||||
setIsWorkspaceDropdownOpen(false);
|
||||
router.push(targetPath);
|
||||
});
|
||||
};
|
||||
|
||||
const handleOrganizationChange = (organizationId: string) => {
|
||||
if (organizationId === organization.id) return;
|
||||
const targetPath =
|
||||
organizationId === organization.id
|
||||
? `/environments/${environment.id}/settings/general`
|
||||
: `/organizations/${organizationId}/`;
|
||||
startTransition(() => {
|
||||
router.push(`/organizations/${organizationId}/`);
|
||||
setIsOrganizationDropdownOpen(false);
|
||||
router.push(targetPath);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -475,7 +481,7 @@ export const MainNavigation = ({
|
||||
);
|
||||
|
||||
const switcherIconClasses =
|
||||
"flex h-9 w-9 items-center justify-center rounded-full bg-slate-100 text-slate-600";
|
||||
"flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-slate-100 text-slate-600";
|
||||
const isInitialProjectsLoading = isWorkspaceDropdownOpen && !hasInitializedProjects && !workspaceLoadError;
|
||||
|
||||
return (
|
||||
|
||||
+5
-1
@@ -114,8 +114,12 @@ export const OrganizationBreadcrumb = ({
|
||||
}
|
||||
|
||||
const handleOrganizationChange = (organizationId: string) => {
|
||||
if (organizationId === currentOrganizationId) return;
|
||||
startTransition(() => {
|
||||
setIsOrganizationDropdownOpen(false);
|
||||
if (organizationId === currentOrganizationId && currentEnvironmentId) {
|
||||
router.push(`/environments/${currentEnvironmentId}/settings/general`);
|
||||
return;
|
||||
}
|
||||
router.push(`/organizations/${organizationId}/`);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -152,9 +152,13 @@ export const ProjectBreadcrumb = ({
|
||||
}
|
||||
|
||||
const handleProjectChange = (projectId: string) => {
|
||||
if (projectId === currentProjectId) return;
|
||||
const targetPath =
|
||||
projectId === currentProjectId
|
||||
? `/environments/${currentEnvironmentId}/surveys`
|
||||
: `/workspaces/${projectId}/`;
|
||||
startTransition(() => {
|
||||
router.push(`/workspaces/${projectId}/`);
|
||||
setIsProjectDropdownOpen(false);
|
||||
router.push(targetPath);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
+8
-11
@@ -3,25 +3,22 @@
|
||||
import { InboxIcon, PresentationIcon } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { useEnvironment } from "@/app/(app)/environments/[environmentId]/context/environment-context";
|
||||
import { revalidateSurveyIdPath } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/actions";
|
||||
import { useSurvey } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/context/survey-context";
|
||||
import { SecondaryNavigation } from "@/modules/ui/components/secondary-navigation";
|
||||
|
||||
interface SurveyAnalysisNavigationProps {
|
||||
environmentId: string;
|
||||
survey: TSurvey;
|
||||
activeId: string;
|
||||
}
|
||||
|
||||
export const SurveyAnalysisNavigation = ({
|
||||
environmentId,
|
||||
survey,
|
||||
activeId,
|
||||
}: SurveyAnalysisNavigationProps) => {
|
||||
export const SurveyAnalysisNavigation = ({ activeId }: SurveyAnalysisNavigationProps) => {
|
||||
const pathname = usePathname();
|
||||
const { t } = useTranslation();
|
||||
const { environment } = useEnvironment();
|
||||
const { survey } = useSurvey();
|
||||
|
||||
const url = `/environments/${environmentId}/surveys/${survey.id}`;
|
||||
const url = `/environments/${environment.id}/surveys/${survey.id}`;
|
||||
|
||||
const navigation = [
|
||||
{
|
||||
@@ -31,7 +28,7 @@ export const SurveyAnalysisNavigation = ({
|
||||
href: `${url}/summary?referer=true`,
|
||||
current: pathname?.includes("/summary"),
|
||||
onClick: () => {
|
||||
revalidateSurveyIdPath(environmentId, survey.id);
|
||||
revalidateSurveyIdPath(environment.id, survey.id);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -41,7 +38,7 @@ export const SurveyAnalysisNavigation = ({
|
||||
href: `${url}/responses?referer=true`,
|
||||
current: pathname?.includes("/responses"),
|
||||
onClick: () => {
|
||||
revalidateSurveyIdPath(environmentId, survey.id);
|
||||
revalidateSurveyIdPath(environment.id, survey.id);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
+1
-1
@@ -1,5 +1,4 @@
|
||||
import { TFunction } from "i18next";
|
||||
import { capitalize } from "lodash";
|
||||
import {
|
||||
AirplayIcon,
|
||||
ArrowUpFromDotIcon,
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
SmartphoneIcon,
|
||||
} from "lucide-react";
|
||||
import { TResponseMeta } from "@formbricks/types/responses";
|
||||
import { capitalize } from "@/lib/utils/object";
|
||||
|
||||
export const getAddressFieldLabel = (field: string, t: TFunction) => {
|
||||
switch (field) {
|
||||
|
||||
+1
-3
@@ -64,8 +64,6 @@ const Page = async (props: { params: Promise<{ environmentId: string; surveyId:
|
||||
pageTitle={survey.name}
|
||||
cta={
|
||||
<SurveyAnalysisCTA
|
||||
environment={environment}
|
||||
survey={survey}
|
||||
isReadOnly={isReadOnly}
|
||||
user={user}
|
||||
publicDomain={publicDomain}
|
||||
@@ -76,7 +74,7 @@ const Page = async (props: { params: Promise<{ environmentId: string; surveyId:
|
||||
isStorageConfigured={IS_STORAGE_CONFIGURED}
|
||||
/>
|
||||
}>
|
||||
<SurveyAnalysisNavigation environmentId={environment.id} survey={survey} activeId="responses" />
|
||||
<SurveyAnalysisNavigation activeId="responses" />
|
||||
</PageHeader>
|
||||
<ResponsePage
|
||||
environment={environment}
|
||||
|
||||
+5
-8
@@ -4,16 +4,13 @@ import { useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { useEnvironment } from "@/app/(app)/environments/[environmentId]/context/environment-context";
|
||||
import { useSurvey } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/context/survey-context";
|
||||
import { Confetti } from "@/modules/ui/components/confetti";
|
||||
|
||||
interface SummaryMetadataProps {
|
||||
environment: TEnvironment;
|
||||
survey: TSurvey;
|
||||
}
|
||||
|
||||
export const SuccessMessage = ({ environment, survey }: SummaryMetadataProps) => {
|
||||
export const SuccessMessage = () => {
|
||||
const { environment } = useEnvironment();
|
||||
const { survey } = useSurvey();
|
||||
const { t } = useTranslation();
|
||||
const searchParams = useSearchParams();
|
||||
const [confetti, setConfetti] = useState(false);
|
||||
|
||||
+5
-9
@@ -5,14 +5,13 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { TSegment } from "@formbricks/types/segment";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TUser } from "@formbricks/types/user";
|
||||
import { useEnvironment } from "@/app/(app)/environments/[environmentId]/context/environment-context";
|
||||
import { SuccessMessage } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SuccessMessage";
|
||||
import { ShareSurveyModal } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/share-survey-modal";
|
||||
import { SurveyStatusDropdown } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown";
|
||||
import { useSurvey } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/context/survey-context";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { EditPublicSurveyAlertDialog } from "@/modules/survey/components/edit-public-survey-alert-dialog";
|
||||
import { useSingleUseId } from "@/modules/survey/hooks/useSingleUseId";
|
||||
@@ -23,8 +22,6 @@ import { IconBar } from "@/modules/ui/components/iconbar";
|
||||
import { resetSurveyAction } from "../actions";
|
||||
|
||||
interface SurveyAnalysisCTAProps {
|
||||
survey: TSurvey;
|
||||
environment: TEnvironment;
|
||||
isReadOnly: boolean;
|
||||
user: TUser;
|
||||
publicDomain: string;
|
||||
@@ -41,8 +38,6 @@ interface ModalState {
|
||||
}
|
||||
|
||||
export const SurveyAnalysisCTA = ({
|
||||
survey,
|
||||
environment,
|
||||
isReadOnly,
|
||||
user,
|
||||
publicDomain,
|
||||
@@ -64,7 +59,8 @@ export const SurveyAnalysisCTA = ({
|
||||
const [isResetModalOpen, setIsResetModalOpen] = useState(false);
|
||||
const [isResetting, setIsResetting] = useState(false);
|
||||
|
||||
const { project } = useEnvironment();
|
||||
const { environment, project } = useEnvironment();
|
||||
const { survey } = useSurvey();
|
||||
const { refreshSingleUseId } = useSingleUseId(survey, isReadOnly);
|
||||
|
||||
const appSetupCompleted = survey.type === "app" && environment.appSetupCompleted;
|
||||
@@ -183,7 +179,7 @@ export const SurveyAnalysisCTA = ({
|
||||
return (
|
||||
<div className="hidden justify-end gap-x-1.5 sm:flex">
|
||||
{!isReadOnly && (appSetupCompleted || survey.type === "link") && survey.status !== "draft" && (
|
||||
<SurveyStatusDropdown environment={environment} survey={survey} />
|
||||
<SurveyStatusDropdown />
|
||||
)}
|
||||
|
||||
<IconBar actions={iconActions} />
|
||||
@@ -215,7 +211,7 @@ export const SurveyAnalysisCTA = ({
|
||||
projectCustomScripts={project.customHeadScripts}
|
||||
/>
|
||||
)}
|
||||
<SuccessMessage environment={environment} survey={survey} />
|
||||
<SuccessMessage />
|
||||
|
||||
{responseCount > 0 && (
|
||||
<EditPublicSurveyAlertDialog
|
||||
|
||||
+18
-3
@@ -16,13 +16,19 @@ export const WebsiteEmbedTab = ({ surveyUrl }: WebsiteEmbedTabProps) => {
|
||||
const [embedModeEnabled, setEmbedModeEnabled] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const iframeCode = `<div style="position: relative; height:80dvh; overflow:auto;">
|
||||
<iframe
|
||||
src="${surveyUrl}${embedModeEnabled ? "?embed=true" : ""}"
|
||||
const separator = surveyUrl.includes("?") ? "&" : "?";
|
||||
|
||||
const iframeSrc = embedModeEnabled ? `${surveyUrl}${separator}embed=true` : surveyUrl;
|
||||
|
||||
const iframeCode = `<div style="position: relative; height:80dvh; overflow:auto;">
|
||||
<iframe
|
||||
src="${iframeSrc}"
|
||||
frameborder="0" style="position: absolute; left:0; top:0; width:100%; height:100%; border:0;">
|
||||
</iframe>
|
||||
</div>`;
|
||||
|
||||
const previewSrc = `${iframeSrc}${iframeSrc.includes("?") ? "&" : "?"}preview=true`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<CodeBlock language="html" noMargin>
|
||||
@@ -48,6 +54,15 @@ export const WebsiteEmbedTab = ({ surveyUrl }: WebsiteEmbedTabProps) => {
|
||||
{t("common.copy_code")}
|
||||
<CopyIcon />
|
||||
</Button>
|
||||
|
||||
<p className="text-base font-medium text-slate-800">{t("common.preview")}</p>
|
||||
<div className="relative h-[500px] w-full overflow-hidden rounded-lg border border-slate-300">
|
||||
<iframe
|
||||
title={t("common.preview")}
|
||||
src={previewSrc}
|
||||
className="absolute inset-0 h-full w-full border-0"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+1
-3
@@ -66,8 +66,6 @@ const SurveyPage = async (props: { params: Promise<{ environmentId: string; surv
|
||||
pageTitle={survey.name}
|
||||
cta={
|
||||
<SurveyAnalysisCTA
|
||||
environment={environment}
|
||||
survey={survey}
|
||||
isReadOnly={isReadOnly}
|
||||
user={user}
|
||||
publicDomain={publicDomain}
|
||||
@@ -78,7 +76,7 @@ const SurveyPage = async (props: { params: Promise<{ environmentId: string; surv
|
||||
isStorageConfigured={IS_STORAGE_CONFIGURED}
|
||||
/>
|
||||
}>
|
||||
<SurveyAnalysisNavigation environmentId={environment.id} survey={survey} activeId="summary" />
|
||||
<SurveyAnalysisNavigation activeId="summary" />
|
||||
</PageHeader>
|
||||
<SummaryPage
|
||||
environment={environment}
|
||||
|
||||
+5
-16
@@ -3,8 +3,9 @@
|
||||
import { useRouter } from "next/navigation";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { useEnvironment } from "@/app/(app)/environments/[environmentId]/context/environment-context";
|
||||
import { useSurvey } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/context/survey-context";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { updateSurveyAction } from "@/modules/survey/editor/actions";
|
||||
import {
|
||||
@@ -16,17 +17,9 @@ import {
|
||||
} from "@/modules/ui/components/select";
|
||||
import { SurveyStatusIndicator } from "@/modules/ui/components/survey-status-indicator";
|
||||
|
||||
interface SurveyStatusDropdownProps {
|
||||
environment: TEnvironment;
|
||||
updateLocalSurveyStatus?: (status: TSurvey["status"]) => void;
|
||||
survey: TSurvey;
|
||||
}
|
||||
|
||||
export const SurveyStatusDropdown = ({
|
||||
environment,
|
||||
updateLocalSurveyStatus,
|
||||
survey,
|
||||
}: SurveyStatusDropdownProps) => {
|
||||
export const SurveyStatusDropdown = () => {
|
||||
const { environment } = useEnvironment();
|
||||
const { survey } = useSurvey();
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -46,10 +39,6 @@ export const SurveyStatusDropdown = ({
|
||||
toast.success(toastMessage);
|
||||
}
|
||||
|
||||
if (updateLocalSurveyStatus) {
|
||||
updateLocalSurveyStatus(resultingStatus);
|
||||
}
|
||||
|
||||
router.refresh();
|
||||
} else {
|
||||
const errorMessage = getFormattedErrorMessage(updateSurveyActionResponse);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { type ReactNode } from "react";
|
||||
import { SurveysQueryClientProvider } from "./query-client-provider";
|
||||
|
||||
const SurveysLayout = ({ children }: { children: ReactNode }) => {
|
||||
return <SurveysQueryClientProvider>{children}</SurveysQueryClientProvider>;
|
||||
};
|
||||
|
||||
export default SurveysLayout;
|
||||
@@ -0,0 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { type ReactNode, useState } from "react";
|
||||
|
||||
export const SurveysQueryClientProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [queryClient] = useState(() => new QueryClient());
|
||||
|
||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
||||
};
|
||||
+4
@@ -18,6 +18,7 @@ interface AirtableWrapperProps {
|
||||
isEnabled: boolean;
|
||||
webAppUrl: string;
|
||||
locale: TUserLocale;
|
||||
showReconnectButton?: boolean;
|
||||
}
|
||||
|
||||
export const AirtableWrapper = ({
|
||||
@@ -28,6 +29,7 @@ export const AirtableWrapper = ({
|
||||
isEnabled,
|
||||
webAppUrl,
|
||||
locale,
|
||||
showReconnectButton = false,
|
||||
}: AirtableWrapperProps) => {
|
||||
const [isConnected, setIsConnected] = useState(
|
||||
airtableIntegration ? airtableIntegration.config?.key : false
|
||||
@@ -49,6 +51,8 @@ export const AirtableWrapper = ({
|
||||
setIsConnected={setIsConnected}
|
||||
surveys={surveys}
|
||||
locale={locale}
|
||||
showReconnectButton={showReconnectButton}
|
||||
handleAirtableAuthorization={handleAirtableAuthorization}
|
||||
/>
|
||||
) : (
|
||||
<ConnectIntegration
|
||||
|
||||
+38
-9
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Trash2Icon } from "lucide-react";
|
||||
import { RefreshCcwIcon, Trash2Icon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -12,9 +12,11 @@ import { deleteIntegrationAction } from "@/app/(app)/environments/[environmentId
|
||||
import { AddIntegrationModal } from "@/app/(app)/environments/[environmentId]/workspace/integrations/airtable/components/AddIntegrationModal";
|
||||
import { timeSince } from "@/lib/time";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { Alert, AlertButton, AlertDescription } from "@/modules/ui/components/alert";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { DeleteDialog } from "@/modules/ui/components/delete-dialog";
|
||||
import { EmptyState } from "@/modules/ui/components/empty-state";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/modules/ui/components/tooltip";
|
||||
import { IntegrationModalInputs } from "../lib/types";
|
||||
|
||||
interface ManageIntegrationProps {
|
||||
@@ -24,10 +26,20 @@ interface ManageIntegrationProps {
|
||||
surveys: TSurvey[];
|
||||
airtableArray: TIntegrationItem[];
|
||||
locale: TUserLocale;
|
||||
showReconnectButton: boolean;
|
||||
handleAirtableAuthorization: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const ManageIntegration = (props: ManageIntegrationProps) => {
|
||||
const { airtableIntegration, environmentId, setIsConnected, surveys, airtableArray } = props;
|
||||
export const ManageIntegration = ({
|
||||
airtableIntegration,
|
||||
environmentId,
|
||||
setIsConnected,
|
||||
surveys,
|
||||
airtableArray,
|
||||
showReconnectButton,
|
||||
handleAirtableAuthorization,
|
||||
locale,
|
||||
}: ManageIntegrationProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const tableHeaders = [
|
||||
@@ -73,15 +85,34 @@ export const ManageIntegration = (props: ManageIntegrationProps) => {
|
||||
: { isEditMode: false as const };
|
||||
return (
|
||||
<div className="mt-6 flex w-full flex-col items-center justify-center p-6">
|
||||
<div className="flex w-full justify-end gap-x-6">
|
||||
<div className="flex items-center">
|
||||
{showReconnectButton && (
|
||||
<Alert variant="warning" size="small" className="mb-4 w-full">
|
||||
<AlertDescription>{t("environments.integrations.reconnect_button_description")}</AlertDescription>
|
||||
<AlertButton onClick={handleAirtableAuthorization}>
|
||||
{t("environments.integrations.reconnect_button")}
|
||||
</AlertButton>
|
||||
</Alert>
|
||||
)}
|
||||
<div className="flex w-full justify-end space-x-2">
|
||||
<div className="mr-6 flex items-center">
|
||||
<span className="mr-4 h-4 w-4 rounded-full bg-green-600"></span>
|
||||
<span className="cursor-pointer text-slate-500">
|
||||
<span className="text-slate-500">
|
||||
{t("environments.integrations.connected_with_email", {
|
||||
email: airtableIntegration.config.email,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline" onClick={handleAirtableAuthorization}>
|
||||
<RefreshCcwIcon className="mr-2 h-4 w-4" />
|
||||
{t("environments.integrations.reconnect_button")}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("environments.integrations.reconnect_button_tooltip")}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setDefaultValues(null);
|
||||
@@ -122,9 +153,7 @@ export const ManageIntegration = (props: ManageIntegrationProps) => {
|
||||
<div className="col-span-2 text-center">{data.surveyName}</div>
|
||||
<div className="col-span-2 text-center">{data.tableName}</div>
|
||||
<div className="col-span-2 text-center">{data.elements}</div>
|
||||
<div className="col-span-2 text-center">
|
||||
{timeSince(data.createdAt.toString(), props.locale)}
|
||||
</div>
|
||||
<div className="col-span-2 text-center">{timeSince(data.createdAt.toString(), locale)}</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
+9
-1
@@ -1,4 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { TIntegrationItem } from "@formbricks/types/integration";
|
||||
import { TIntegrationAirtable } from "@formbricks/types/integration/airtable";
|
||||
import { AirtableWrapper } from "@/app/(app)/environments/[environmentId]/workspace/integrations/airtable/components/AirtableWrapper";
|
||||
@@ -31,8 +32,14 @@ const Page = async (props: { params: Promise<{ environmentId: string }> }) => {
|
||||
);
|
||||
|
||||
let airtableArray: TIntegrationItem[] = [];
|
||||
let isTokenValid = true;
|
||||
if (airtableIntegration?.config.key) {
|
||||
airtableArray = await getAirtableTables(params.environmentId);
|
||||
try {
|
||||
airtableArray = await getAirtableTables(params.environmentId);
|
||||
} catch (error) {
|
||||
logger.error(error, "Failed to load Airtable bases — token may be expired or revoked");
|
||||
isTokenValid = false;
|
||||
}
|
||||
}
|
||||
if (isReadOnly) {
|
||||
return redirect("./");
|
||||
@@ -51,6 +58,7 @@ const Page = async (props: { params: Promise<{ environmentId: string }> }) => {
|
||||
surveys={surveys}
|
||||
webAppUrl={WEBAPP_URL}
|
||||
locale={locale ?? DEFAULT_LOCALE}
|
||||
showReconnectButton={!isTokenValid}
|
||||
/>
|
||||
</div>
|
||||
</PageContentWrapper>
|
||||
|
||||
@@ -185,4 +185,20 @@ describe("auth route audit logging", () => {
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("does not log a completed sign-in for the intermediate SSO recovery verification step", async () => {
|
||||
const authOptions = await getWrappedAuthOptions("req-sso-recovery");
|
||||
const user = {
|
||||
id: "user_4",
|
||||
email: "user4@example.com",
|
||||
authFlowPurpose: "sso_recovery",
|
||||
};
|
||||
const account = { provider: "token" };
|
||||
|
||||
await expect(authOptions.callbacks.signIn({ user, account })).resolves.toBe(true);
|
||||
await authOptions.events.signIn({ user, account, isNewUser: false });
|
||||
|
||||
expect(mocks.baseEventSignIn).not.toHaveBeenCalled();
|
||||
expect(mocks.queueAuditEventBackground).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,6 +26,12 @@ const getAuthMethod = (account: Account | null) => {
|
||||
return "unknown";
|
||||
};
|
||||
|
||||
const isSsoRecoveryVerificationFlow = (account: Account | null, user: User | AdapterUser) =>
|
||||
account?.provider === "token" &&
|
||||
"authFlowPurpose" in user &&
|
||||
typeof user.authFlowPurpose === "string" &&
|
||||
user.authFlowPurpose === "sso_recovery";
|
||||
|
||||
const handler = async (req: Request, ctx: any) => {
|
||||
const eventId = req.headers.get("x-request-id") ?? undefined;
|
||||
|
||||
@@ -117,6 +123,10 @@ const handler = async (req: Request, ctx: any) => {
|
||||
events: {
|
||||
...baseAuthOptions.events,
|
||||
async signIn({ user, account, isNewUser }: any) {
|
||||
if (isSsoRecoveryVerificationFlow(account, user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await baseAuthOptions.events?.signIn?.({ user, account, isNewUser });
|
||||
} catch (err) {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { getServerSession } from "next-auth";
|
||||
import { NextResponse } from "next/server";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { verifySsoRelinkIntent } from "@/lib/jwt";
|
||||
import { deleteSessionBySessionToken } from "@/modules/auth/lib/auth-session-repository";
|
||||
import { authOptions } from "@/modules/auth/lib/authOptions";
|
||||
import {
|
||||
NEXT_AUTH_SESSION_COOKIE_NAMES,
|
||||
getSessionTokenFromCookieHeader,
|
||||
} from "@/modules/auth/lib/session-cookie";
|
||||
import { completeSsoRecovery, getSsoRecoveryFailureRedirectUrl } from "@/modules/ee/sso/lib/sso-recovery";
|
||||
|
||||
const clearSessionCookies = (response: NextResponse) => {
|
||||
for (const cookieName of NEXT_AUTH_SESSION_COOKIE_NAMES) {
|
||||
response.cookies.set({
|
||||
name: cookieName,
|
||||
value: "",
|
||||
expires: new Date(0),
|
||||
path: "/",
|
||||
secure: cookieName.startsWith("__Secure-"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const buildFailedRecoveryResponse = async (request: Request, callbackUrl?: string) => {
|
||||
const response = NextResponse.redirect(getSsoRecoveryFailureRedirectUrl(callbackUrl));
|
||||
clearSessionCookies(response);
|
||||
|
||||
const sessionToken = getSessionTokenFromCookieHeader(request.headers.get("cookie"));
|
||||
if (!sessionToken) {
|
||||
return response;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteSessionBySessionToken(sessionToken);
|
||||
} catch (error) {
|
||||
logger.error(error, "Failed to delete SSO recovery session after recovery completion error");
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
export const GET = async (request: Request) => {
|
||||
const url = new URL(request.url);
|
||||
const intentToken = url.searchParams.get("intent");
|
||||
|
||||
if (!intentToken) {
|
||||
return NextResponse.redirect(getSsoRecoveryFailureRedirectUrl());
|
||||
}
|
||||
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
const callbackUrl = await completeSsoRecovery({
|
||||
intentToken,
|
||||
sessionUserId: session?.user.id,
|
||||
});
|
||||
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} catch {
|
||||
try {
|
||||
const intent = verifySsoRelinkIntent(intentToken);
|
||||
return await buildFailedRecoveryResponse(request, intent.callbackUrl);
|
||||
} catch {
|
||||
return await buildFailedRecoveryResponse(request);
|
||||
}
|
||||
}
|
||||
};
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { DatabaseError, ResourceNotFoundError, ValidationError } from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { getResponseIdByDisplayId } from "./response";
|
||||
|
||||
vi.mock("@/lib/utils/validate", () => ({
|
||||
validateInputs: vi.fn((inputs: [unknown, unknown][]) =>
|
||||
inputs.map((input: [unknown, unknown]) => input[0])
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
prisma: {
|
||||
display: {
|
||||
findFirst: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe("getResponseIdByDisplayId", () => {
|
||||
const environmentId = "env1234567890123456789012";
|
||||
const displayId = "display1234567890123456789";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns the linked responseId when a response exists", async () => {
|
||||
vi.mocked(prisma.display.findFirst).mockResolvedValue({
|
||||
response: {
|
||||
id: "response123456789012345678",
|
||||
},
|
||||
} as any);
|
||||
|
||||
const result = await getResponseIdByDisplayId(environmentId, displayId);
|
||||
|
||||
expect(validateInputs).toHaveBeenCalledWith(
|
||||
[environmentId, expect.any(Object)],
|
||||
[displayId, expect.any(Object)]
|
||||
);
|
||||
expect(prisma.display.findFirst).toHaveBeenCalledWith({
|
||||
where: {
|
||||
id: displayId,
|
||||
survey: {
|
||||
environmentId,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
response: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toEqual({ responseId: "response123456789012345678" });
|
||||
});
|
||||
|
||||
test("returns null when the display exists but has no response", async () => {
|
||||
vi.mocked(prisma.display.findFirst).mockResolvedValue({
|
||||
response: null,
|
||||
} as any);
|
||||
|
||||
await expect(getResponseIdByDisplayId(environmentId, displayId)).resolves.toEqual({
|
||||
responseId: null,
|
||||
});
|
||||
});
|
||||
|
||||
test("throws ResourceNotFoundError when the display does not exist in the environment", async () => {
|
||||
vi.mocked(prisma.display.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(getResponseIdByDisplayId(environmentId, displayId)).rejects.toThrow(
|
||||
new ResourceNotFoundError("Display", displayId)
|
||||
);
|
||||
});
|
||||
|
||||
test("throws ValidationError when input validation fails", async () => {
|
||||
const validationError = new ValidationError("Validation failed");
|
||||
vi.mocked(validateInputs).mockImplementation(() => {
|
||||
throw validationError;
|
||||
});
|
||||
|
||||
await expect(getResponseIdByDisplayId(environmentId, displayId)).rejects.toThrow(ValidationError);
|
||||
expect(prisma.display.findFirst).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("throws DatabaseError on Prisma request errors", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Database error", {
|
||||
code: "P2002",
|
||||
clientVersion: "test",
|
||||
});
|
||||
vi.mocked(prisma.display.findFirst).mockRejectedValue(prismaError);
|
||||
|
||||
await expect(getResponseIdByDisplayId(environmentId, displayId)).rejects.toThrow(DatabaseError);
|
||||
});
|
||||
});
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { ZId } from "@formbricks/types/common";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
|
||||
export const getResponseIdByDisplayId = async (
|
||||
environmentId: string,
|
||||
displayId: string
|
||||
): Promise<{ responseId: string | null }> => {
|
||||
validateInputs([environmentId, ZId], [displayId, ZId]);
|
||||
|
||||
try {
|
||||
const display = await prisma.display.findFirst({
|
||||
where: {
|
||||
id: displayId,
|
||||
survey: {
|
||||
environmentId,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
response: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!display) {
|
||||
throw new ResourceNotFoundError("Display", displayId);
|
||||
}
|
||||
|
||||
return {
|
||||
responseId: display.response?.id ?? null,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseError(error.message);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import { NextRequest } from "next/server";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { getResponseIdByDisplayId } from "./lib/response";
|
||||
import { GET } from "./route";
|
||||
|
||||
vi.mock("@/app/lib/api/with-api-logging", async () => {
|
||||
return {
|
||||
withV1ApiWrapper:
|
||||
({ handler }: { handler: any }) =>
|
||||
async (req: NextRequest, props: any) => {
|
||||
const result = await handler({ req, props });
|
||||
return result.response;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./lib/response", () => ({
|
||||
getResponseIdByDisplayId: vi.fn(),
|
||||
}));
|
||||
|
||||
describe("GET /api/v1/client/[environmentId]/displays/[displayId]/response", () => {
|
||||
const req = new NextRequest("http://localhost/api/v1/client/env/displays/display/response");
|
||||
const props = {
|
||||
params: Promise.resolve({
|
||||
environmentId: "env1234567890123456789012",
|
||||
displayId: "display1234567890123456789",
|
||||
}),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns the responseId when a linked response exists", async () => {
|
||||
vi.mocked(getResponseIdByDisplayId).mockResolvedValue({ responseId: "response123456789012345678" });
|
||||
|
||||
const response = await GET(req, props);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
await expect(response.json()).resolves.toEqual({
|
||||
data: {
|
||||
responseId: "response123456789012345678",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("returns null when the display exists without a response", async () => {
|
||||
vi.mocked(getResponseIdByDisplayId).mockResolvedValue({ responseId: null });
|
||||
|
||||
const response = await GET(req, props);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
await expect(response.json()).resolves.toEqual({
|
||||
data: {
|
||||
responseId: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("returns 404 when the display is missing for the environment", async () => {
|
||||
vi.mocked(getResponseIdByDisplayId).mockRejectedValue(
|
||||
new ResourceNotFoundError("Display", "display1234567890123456789")
|
||||
);
|
||||
|
||||
const response = await GET(req, props);
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { responses } from "@/app/lib/api/response";
|
||||
import { THandlerParams, withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
|
||||
import { getResponseIdByDisplayId } from "./lib/response";
|
||||
|
||||
export const OPTIONS = async (): Promise<Response> => {
|
||||
return responses.successResponse({}, true);
|
||||
};
|
||||
|
||||
export const GET = withV1ApiWrapper({
|
||||
handler: async ({
|
||||
req,
|
||||
props,
|
||||
}: THandlerParams<{ params: Promise<{ environmentId: string; displayId: string }> }>) => {
|
||||
const params = await props.params;
|
||||
|
||||
try {
|
||||
const response = await getResponseIdByDisplayId(params.environmentId, params.displayId);
|
||||
|
||||
return {
|
||||
response: responses.successResponse(response, true),
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ResourceNotFoundError) {
|
||||
return {
|
||||
response: responses.notFoundResponse("Display", params.displayId, true),
|
||||
};
|
||||
}
|
||||
|
||||
logger.error(
|
||||
{ error, url: req.url, environmentId: params.environmentId, displayId: params.displayId },
|
||||
"Error in GET /api/v1/client/[environmentId]/displays/[displayId]/response"
|
||||
);
|
||||
return {
|
||||
response: responses.internalServerErrorResponse("Something went wrong. Please try again."),
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -10,6 +10,8 @@ import { responses } from "@/app/lib/api/response";
|
||||
import { transformErrorToDetails } from "@/app/lib/api/validator";
|
||||
import { THandlerParams, withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
|
||||
import { sendToPipeline } from "@/app/lib/pipelines";
|
||||
import { ENCRYPTION_KEY } from "@/lib/constants";
|
||||
import { symmetricDecrypt } from "@/lib/crypto";
|
||||
import { getSurvey } from "@/lib/survey/service";
|
||||
import { getClientIpFromHeaders } from "@/lib/utils/client-ip";
|
||||
import { getOrganizationIdFromEnvironmentId } from "@/lib/utils/helper";
|
||||
@@ -123,17 +125,118 @@ export const POST = withV1ApiWrapper({
|
||||
}
|
||||
if (survey.environmentId !== environmentId) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Survey is part of another environment",
|
||||
{
|
||||
"survey.environmentId": survey.environmentId,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
response: responses.badRequestResponse("Survey does not belong to this environment", undefined, true),
|
||||
};
|
||||
}
|
||||
|
||||
if (survey.type === "link" && survey.singleUse?.enabled) {
|
||||
if (!responseInputData.singleUseId) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Missing single use id",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if (!responseInputData.meta?.url) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Missing or invalid URL in response metadata",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(responseInputData.meta.url);
|
||||
} catch (error) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Invalid URL in response metadata",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
error: error instanceof Error ? error.message : "Unknown error occurred",
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
const suId = url.searchParams.get("suId");
|
||||
if (!suId) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Missing single use id",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if (survey.singleUse.isEncrypted) {
|
||||
if (!ENCRYPTION_KEY) {
|
||||
logger.error({ url: req.url, surveyId: survey.id, environmentId }, "ENCRYPTION_KEY is not set");
|
||||
return {
|
||||
response: responses.internalServerErrorResponse("An unexpected error occurred.", true),
|
||||
};
|
||||
}
|
||||
|
||||
let decryptedSuId: string;
|
||||
try {
|
||||
decryptedSuId = symmetricDecrypt(suId, ENCRYPTION_KEY);
|
||||
} catch {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Invalid single use id",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if (decryptedSuId !== responseInputData.singleUseId) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Invalid single use id",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
} else if (responseInputData.singleUseId !== suId) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Invalid single use id",
|
||||
{
|
||||
surveyId: survey.id,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!validateFileUploads(responseInputData.data, survey.questions)) {
|
||||
return {
|
||||
response: responses.badRequestResponse("Invalid file upload response"),
|
||||
|
||||
@@ -75,11 +75,7 @@ export const POST = withV1ApiWrapper({
|
||||
|
||||
if (survey.environmentId !== environmentId) {
|
||||
return {
|
||||
response: responses.badRequestResponse(
|
||||
"Survey does not belong to the environment",
|
||||
{ surveyId, environmentId },
|
||||
true
|
||||
),
|
||||
response: responses.badRequestResponse("Survey does not belong to this environment", undefined, true),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
|
||||
import { fetchAirtableAuthToken } from "@/lib/airtable/service";
|
||||
import { AIRTABLE_CLIENT_ID, WEBAPP_URL } from "@/lib/constants";
|
||||
import { hasUserEnvironmentAccess } from "@/lib/environment/auth";
|
||||
import { createOrUpdateIntegration } from "@/lib/integration/service";
|
||||
import { createOrUpdateIntegration, getIntegrationByType } from "@/lib/integration/service";
|
||||
import { capturePostHogEvent } from "@/lib/posthog";
|
||||
import { getOrganizationIdFromEnvironmentId } from "@/lib/utils/helper";
|
||||
|
||||
@@ -78,12 +78,16 @@ export const GET = withV1ApiWrapper({
|
||||
}
|
||||
const email = await getEmail(key.access_token);
|
||||
|
||||
// Preserve existing integration data (survey-to-table mappings) when re-authorizing
|
||||
const existingIntegration = await getIntegrationByType(environmentId, "airtable");
|
||||
const existingData = existingIntegration?.config?.data ?? [];
|
||||
|
||||
const airtableIntegrationInput = {
|
||||
type: "airtable" as "airtable",
|
||||
environment: environmentId,
|
||||
config: {
|
||||
key,
|
||||
data: [],
|
||||
data: existingData,
|
||||
email,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as z from "zod";
|
||||
import { TIntegrationAirtable } from "@formbricks/types/integration/airtable";
|
||||
import { responses } from "@/app/lib/api/response";
|
||||
import { withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
|
||||
import { getTables } from "@/lib/airtable/service";
|
||||
import { getAirtableToken, getTables } from "@/lib/airtable/service";
|
||||
import { hasUserEnvironmentAccess } from "@/lib/environment/auth";
|
||||
import { getIntegrationByType } from "@/lib/integration/service";
|
||||
|
||||
@@ -36,7 +35,7 @@ export const GET = withV1ApiWrapper({
|
||||
};
|
||||
}
|
||||
|
||||
const integration = (await getIntegrationByType(environmentId, "airtable")) as TIntegrationAirtable;
|
||||
const integration = await getIntegrationByType(environmentId, "airtable");
|
||||
|
||||
if (!integration) {
|
||||
return {
|
||||
@@ -44,7 +43,12 @@ export const GET = withV1ApiWrapper({
|
||||
};
|
||||
}
|
||||
|
||||
const tables = await getTables(integration.config.key, baseId.data);
|
||||
// Use getAirtableToken to ensure the access token is refreshed if expired
|
||||
const freshAccessToken = await getAirtableToken(environmentId);
|
||||
const tables = await getTables(
|
||||
{ ...integration.config.key, access_token: freshAccessToken },
|
||||
baseId.data
|
||||
);
|
||||
return {
|
||||
response: responses.successResponse(tables),
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getSessionUser } from "@/app/api/v1/management/me/lib/utils";
|
||||
import { responses } from "@/app/lib/api/response";
|
||||
import { CONTROL_HASH } from "@/lib/constants";
|
||||
import { hashSha256, parseApiKeyV2, verifySecret } from "@/lib/crypto";
|
||||
import { publicUserSelect } from "@/lib/user/public-user";
|
||||
import { applyRateLimit } from "@/modules/core/rate-limit/helpers";
|
||||
import { rateLimitConfigs } from "@/modules/core/rate-limit/rate-limit-configs";
|
||||
|
||||
@@ -176,6 +177,7 @@ const handleSessionAuthentication = async () => {
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: sessionUser.id },
|
||||
select: publicUserSelect,
|
||||
});
|
||||
|
||||
return Response.json(user);
|
||||
|
||||
@@ -96,14 +96,7 @@ const validateSurvey = async (responseInput: TResponseInput, environmentId: stri
|
||||
}
|
||||
if (survey.environmentId !== environmentId) {
|
||||
return {
|
||||
error: responses.badRequestResponse(
|
||||
"Survey is part of another environment",
|
||||
{
|
||||
"survey.environmentId": survey.environmentId,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
),
|
||||
error: responses.badRequestResponse("Survey does not belong to this environment", undefined, true),
|
||||
};
|
||||
}
|
||||
return { survey };
|
||||
|
||||
@@ -1,47 +1,19 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { deleteSurvey } from "./surveys";
|
||||
|
||||
vi.mock("@/lib/utils/validate", () => ({
|
||||
validateInputs: vi.fn(),
|
||||
const { mockDeleteSharedSurvey } = vi.hoisted(() => ({
|
||||
mockDeleteSharedSurvey: vi.fn(),
|
||||
}));
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
prisma: {
|
||||
survey: {
|
||||
delete: vi.fn(),
|
||||
},
|
||||
segment: {
|
||||
delete: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
vi.mock("@formbricks/logger", () => ({
|
||||
logger: {
|
||||
error: vi.fn(),
|
||||
},
|
||||
|
||||
vi.mock("@/modules/survey/lib/surveys", () => ({
|
||||
deleteSurvey: mockDeleteSharedSurvey,
|
||||
}));
|
||||
|
||||
const surveyId = "clq5n7p1q0000m7z0h5p6g3r2";
|
||||
const environmentId = "clq5n7p1q0000m7z0h5p6g3r3";
|
||||
const segmentId = "clq5n7p1q0000m7z0h5p6g3r4";
|
||||
const actionClassId1 = "clq5n7p1q0000m7z0h5p6g3r5";
|
||||
const actionClassId2 = "clq5n7p1q0000m7z0h5p6g3r6";
|
||||
|
||||
const mockDeletedSurveyAppPrivateSegment = {
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
type: "app",
|
||||
segment: { id: segmentId, isPrivate: true },
|
||||
triggers: [{ actionClass: { id: actionClassId1 } }, { actionClass: { id: actionClassId2 } }],
|
||||
};
|
||||
|
||||
const mockDeletedSurveyLink = {
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
environmentId: "clq5n7p1q0000m7z0h5p6g3r3",
|
||||
type: "link",
|
||||
segment: null,
|
||||
triggers: [],
|
||||
@@ -56,66 +28,20 @@ describe("deleteSurvey", () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("should delete a link survey without a segment and revalidate caches", async () => {
|
||||
vi.mocked(prisma.survey.delete).mockResolvedValue(mockDeletedSurveyLink as any);
|
||||
test("delegates survey deletion to the shared service", async () => {
|
||||
mockDeleteSharedSurvey.mockResolvedValue(mockDeletedSurveyLink);
|
||||
|
||||
const deletedSurvey = await deleteSurvey(surveyId);
|
||||
|
||||
expect(validateInputs).toHaveBeenCalledWith([surveyId, expect.any(Object)]);
|
||||
expect(prisma.survey.delete).toHaveBeenCalledWith({
|
||||
where: { id: surveyId },
|
||||
include: {
|
||||
segment: true,
|
||||
triggers: { include: { actionClass: true } },
|
||||
},
|
||||
});
|
||||
expect(prisma.segment.delete).not.toHaveBeenCalled();
|
||||
|
||||
expect(mockDeleteSharedSurvey).toHaveBeenCalledWith(surveyId);
|
||||
expect(deletedSurvey).toEqual(mockDeletedSurveyLink);
|
||||
});
|
||||
|
||||
test("should handle PrismaClientKnownRequestError during survey deletion", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Record not found", {
|
||||
code: "P2025",
|
||||
clientVersion: "4.0.0",
|
||||
});
|
||||
vi.mocked(prisma.survey.delete).mockRejectedValue(prismaError);
|
||||
|
||||
await expect(deleteSurvey(surveyId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith({ error: prismaError, surveyId }, "Error deleting survey");
|
||||
expect(prisma.segment.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should handle PrismaClientKnownRequestError during segment deletion", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Foreign key constraint failed", {
|
||||
code: "P2003",
|
||||
clientVersion: "4.0.0",
|
||||
});
|
||||
vi.mocked(prisma.survey.delete).mockResolvedValue(mockDeletedSurveyAppPrivateSegment as any);
|
||||
vi.mocked(prisma.segment.delete).mockRejectedValue(prismaError);
|
||||
|
||||
await expect(deleteSurvey(surveyId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith({ error: prismaError, surveyId }, "Error deleting survey");
|
||||
expect(prisma.segment.delete).toHaveBeenCalledWith({ where: { id: segmentId } });
|
||||
});
|
||||
|
||||
test("should handle generic errors during deletion", async () => {
|
||||
test("rethrows shared delete service errors", async () => {
|
||||
const genericError = new Error("Something went wrong");
|
||||
vi.mocked(prisma.survey.delete).mockRejectedValue(genericError);
|
||||
mockDeleteSharedSurvey.mockRejectedValue(genericError);
|
||||
|
||||
await expect(deleteSurvey(surveyId)).rejects.toThrow(genericError);
|
||||
expect(logger.error).not.toHaveBeenCalled();
|
||||
expect(prisma.segment.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should throw validation error for invalid surveyId", async () => {
|
||||
const invalidSurveyId = "invalid-id";
|
||||
const validationError = new Error("Validation failed");
|
||||
vi.mocked(validateInputs).mockImplementation(() => {
|
||||
throw validationError;
|
||||
});
|
||||
|
||||
await expect(deleteSurvey(invalidSurveyId)).rejects.toThrow(validationError);
|
||||
expect(prisma.survey.delete).not.toHaveBeenCalled();
|
||||
expect(mockDeleteSharedSurvey).toHaveBeenCalledWith(surveyId);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,43 +1,3 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { deleteSurvey as deleteSharedSurvey } from "@/modules/survey/lib/surveys";
|
||||
|
||||
export const deleteSurvey = async (surveyId: string) => {
|
||||
validateInputs([surveyId, z.cuid2()]);
|
||||
|
||||
try {
|
||||
const deletedSurvey = await prisma.survey.delete({
|
||||
where: {
|
||||
id: surveyId,
|
||||
},
|
||||
include: {
|
||||
segment: true,
|
||||
triggers: {
|
||||
include: {
|
||||
actionClass: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (deletedSurvey.type === "app" && deletedSurvey.segment?.isPrivate) {
|
||||
await prisma.segment.delete({
|
||||
where: {
|
||||
id: deletedSurvey.segment.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return deletedSurvey;
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
logger.error({ error, surveyId }, "Error deleting survey");
|
||||
throw new DatabaseError(error.message);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
export const deleteSurvey = async (surveyId: string) => deleteSharedSurvey(surveyId);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { TAuthenticationApiKey } from "@formbricks/types/auth";
|
||||
import { ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { ZSurveyUpdateInput } from "@formbricks/types/surveys/types";
|
||||
import { handleErrorResponse } from "@/app/api/v1/auth";
|
||||
import { deleteSurvey } from "@/app/api/v1/management/surveys/[surveyId]/lib/surveys";
|
||||
@@ -70,6 +71,12 @@ export const GET = withV1ApiWrapper({
|
||||
response: responses.successResponse(resolveStorageUrlsInObject(result.survey)),
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ResourceNotFoundError) {
|
||||
return {
|
||||
response: responses.notFoundResponse("Survey", params.surveyId),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
response: handleErrorResponse(error),
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Prisma } from "@prisma/client";
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { TContactAttributes } from "@formbricks/types/contact-attribute";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { DatabaseError, ResourceNotFoundError, UniqueConstraintError } from "@formbricks/types/errors";
|
||||
import { TResponseWithQuotaFull, TSurveyQuota } from "@formbricks/types/quota";
|
||||
import { TResponse } from "@formbricks/types/responses";
|
||||
import { TTag } from "@formbricks/types/tags";
|
||||
@@ -175,10 +175,34 @@ describe("createResponse V2", () => {
|
||||
).rejects.toThrow(ResourceNotFoundError);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma known request error", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Test Prisma Error", {
|
||||
test("should throw UniqueConstraintError on P2002 with singleUseId target", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Unique constraint failed", {
|
||||
code: "P2002",
|
||||
clientVersion: "test",
|
||||
meta: { target: ["surveyId", "singleUseId"] },
|
||||
});
|
||||
vi.mocked(mockTx.response.create).mockRejectedValue(prismaError);
|
||||
await expect(
|
||||
createResponse(mockResponseInput, mockTx as unknown as Prisma.TransactionClient)
|
||||
).rejects.toThrow(UniqueConstraintError);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on P2002 without singleUseId target", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Unique constraint failed", {
|
||||
code: "P2002",
|
||||
clientVersion: "test",
|
||||
meta: { target: ["displayId"] },
|
||||
});
|
||||
vi.mocked(mockTx.response.create).mockRejectedValue(prismaError);
|
||||
await expect(
|
||||
createResponse(mockResponseInput, mockTx as unknown as Prisma.TransactionClient)
|
||||
).rejects.toThrow(DatabaseError);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on non-P2002 Prisma known request error", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Test Prisma Error", {
|
||||
code: "P2025",
|
||||
clientVersion: "test",
|
||||
});
|
||||
vi.mocked(mockTx.response.create).mockRejectedValue(prismaError);
|
||||
await expect(
|
||||
|
||||
@@ -2,7 +2,7 @@ import "server-only";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { TContactAttributes } from "@formbricks/types/contact-attribute";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { DatabaseError, ResourceNotFoundError, UniqueConstraintError } from "@formbricks/types/errors";
|
||||
import { TResponseWithQuotaFull } from "@formbricks/types/quota";
|
||||
import { TResponse, ZResponseInput } from "@formbricks/types/responses";
|
||||
import { TTag } from "@formbricks/types/tags";
|
||||
@@ -129,6 +129,13 @@ export const createResponse = async (
|
||||
return response;
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
if (error.code === "P2002") {
|
||||
const target = (error.meta?.target as string[]) ?? [];
|
||||
if (target?.includes("singleUseId")) {
|
||||
throw new UniqueConstraintError("Response already submitted for this single-use link");
|
||||
}
|
||||
}
|
||||
|
||||
throw new DatabaseError(error.message);
|
||||
}
|
||||
|
||||
|
||||
@@ -124,11 +124,8 @@ describe("checkSurveyValidity", () => {
|
||||
expect(result).toBeInstanceOf(Response);
|
||||
expect(result?.status).toBe(400);
|
||||
expect(responses.badRequestResponse).toHaveBeenCalledWith(
|
||||
"Survey is part of another environment",
|
||||
{
|
||||
"survey.environmentId": "env-2",
|
||||
environmentId: "env-1",
|
||||
},
|
||||
"Survey does not belong to this environment",
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
@@ -17,14 +17,7 @@ export const checkSurveyValidity = async (
|
||||
responseInput: TResponseInputV2
|
||||
): Promise<Response | null> => {
|
||||
if (survey.environmentId !== environmentId) {
|
||||
return responses.badRequestResponse(
|
||||
"Survey is part of another environment",
|
||||
{
|
||||
"survey.environmentId": survey.environmentId,
|
||||
environmentId,
|
||||
},
|
||||
true
|
||||
);
|
||||
return responses.badRequestResponse("Survey does not belong to this environment", undefined, true);
|
||||
}
|
||||
|
||||
if (survey.type === "link" && survey.singleUse?.enabled) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UAParser } from "ua-parser-js";
|
||||
import { ZEnvironmentId } from "@formbricks/types/environment";
|
||||
import { InvalidInputError } from "@formbricks/types/errors";
|
||||
import { InvalidInputError, UniqueConstraintError } from "@formbricks/types/errors";
|
||||
import { TResponseWithQuotaFull } from "@formbricks/types/quota";
|
||||
import { checkSurveyValidity } from "@/app/api/v2/client/[environmentId]/responses/lib/utils";
|
||||
import { reportApiError } from "@/app/lib/api/api-error-reporter";
|
||||
@@ -177,6 +177,10 @@ const createResponseForRequest = async ({
|
||||
return responses.badRequestResponse(error.message, undefined, true);
|
||||
}
|
||||
|
||||
if (error instanceof UniqueConstraintError) {
|
||||
return responses.conflictResponse(error.message, undefined, true);
|
||||
}
|
||||
|
||||
const response = getUnexpectedPublicErrorResponse();
|
||||
reportApiError({
|
||||
request,
|
||||
|
||||
@@ -9,6 +9,22 @@ const { mockAuthenticateRequest, mockGetServerSession } = vi.hoisted(() => ({
|
||||
mockGetServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
const { mockQueueAuditEvent, mockBuildAuditLogBaseObject } = vi.hoisted(() => ({
|
||||
mockQueueAuditEvent: vi.fn().mockImplementation(async () => undefined),
|
||||
mockBuildAuditLogBaseObject: vi.fn((action: string, targetType: string, apiUrl: string) => ({
|
||||
action,
|
||||
targetType,
|
||||
userId: "unknown",
|
||||
targetId: "unknown",
|
||||
organizationId: "unknown",
|
||||
status: "failure",
|
||||
oldObject: undefined,
|
||||
newObject: undefined,
|
||||
userType: "api",
|
||||
apiUrl,
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("next-auth", () => ({
|
||||
getServerSession: mockGetServerSession,
|
||||
}));
|
||||
@@ -25,6 +41,14 @@ vi.mock("@/modules/core/rate-limit/helpers", () => ({
|
||||
applyRateLimit: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
vi.mock("@/modules/ee/audit-logs/lib/handler", () => ({
|
||||
queueAuditEvent: mockQueueAuditEvent,
|
||||
}));
|
||||
|
||||
vi.mock("@/app/lib/api/with-api-logging", () => ({
|
||||
buildAuditLogBaseObject: mockBuildAuditLogBaseObject,
|
||||
}));
|
||||
|
||||
vi.mock("@formbricks/logger", () => ({
|
||||
logger: {
|
||||
withContext: vi.fn(() => ({
|
||||
@@ -45,6 +69,114 @@ describe("withV3ApiWrapper", () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("passes an audit log to the handler and queues success after the response", async () => {
|
||||
const { queueAuditEvent } = await import("@/modules/ee/audit-logs/lib/handler");
|
||||
|
||||
mockGetServerSession.mockResolvedValue({
|
||||
user: { id: "user_1", name: "Test", email: "t@example.com" },
|
||||
expires: "2026-01-01",
|
||||
});
|
||||
|
||||
const handler = vi.fn(async ({ auditLog }) => {
|
||||
expect(auditLog).toEqual(
|
||||
expect.objectContaining({
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
userId: "user_1",
|
||||
userType: "user",
|
||||
status: "failure",
|
||||
})
|
||||
);
|
||||
|
||||
if (auditLog) {
|
||||
auditLog.targetId = "survey_1";
|
||||
auditLog.organizationId = "org_1";
|
||||
auditLog.oldObject = { id: "survey_1" };
|
||||
}
|
||||
|
||||
return Response.json({ ok: true });
|
||||
});
|
||||
|
||||
const wrapped = withV3ApiWrapper({
|
||||
auth: "both",
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
handler,
|
||||
});
|
||||
|
||||
const response = await wrapped(
|
||||
new NextRequest("http://localhost/api/v3/surveys/survey_1", {
|
||||
method: "DELETE",
|
||||
headers: { "x-request-id": "req-audit" },
|
||||
}),
|
||||
{} as never
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(queueAuditEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
targetId: "survey_1",
|
||||
organizationId: "org_1",
|
||||
userId: "user_1",
|
||||
userType: "user",
|
||||
status: "success",
|
||||
oldObject: { id: "survey_1" },
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("queues a failure audit log when the handler returns a non-ok response", async () => {
|
||||
const { queueAuditEvent } = await import("@/modules/ee/audit-logs/lib/handler");
|
||||
|
||||
mockAuthenticateRequest.mockResolvedValue({
|
||||
type: "apiKey",
|
||||
apiKeyId: "key_1",
|
||||
organizationId: "org_1",
|
||||
organizationAccess: { accessControl: { read: true, write: true } },
|
||||
environmentPermissions: [],
|
||||
});
|
||||
|
||||
const wrapped = withV3ApiWrapper({
|
||||
auth: "both",
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
handler: async ({ auditLog }) => {
|
||||
if (auditLog) {
|
||||
auditLog.targetId = "survey_2";
|
||||
}
|
||||
|
||||
return new Response("forbidden", { status: 403 });
|
||||
},
|
||||
});
|
||||
|
||||
const response = await wrapped(
|
||||
new NextRequest("http://localhost/api/v3/surveys/survey_2", {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"x-request-id": "req-failure-audit",
|
||||
"x-api-key": "fbk_test",
|
||||
},
|
||||
}),
|
||||
{} as never
|
||||
);
|
||||
|
||||
expect(response.status).toBe(403);
|
||||
expect(queueAuditEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
targetId: "survey_2",
|
||||
organizationId: "org_1",
|
||||
userId: "key_1",
|
||||
userType: "api",
|
||||
status: "failure",
|
||||
eventId: "req-failure-audit",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("uses session auth first in both mode and injects request id into plain responses", async () => {
|
||||
const { applyRateLimit } = await import("@/modules/core/rate-limit/helpers");
|
||||
mockGetServerSession.mockResolvedValue({
|
||||
|
||||
@@ -4,10 +4,13 @@ import { z } from "zod";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { TooManyRequestsError } from "@formbricks/types/errors";
|
||||
import { authenticateRequest } from "@/app/api/v1/auth";
|
||||
import { buildAuditLogBaseObject } from "@/app/lib/api/with-api-logging";
|
||||
import { authOptions } from "@/modules/auth/lib/authOptions";
|
||||
import { applyRateLimit } from "@/modules/core/rate-limit/helpers";
|
||||
import { rateLimitConfigs } from "@/modules/core/rate-limit/rate-limit-configs";
|
||||
import type { TRateLimitConfig } from "@/modules/core/rate-limit/types/rate-limit";
|
||||
import { queueAuditEvent } from "@/modules/ee/audit-logs/lib/handler";
|
||||
import { TAuditAction, TAuditTarget } from "@/modules/ee/audit-logs/types/audit-log";
|
||||
import {
|
||||
type InvalidParam,
|
||||
problemBadRequest,
|
||||
@@ -15,7 +18,7 @@ import {
|
||||
problemTooManyRequests,
|
||||
problemUnauthorized,
|
||||
} from "./response";
|
||||
import type { TV3Authentication } from "./types";
|
||||
import type { TV3AuditLog, TV3Authentication } from "./types";
|
||||
|
||||
type TV3Schema = z.ZodTypeAny;
|
||||
type MaybePromise<T> = T | Promise<T>;
|
||||
@@ -38,6 +41,7 @@ export type TV3HandlerParams<TParsedInput = Record<string, never>, TProps = unkn
|
||||
req: NextRequest;
|
||||
props: TProps;
|
||||
authentication: TV3Authentication;
|
||||
auditLog?: TV3AuditLog;
|
||||
parsedInput: TParsedInput;
|
||||
requestId: string;
|
||||
instance: string;
|
||||
@@ -48,6 +52,8 @@ export type TWithV3ApiWrapperParams<S extends TV3Schemas | undefined, TProps = u
|
||||
schemas?: S;
|
||||
rateLimit?: boolean;
|
||||
customRateLimitConfig?: TRateLimitConfig;
|
||||
action?: TAuditAction;
|
||||
targetType?: TAuditTarget;
|
||||
handler: (params: TV3HandlerParams<TV3ParsedInput<S>, TProps>) => MaybePromise<Response>;
|
||||
};
|
||||
|
||||
@@ -293,10 +299,61 @@ async function applyV3RateLimitOrRespond(params: {
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildV3AuditLog(
|
||||
authentication: TV3Authentication,
|
||||
action?: TAuditAction,
|
||||
targetType?: TAuditTarget,
|
||||
apiUrl?: string
|
||||
): TV3AuditLog | undefined {
|
||||
if (!authentication || !action || !targetType || !apiUrl) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const auditLog = buildAuditLogBaseObject(action, targetType, apiUrl);
|
||||
|
||||
if ("user" in authentication && authentication.user?.id) {
|
||||
auditLog.userId = authentication.user.id;
|
||||
auditLog.userType = "user";
|
||||
} else if ("apiKeyId" in authentication) {
|
||||
auditLog.userId = authentication.apiKeyId;
|
||||
auditLog.userType = "api";
|
||||
auditLog.organizationId = authentication.organizationId;
|
||||
}
|
||||
|
||||
return auditLog;
|
||||
}
|
||||
|
||||
async function queueV3AuditLog(
|
||||
auditLog: TV3AuditLog | undefined,
|
||||
requestId: string,
|
||||
log: ReturnType<typeof logger.withContext>
|
||||
): Promise<void> {
|
||||
if (!auditLog) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await queueAuditEvent({
|
||||
...auditLog,
|
||||
...(auditLog.status === "failure" ? { eventId: auditLog.eventId ?? requestId } : {}),
|
||||
});
|
||||
} catch (error) {
|
||||
log.error({ error }, "Failed to queue V3 audit event");
|
||||
}
|
||||
}
|
||||
|
||||
export const withV3ApiWrapper = <S extends TV3Schemas | undefined, TProps = unknown>(
|
||||
params: TWithV3ApiWrapperParams<S, TProps>
|
||||
): ((req: NextRequest, props: TProps) => Promise<Response>) => {
|
||||
const { auth = "both", schemas, rateLimit = true, customRateLimitConfig, handler } = params;
|
||||
const {
|
||||
auth = "both",
|
||||
schemas,
|
||||
rateLimit = true,
|
||||
customRateLimitConfig,
|
||||
handler,
|
||||
action,
|
||||
targetType,
|
||||
} = params;
|
||||
|
||||
return async (req: NextRequest, props: TProps): Promise<Response> => {
|
||||
const requestId = req.headers.get("x-request-id") ?? crypto.randomUUID();
|
||||
@@ -306,6 +363,7 @@ export const withV3ApiWrapper = <S extends TV3Schemas | undefined, TProps = unkn
|
||||
method: req.method,
|
||||
path: instance,
|
||||
});
|
||||
let auditLog: TV3AuditLog | undefined;
|
||||
|
||||
try {
|
||||
const authResult = await authenticateV3RequestOrRespond(req, auth, requestId, instance);
|
||||
@@ -331,17 +389,33 @@ export const withV3ApiWrapper = <S extends TV3Schemas | undefined, TProps = unkn
|
||||
return rateLimitResponse;
|
||||
}
|
||||
|
||||
auditLog = buildV3AuditLog(authResult.authentication, action, targetType, req.url);
|
||||
|
||||
const response = await handler({
|
||||
req,
|
||||
props,
|
||||
authentication: authResult.authentication,
|
||||
auditLog,
|
||||
parsedInput: parsedInputResult.parsedInput,
|
||||
requestId,
|
||||
instance,
|
||||
});
|
||||
|
||||
if (auditLog) {
|
||||
if (response.ok) {
|
||||
auditLog.status = "success";
|
||||
} else {
|
||||
auditLog.eventId = requestId;
|
||||
}
|
||||
}
|
||||
|
||||
await queueV3AuditLog(auditLog, requestId, log);
|
||||
return ensureRequestIdHeader(response, requestId);
|
||||
} catch (error) {
|
||||
if (auditLog) {
|
||||
auditLog.eventId = requestId;
|
||||
await queueV3AuditLog(auditLog, requestId, log);
|
||||
}
|
||||
log.error({ error, statusCode: 500 }, "V3 API unexpected error");
|
||||
return problemInternalError(requestId, "An unexpected error occurred.", instance);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
problemTooManyRequests,
|
||||
problemUnauthorized,
|
||||
successListResponse,
|
||||
successResponse,
|
||||
} from "./response";
|
||||
|
||||
describe("v3 problem responses", () => {
|
||||
@@ -93,3 +94,27 @@ describe("successListResponse", () => {
|
||||
expect(res.headers.get("Cache-Control")).toBe("private, max-age=0");
|
||||
});
|
||||
});
|
||||
|
||||
describe("successResponse", () => {
|
||||
test("wraps the payload in a data envelope", async () => {
|
||||
const res = successResponse({ id: "survey_1" }, { requestId: "req-success" });
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get("X-Request-Id")).toBe("req-success");
|
||||
expect(res.headers.get("Cache-Control")).toContain("no-store");
|
||||
expect(await res.json()).toEqual({
|
||||
data: { id: "survey_1" },
|
||||
});
|
||||
});
|
||||
|
||||
test("allows custom status and cache headers", async () => {
|
||||
const res = successResponse(
|
||||
{ ok: true },
|
||||
{
|
||||
cache: "private, max-age=60",
|
||||
status: 202,
|
||||
}
|
||||
);
|
||||
expect(res.status).toBe(202);
|
||||
expect(res.headers.get("Cache-Control")).toBe("private, max-age=60");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -147,3 +147,27 @@ export function successListResponse<T, TMeta extends Record<string, unknown>>(
|
||||
}
|
||||
return Response.json({ data, meta }, { status: 200, headers });
|
||||
}
|
||||
|
||||
export function successResponse<T>(
|
||||
data: T,
|
||||
options?: { requestId?: string; cache?: string; status?: number }
|
||||
): Response {
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
"Cache-Control": options?.cache ?? CACHE_NO_STORE,
|
||||
};
|
||||
|
||||
if (options?.requestId) {
|
||||
headers["X-Request-Id"] = options.requestId;
|
||||
}
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
data,
|
||||
},
|
||||
{
|
||||
status: options?.status ?? 200,
|
||||
headers,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { Session } from "next-auth";
|
||||
import type { TAuthenticationApiKey } from "@formbricks/types/auth";
|
||||
import type { TApiAuditLog } from "@/app/lib/api/with-api-logging";
|
||||
|
||||
export type TV3Authentication = TAuthenticationApiKey | Session | null;
|
||||
export type TV3AuditLog = TApiAuditLog;
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
import { ApiKeyPermission, EnvironmentType } from "@prisma/client";
|
||||
import { NextRequest } from "next/server";
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { requireV3WorkspaceAccess } from "@/app/api/v3/lib/auth";
|
||||
import { getSurvey } from "@/lib/survey/service";
|
||||
import { deleteSurvey } from "@/modules/survey/lib/surveys";
|
||||
import { DELETE } from "./route";
|
||||
|
||||
const { mockAuthenticateRequest } = vi.hoisted(() => ({
|
||||
mockAuthenticateRequest: vi.fn(),
|
||||
}));
|
||||
|
||||
const { mockQueueAuditEvent, mockBuildAuditLogBaseObject } = vi.hoisted(() => ({
|
||||
mockQueueAuditEvent: vi.fn().mockImplementation(async () => undefined),
|
||||
mockBuildAuditLogBaseObject: vi.fn((action: string, targetType: string, apiUrl: string) => ({
|
||||
action,
|
||||
targetType,
|
||||
userId: "unknown",
|
||||
targetId: "unknown",
|
||||
organizationId: "unknown",
|
||||
status: "failure",
|
||||
oldObject: undefined,
|
||||
newObject: undefined,
|
||||
userType: "api",
|
||||
apiUrl,
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("next-auth", () => ({
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/app/api/v1/auth", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("@/app/api/v1/auth")>();
|
||||
return { ...actual, authenticateRequest: mockAuthenticateRequest };
|
||||
});
|
||||
|
||||
vi.mock("@/modules/core/rate-limit/helpers", () => ({
|
||||
applyRateLimit: vi.fn().mockResolvedValue(undefined),
|
||||
applyIPRateLimit: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/constants", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("@/lib/constants")>();
|
||||
return { ...actual, AUDIT_LOG_ENABLED: false };
|
||||
});
|
||||
|
||||
vi.mock("@/app/api/v3/lib/auth", () => ({
|
||||
requireV3WorkspaceAccess: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/survey/service", () => ({
|
||||
getSurvey: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/modules/survey/lib/surveys", () => ({
|
||||
deleteSurvey: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/modules/ee/audit-logs/lib/handler", () => ({
|
||||
queueAuditEvent: mockQueueAuditEvent,
|
||||
}));
|
||||
|
||||
vi.mock("@/app/lib/api/with-api-logging", () => ({
|
||||
buildAuditLogBaseObject: mockBuildAuditLogBaseObject,
|
||||
}));
|
||||
|
||||
vi.mock("@formbricks/logger", () => ({
|
||||
logger: {
|
||||
withContext: vi.fn(() => ({
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
const getServerSession = vi.mocked((await import("next-auth")).getServerSession);
|
||||
const queueAuditEvent = vi.mocked((await import("@/modules/ee/audit-logs/lib/handler")).queueAuditEvent);
|
||||
|
||||
const surveyId = "clxx1234567890123456789012";
|
||||
const environmentId = "clzz9876543210987654321098";
|
||||
|
||||
function createRequest(url: string, requestId?: string, extraHeaders?: Record<string, string>): NextRequest {
|
||||
const headers: Record<string, string> = { ...extraHeaders };
|
||||
if (requestId) {
|
||||
headers["x-request-id"] = requestId;
|
||||
}
|
||||
|
||||
return new NextRequest(url, {
|
||||
method: "DELETE",
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
const apiKeyAuth = {
|
||||
type: "apiKey" as const,
|
||||
apiKeyId: "key_1",
|
||||
organizationId: "org_1",
|
||||
organizationAccess: {
|
||||
accessControl: { read: true, write: true },
|
||||
},
|
||||
environmentPermissions: [
|
||||
{
|
||||
environmentId,
|
||||
environmentType: EnvironmentType.development,
|
||||
projectId: "proj_1",
|
||||
projectName: "P",
|
||||
permission: ApiKeyPermission.write,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe("DELETE /api/v3/surveys/[surveyId]", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
getServerSession.mockResolvedValue({
|
||||
user: { id: "user_1", name: "User", email: "u@example.com" },
|
||||
expires: "2026-01-01",
|
||||
} as any);
|
||||
mockAuthenticateRequest.mockResolvedValue(null);
|
||||
vi.mocked(getSurvey).mockResolvedValue({
|
||||
id: surveyId,
|
||||
name: "Delete me",
|
||||
environmentId,
|
||||
type: "link",
|
||||
status: "draft",
|
||||
createdAt: new Date("2026-04-15T10:00:00.000Z"),
|
||||
updatedAt: new Date("2026-04-15T10:00:00.000Z"),
|
||||
responseCount: 0,
|
||||
creator: { name: "User" },
|
||||
singleUse: null,
|
||||
} as any);
|
||||
vi.mocked(deleteSurvey).mockResolvedValue({
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
type: "link",
|
||||
segment: null,
|
||||
triggers: [],
|
||||
} as any);
|
||||
vi.mocked(requireV3WorkspaceAccess).mockResolvedValue({
|
||||
environmentId,
|
||||
projectId: "proj_1",
|
||||
organizationId: "org_1",
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns 401 when no session and no API key", async () => {
|
||||
getServerSession.mockResolvedValue(null);
|
||||
mockAuthenticateRequest.mockResolvedValue(null);
|
||||
|
||||
const res = await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(401);
|
||||
expect(vi.mocked(getSurvey)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("returns 200 with session auth and deletes the survey", async () => {
|
||||
const res = await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`, "req-delete"), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(requireV3WorkspaceAccess).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ user: expect.any(Object) }),
|
||||
environmentId,
|
||||
"readWrite",
|
||||
"req-delete",
|
||||
`/api/v3/surveys/${surveyId}`
|
||||
);
|
||||
expect(deleteSurvey).toHaveBeenCalledWith(surveyId);
|
||||
expect(await res.json()).toEqual({
|
||||
data: {
|
||||
id: surveyId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("returns 200 with x-api-key when the key can delete in the survey workspace", async () => {
|
||||
getServerSession.mockResolvedValue(null);
|
||||
mockAuthenticateRequest.mockResolvedValue(apiKeyAuth as any);
|
||||
|
||||
const res = await DELETE(
|
||||
createRequest(`http://localhost/api/v3/surveys/${surveyId}`, "req-api-key", {
|
||||
"x-api-key": "fbk_test",
|
||||
}),
|
||||
{
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never
|
||||
);
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(requireV3WorkspaceAccess).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ apiKeyId: "key_1" }),
|
||||
environmentId,
|
||||
"readWrite",
|
||||
"req-api-key",
|
||||
`/api/v3/surveys/${surveyId}`
|
||||
);
|
||||
});
|
||||
|
||||
test("returns 400 when surveyId is invalid", async () => {
|
||||
const res = await DELETE(createRequest("http://localhost/api/v3/surveys/not-a-cuid"), {
|
||||
params: Promise.resolve({ surveyId: "not-a-cuid" }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(vi.mocked(getSurvey)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("returns 403 when the survey does not exist", async () => {
|
||||
vi.mocked(getSurvey).mockResolvedValueOnce(null);
|
||||
|
||||
const res = await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(403);
|
||||
expect(deleteSurvey).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("returns 403 when the user lacks readWrite workspace access", async () => {
|
||||
vi.mocked(requireV3WorkspaceAccess).mockResolvedValueOnce(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
title: "Forbidden",
|
||||
status: 403,
|
||||
detail: "You are not authorized to access this resource",
|
||||
requestId: "req-forbidden",
|
||||
}),
|
||||
{ status: 403, headers: { "Content-Type": "application/problem+json" } }
|
||||
)
|
||||
);
|
||||
|
||||
const res = await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`, "req-forbidden"), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(403);
|
||||
expect(deleteSurvey).not.toHaveBeenCalled();
|
||||
expect(queueAuditEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
targetId: "unknown",
|
||||
organizationId: "unknown",
|
||||
userId: "user_1",
|
||||
userType: "user",
|
||||
status: "failure",
|
||||
oldObject: undefined,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("returns 500 when survey deletion fails", async () => {
|
||||
vi.mocked(deleteSurvey).mockRejectedValueOnce(new DatabaseError("db down"));
|
||||
|
||||
const res = await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`, "req-db"), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(500);
|
||||
const body = await res.json();
|
||||
expect(body.code).toBe("internal_server_error");
|
||||
});
|
||||
|
||||
test("returns 403 when the survey is deleted after authorization succeeds", async () => {
|
||||
vi.mocked(deleteSurvey).mockRejectedValueOnce(new ResourceNotFoundError("Survey", surveyId));
|
||||
|
||||
const res = await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`, "req-race"), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(res.status).toBe(403);
|
||||
const body = await res.json();
|
||||
expect(body.code).toBe("forbidden");
|
||||
expect(queueAuditEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
targetId: surveyId,
|
||||
organizationId: "org_1",
|
||||
userId: "user_1",
|
||||
userType: "user",
|
||||
status: "failure",
|
||||
oldObject: expect.objectContaining({
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("queues an audit log with target, actor, organization, and old object", async () => {
|
||||
await DELETE(createRequest(`http://localhost/api/v3/surveys/${surveyId}`, "req-audit"), {
|
||||
params: Promise.resolve({ surveyId }),
|
||||
} as never);
|
||||
|
||||
expect(queueAuditEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
targetId: surveyId,
|
||||
organizationId: "org_1",
|
||||
userId: "user_1",
|
||||
userType: "user",
|
||||
status: "success",
|
||||
oldObject: expect.objectContaining({
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
import { z } from "zod";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { withV3ApiWrapper } from "@/app/api/v3/lib/api-wrapper";
|
||||
import { requireV3WorkspaceAccess } from "@/app/api/v3/lib/auth";
|
||||
import { problemForbidden, problemInternalError, successResponse } from "@/app/api/v3/lib/response";
|
||||
import { getSurvey } from "@/lib/survey/service";
|
||||
import { deleteSurvey } from "@/modules/survey/lib/surveys";
|
||||
|
||||
export const DELETE = withV3ApiWrapper({
|
||||
auth: "both",
|
||||
action: "deleted",
|
||||
targetType: "survey",
|
||||
schemas: {
|
||||
params: z.object({
|
||||
surveyId: z.cuid2(),
|
||||
}),
|
||||
},
|
||||
handler: async ({ parsedInput, authentication, requestId, instance, auditLog }) => {
|
||||
const surveyId = parsedInput.params.surveyId;
|
||||
const log = logger.withContext({ requestId, surveyId });
|
||||
|
||||
try {
|
||||
const survey = await getSurvey(surveyId);
|
||||
|
||||
if (!survey) {
|
||||
log.warn({ statusCode: 403 }, "Survey not found or not accessible");
|
||||
return problemForbidden(requestId, "You are not authorized to access this resource", instance);
|
||||
}
|
||||
|
||||
const authResult = await requireV3WorkspaceAccess(
|
||||
authentication,
|
||||
survey.environmentId,
|
||||
"readWrite",
|
||||
requestId,
|
||||
instance
|
||||
);
|
||||
|
||||
if (authResult instanceof Response) {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
if (auditLog) {
|
||||
auditLog.targetId = survey.id;
|
||||
auditLog.organizationId = authResult.organizationId;
|
||||
auditLog.oldObject = survey;
|
||||
}
|
||||
|
||||
const deletedSurvey = await deleteSurvey(surveyId);
|
||||
|
||||
return successResponse(
|
||||
{
|
||||
id: deletedSurvey.id,
|
||||
},
|
||||
{ requestId }
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof ResourceNotFoundError) {
|
||||
log.warn({ errorCode: error.name, statusCode: 403 }, "Survey not found or not accessible");
|
||||
return problemForbidden(requestId, "You are not authorized to access this resource", instance);
|
||||
}
|
||||
|
||||
if (error instanceof DatabaseError) {
|
||||
log.error({ error, statusCode: 500 }, "Database error");
|
||||
return problemInternalError(requestId, "An unexpected error occurred.", instance);
|
||||
}
|
||||
|
||||
log.error({ error, statusCode: 500 }, "V3 survey delete unexpected error");
|
||||
return problemInternalError(requestId, "An unexpected error occurred.", instance);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -321,11 +321,11 @@ describe("GET /api/v3/surveys", () => {
|
||||
const res = await GET(req, {} as any);
|
||||
const body = await res.json();
|
||||
expect(body.data[0]).not.toHaveProperty("blocks");
|
||||
expect(body.data[0]).not.toHaveProperty("singleUse");
|
||||
expect(body.data[0]).not.toHaveProperty("_count");
|
||||
expect(body.data[0]).not.toHaveProperty("environmentId");
|
||||
expect(body.data[0].id).toBe("s1");
|
||||
expect(body.data[0].workspaceId).toBe("env_1");
|
||||
expect(body.data[0].singleUse).toBeNull();
|
||||
});
|
||||
|
||||
test("returns 403 when getSurveyListPage throws ResourceNotFoundError", async () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { TSurvey } from "@/modules/survey/list/types/surveys";
|
||||
|
||||
export type TV3SurveyListItem = Omit<TSurvey, "environmentId" | "singleUse"> & {
|
||||
export type TV3SurveyListItem = Omit<TSurvey, "environmentId"> & {
|
||||
workspaceId: string;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ export type TV3SurveyListItem = Omit<TSurvey, "environmentId" | "singleUse"> & {
|
||||
* Internally surveys are still scoped by environmentId; externally v3 exposes workspaceId.
|
||||
*/
|
||||
export function serializeV3SurveyListItem(survey: TSurvey): TV3SurveyListItem {
|
||||
const { environmentId, singleUse: _omitSingleUse, ...rest } = survey;
|
||||
const { environmentId, ...rest } = survey;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
|
||||
@@ -339,6 +339,56 @@ describe("API Response Utilities", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("conflictResponse", () => {
|
||||
test("should return a conflict response", () => {
|
||||
const message = "Resource already exists";
|
||||
const details = { field: "singleUseId" };
|
||||
const response = responses.conflictResponse(message, details);
|
||||
|
||||
expect(response.status).toBe(409);
|
||||
|
||||
return response.json().then((body) => {
|
||||
expect(body).toEqual({
|
||||
code: "conflict",
|
||||
message,
|
||||
details,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle undefined details", () => {
|
||||
const message = "Resource already exists";
|
||||
const response = responses.conflictResponse(message);
|
||||
|
||||
expect(response.status).toBe(409);
|
||||
|
||||
return response.json().then((body) => {
|
||||
expect(body).toEqual({
|
||||
code: "conflict",
|
||||
message,
|
||||
details: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("should include CORS headers when cors is true", () => {
|
||||
const message = "Resource already exists";
|
||||
const response = responses.conflictResponse(message, undefined, true);
|
||||
|
||||
expect(response.headers.get("Access-Control-Allow-Origin")).toBe("*");
|
||||
expect(response.headers.get("Access-Control-Allow-Methods")).toBe("GET, POST, PUT, DELETE, OPTIONS");
|
||||
expect(response.headers.get("Access-Control-Allow-Headers")).toBe("Content-Type, Authorization");
|
||||
});
|
||||
|
||||
test("should use custom cache control header when provided", () => {
|
||||
const message = "Resource already exists";
|
||||
const customCache = "no-cache";
|
||||
const response = responses.conflictResponse(message, undefined, false, customCache);
|
||||
|
||||
expect(response.headers.get("Cache-Control")).toBe(customCache);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tooManyRequestsResponse", () => {
|
||||
test("should return a too many requests response", () => {
|
||||
const message = "Rate limit exceeded";
|
||||
|
||||
@@ -16,7 +16,8 @@ interface ApiErrorResponse {
|
||||
| "method_not_allowed"
|
||||
| "not_authenticated"
|
||||
| "forbidden"
|
||||
| "too_many_requests";
|
||||
| "too_many_requests"
|
||||
| "conflict";
|
||||
message: string;
|
||||
details: {
|
||||
[key: string]: string | string[] | number | number[] | boolean | boolean[];
|
||||
@@ -236,6 +237,30 @@ const internalServerErrorResponse = (
|
||||
);
|
||||
};
|
||||
|
||||
const conflictResponse = (
|
||||
message: string,
|
||||
details?: { [key: string]: string },
|
||||
cors: boolean = false,
|
||||
cache: string = "private, no-store"
|
||||
) => {
|
||||
const headers = {
|
||||
...(cors && corsHeaders),
|
||||
"Cache-Control": cache,
|
||||
};
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
code: "conflict",
|
||||
message,
|
||||
details: details || {},
|
||||
} as ApiErrorResponse,
|
||||
{
|
||||
status: 409,
|
||||
headers,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const tooManyRequestsResponse = (
|
||||
message: string,
|
||||
cors: boolean = false,
|
||||
@@ -270,4 +295,5 @@ export const responses = {
|
||||
successResponse,
|
||||
tooManyRequestsResponse,
|
||||
forbiddenResponse,
|
||||
conflictResponse,
|
||||
};
|
||||
|
||||
@@ -971,13 +971,13 @@ const improveTrialConversion = (t: TFunction): TTemplate => {
|
||||
elements: [
|
||||
buildOpenTextElement({
|
||||
id: reusableElementIds[2],
|
||||
headline: t("templates.improve_trial_conversion_question_2_headline"),
|
||||
headline: t("templates.improve_trial_conversion_question_3_headline"),
|
||||
required: true,
|
||||
inputType: "text",
|
||||
}),
|
||||
],
|
||||
logic: [createBlockJumpLogic(reusableElementIds[2], block6Id, "isSubmitted")],
|
||||
buttonLabel: t("templates.improve_trial_conversion_question_2_button_label"),
|
||||
buttonLabel: t("templates.improve_trial_conversion_question_3_button_label"),
|
||||
t,
|
||||
}),
|
||||
buildBlock({
|
||||
@@ -1647,14 +1647,14 @@ const identifyCustomerGoals = (t: TFunction): TTemplate => {
|
||||
elements: [
|
||||
buildMultipleChoiceElement({
|
||||
type: TSurveyElementTypeEnum.MultipleChoiceSingle,
|
||||
headline: "What's your primary goal for using $[projectName]?",
|
||||
headline: t("templates.identify_customer_goals_question_1_headline"),
|
||||
required: true,
|
||||
shuffleOption: "none",
|
||||
choices: [
|
||||
"Understand my user base deeply",
|
||||
"Identify upselling opportunities",
|
||||
"Build the best possible product",
|
||||
"Rule the world to make everyone breakfast brussels sprouts.",
|
||||
t("templates.identify_customer_goals_question_1_choice_1"),
|
||||
t("templates.identify_customer_goals_question_1_choice_2"),
|
||||
t("templates.identify_customer_goals_question_1_choice_3"),
|
||||
t("templates.identify_customer_goals_question_1_choice_4"),
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"ro-RO",
|
||||
"ru-RU",
|
||||
"sv-SE",
|
||||
"tr-TR",
|
||||
"zh-Hans-CN",
|
||||
"zh-Hant-TW"
|
||||
]
|
||||
|
||||
+40
-27
@@ -125,6 +125,7 @@ checksums:
|
||||
common/centered_modal: 982ff411cb7e91e30300c2ed56b7e507
|
||||
common/change_organization: 3b2c873962509445ff2cb8cde5ad913b
|
||||
common/change_workspace: 489cbcf7eef9b9b960e426fbf4da318f
|
||||
common/choice_n: ee41eb382bae7289a221d959f3046965
|
||||
common/choices: 8a7a77a71ec6eebc363c5dc0f8490a4d
|
||||
common/choose_environment: 5762cd499529815fc3e6a7feea39f90b
|
||||
common/choose_organization: a8f5db68012323bfbb1a0ad0fb194603
|
||||
@@ -138,6 +139,7 @@ checksums:
|
||||
common/close: 2c2e22f8424a1031de89063bd0022e16
|
||||
common/code: 343bc5386149b97cece2b093c39034b2
|
||||
common/collapse_rows: 24988527f9180f37aa55d2aa183ccb21
|
||||
common/column_n: 550955aee6a92d8ccc96989300add693
|
||||
common/completed: 0e4bbce9985f25eb673d9a054c8d5334
|
||||
common/configuration: 923ec0502721489202f6222dd4107163
|
||||
common/confirm: 90930b51154032f119fa75c1bd422d8b
|
||||
@@ -209,6 +211,7 @@ checksums:
|
||||
common/failed_to_copy_to_clipboard: de836a7d628d36c832809252f188f784
|
||||
common/failed_to_load_organizations: 512808a2b674c7c28bca73f8f91fd87e
|
||||
common/failed_to_load_workspaces: 6ee3448097394517dc605074cd4e6ea4
|
||||
common/field_placeholder: ec26d96643d86da164162204ec6c650f
|
||||
common/filter: 626325a05e4c8800f7ede7012b0cadaf
|
||||
common/finish: ffa7a10f71182b48fefed7135bee24fa
|
||||
common/first_name: cf040a5d6a9fd696be400380cc99f54b
|
||||
@@ -220,10 +223,12 @@ checksums:
|
||||
common/generate: 0345bf322c191e70d01fd6607ec5c2f8
|
||||
common/go_back: b917ea82facb90c88c523b255d29f84b
|
||||
common/go_to_dashboard: a6efa97d25e36fedc0af794f6ba610f2
|
||||
common/headline: 0023cbe059bbadcc77312825cbbce5ac
|
||||
common/hidden: fa290c6ada5869d744ed35e9cca64699
|
||||
common/hidden_field: 3ed5c58d0ed359e558cdf7bd33606d2d
|
||||
common/hidden_fields: 3de6cfd308293a826cb8679fd1d49972
|
||||
common/hide_column: 23ce94db148f2d8e4a0923defead6cf1
|
||||
common/html: f750870203043349d570d8f5865ca0f8
|
||||
common/id: c8886d38aeea2ed5f785aba4fc96784b
|
||||
common/image: 048ba7a239de0fbd883ade8558415830
|
||||
common/images: 9305827c28694866f49db42b4c51831f
|
||||
@@ -271,7 +276,6 @@ checksums:
|
||||
common/months: da74749fbe80394fa0f72973d7b0964a
|
||||
common/move_down: 4f4de55743043355ad4a839aff2c48ff
|
||||
common/move_up: 69f25b205c677abdb26cbb69d97cd10b
|
||||
common/multiple_languages: 7d8ddd4b40d32fcd7bd6f7bac6485b1f
|
||||
common/my_product: ad022177062f9ef6e9acf33b13e889aa
|
||||
common/name: 9368b5a047572b6051f334af5aa76819
|
||||
common/new: 126d036fae5fb6b629728ecb97e6195b
|
||||
@@ -286,6 +290,7 @@ checksums:
|
||||
common/no_result_found: fedddbc0149972ea072a9e063198a16d
|
||||
common/no_results: 0e9b73265c6542240f5a3bf6b43e9280
|
||||
common/no_surveys_found: 7b74706fe4f4aacd7d858e19e444fe85
|
||||
common/no_text_found: 27350f35bdd57b3701c7ec578a1a0e11
|
||||
common/none_of_the_above: e007f0b1e046d5ddbbcfbd87940456ee
|
||||
common/not_authenticated: fed6c62208524ea6782b5f9c07a95a4f
|
||||
common/not_authorized: 4be80383fe1a6f52c61138f1aa8d01d4
|
||||
@@ -309,7 +314,7 @@ checksums:
|
||||
common/organization_settings: 11528aa89ae9935e55dcb54478058775
|
||||
common/other: 79acaa6cd481262bea4e743a422529d2
|
||||
common/other_filters: 20b09213c131db47eb8b23e72d0c4bea
|
||||
common/others: 39160224ce0e35eb4eb252c997edf4d8
|
||||
common/other_placeholder: f3a0fa2eaaf75aa92b290449c928c081
|
||||
common/overlay_color: 4b72073285d13fff93d094aabffe05ac
|
||||
common/overview: 30c54e4dc4ce599b87d94be34a8617f5
|
||||
common/password: 223a61cf906ab9c40d22612c588dff48
|
||||
@@ -327,7 +332,6 @@ checksums:
|
||||
common/please_upgrade_your_plan: 03d54a21ecd27723c72a13644837e5ed
|
||||
common/powered_by_formbricks: 1c3e19894583292bfaf686cac84a4960
|
||||
common/preview: 3173ee1f0f1d4e50665ca4a84c38e15d
|
||||
common/preview_survey: 7409e9c118e3e5d5f2a86201c2b354f2
|
||||
common/privacy: 7459744a63ef8af4e517a09024bd7c08
|
||||
common/product_manager: dfeadc96e6d3de22a884ee97974b505e
|
||||
common/production: 226e0ce83b49700bc1b1c08c4c3ed23a
|
||||
@@ -354,6 +358,7 @@ checksums:
|
||||
common/responses: 14bb6c69f906d7bbd1359f7ef1bb3c28
|
||||
common/restart: bab6232e89f24e3129f8e48268739d5b
|
||||
common/role: 53743bbb6ca938f5b893552e839d067f
|
||||
common/row_n: eb5bb04b244fadd7a6962aa58bf6bd17
|
||||
common/saas: f01686245bcfb35a3590ab56db677bdb
|
||||
common/sales: 38758eb50094cd8190a71fe67be4d647
|
||||
common/save: f7a2929f33bc420195e59ac5a8bcd454
|
||||
@@ -392,6 +397,7 @@ checksums:
|
||||
common/storage_not_configured: b0c3e339f6d71f23fdd189e7bcb076f6
|
||||
common/string: 4ddccc1974775ed7357f9beaf9361cec
|
||||
common/styling: 240fc91eb03c52d46b137f82e7aec2a1
|
||||
common/subheader: 73a37d57cb9807e574a42bd0c7e334ed
|
||||
common/submit: 7c91ef5f747eea9f77a9c4f23e19fb2e
|
||||
common/summary: 13eb7b8a239fb4702dfdaee69100a220
|
||||
common/survey: b659d270a53dada994d926e0cc6e9a54
|
||||
@@ -460,7 +466,6 @@ checksums:
|
||||
common/workspace_name_placeholder: 8a9e30ab01666af13c44a73b82c37ec1
|
||||
common/workspaces: 8ba082a84aa35cf851af1cf874b853e2
|
||||
common/years: eb4f5fdd2b320bf13e200fd6a6c1abff
|
||||
common/you: db2a4a796b70cc1430d1b21f6ffb6dcb
|
||||
common/you_are_downgraded_to_the_community_edition: e3ae56502ff787109cae0997519f628e
|
||||
common/you_are_not_authorized_to_perform_this_action: 1b3255ab740582ddff016a399f8bf302
|
||||
common/you_have_reached_your_limit_of_workspace_limit: 54d754c3267036742f23fb05fd3fcc45
|
||||
@@ -784,6 +789,9 @@ checksums:
|
||||
environments/integrations/notion/update_connection_tooltip: 2429919f575e47f5c76e54b4442ba706
|
||||
environments/integrations/notion_integration_description: 31a73dbe88fe18a078d6dc15f0c303e2
|
||||
environments/integrations/please_select_a_survey_error: 465aa7048773079c8ffdde8b333b78eb
|
||||
environments/integrations/reconnect_button: 8992a0f250278c116cb26be448b68ba2
|
||||
environments/integrations/reconnect_button_description: 01f79dc561ff87b5f2a80bf66e492844
|
||||
environments/integrations/reconnect_button_tooltip: 5552effda9df8d6778dda1cf42e5d880
|
||||
environments/integrations/select_at_least_one_question_error: a3513cb02ab0de2a1531893ac0c7e089
|
||||
environments/integrations/slack/already_connected_another_survey: 4508f9e4a2915e3818ea5f9e2695e000
|
||||
environments/integrations/slack/channel_name: 1afcd1d0401850ff353f5ae27502b04a
|
||||
@@ -1231,15 +1239,9 @@ checksums:
|
||||
environments/settings/teams/you_are_a_member: cf5af638d5371c8fbc337e92519e5150
|
||||
environments/surveys/all_set_time_to_create_first_survey: 21d3bb74c3b9642b3195d17c17346399
|
||||
environments/surveys/alphabetical: 5fcfeff9c5fd28714f0a390e0ddaaaee
|
||||
environments/surveys/copy_survey: de8142b45e7bca61f2dca0069a62b417
|
||||
environments/surveys/copy_survey_description: 66d0aadf192ad5790fbf3f55f3bb5485
|
||||
environments/surveys/copy_survey_error: 74cab7d84ea8b669e106d4c326cac005
|
||||
environments/surveys/copy_survey_link_to_clipboard: 77387e3d3de4be07a2a34963f73cd7e8
|
||||
environments/surveys/copy_survey_partially_success: a436a5fb7167b95c2308794d35aab070
|
||||
environments/surveys/copy_survey_success: a829e645fe034b3e712d0b8572a5edc4
|
||||
environments/surveys/delete_survey_and_responses_warning: 3320c91c1fd27378b7f3d6abc003f2ae
|
||||
environments/surveys/edit/1_choose_the_default_language_for_this_survey: d22759857c1bb3d6b337e8e9d501dad7
|
||||
environments/surveys/edit/2_activate_translation_for_specific_languages: 9f23cb81ad301073df45ae36f0d94f9e
|
||||
environments/surveys/edit/activate_translations: af127c1bed2b47e2012e3a23e489ecb8
|
||||
environments/surveys/edit/add: 5196f5cd4ba3a6ac8edef91345e17f66
|
||||
environments/surveys/edit/add_a_delay_or_auto_close_the_survey: b5fa358bf3ff324014060eb0baf6dd2f
|
||||
environments/surveys/edit/add_a_four_digit_pin: 953cb3673d2135923e3b4474d33ffb2c
|
||||
@@ -1289,7 +1291,7 @@ checksums:
|
||||
environments/surveys/edit/audience: a4d9fab4214a641e2d358fbb28f010e0
|
||||
environments/surveys/edit/auto_close_on_inactivity: 093db516799315ccd4242a3675693012
|
||||
environments/surveys/edit/auto_progress_rating_and_nps: 76b98e95a5b850850baa0ccc3c7fbf7c
|
||||
environments/surveys/edit/auto_progress_rating_and_nps_description: cbf676789b9f3f47e36bdf35fa58282b
|
||||
environments/surveys/edit/auto_progress_rating_and_nps_description: 2a992dd8a5b9532f178f9a21881feb9a
|
||||
environments/surveys/edit/auto_save_disabled: f7411fb0dcfb8f7b19b85f0be54f2231
|
||||
environments/surveys/edit/auto_save_disabled_tooltip: 77322e1e866b7d29f7641a88bbd3b681
|
||||
environments/surveys/edit/auto_save_on: 1524d466830b00c5d727c701db404963
|
||||
@@ -1335,6 +1337,7 @@ checksums:
|
||||
environments/surveys/edit/caution_text: 3291e962c0e4c4656832837ddc512918
|
||||
environments/surveys/edit/change_anyway: 6377497d40373f6d0f082670194981ab
|
||||
environments/surveys/edit/change_background: fa71a993869f7d3ac553c547c12c3e9b
|
||||
environments/surveys/edit/change_default: 6236a6c8a28489ba7c4cad7426806859
|
||||
environments/surveys/edit/change_question_type: 2d555ae48df8dbedfc6a4e1ad492f4aa
|
||||
environments/surveys/edit/change_survey_type: c26322043a476da6d94adb8b4efe1e93
|
||||
environments/surveys/edit/change_the_background_to_a_color_image_or_animation: f1b9c9eb61497dd91b2550dd50c77836
|
||||
@@ -1347,6 +1350,7 @@ checksums:
|
||||
environments/surveys/edit/choose_where_to_run_the_survey: ad87bcae97c445f1fd9ac110ea24f117
|
||||
environments/surveys/edit/city: 1831f32e1babbb29af27fac3053504a2
|
||||
environments/surveys/edit/close_survey_on_response_limit: 256d0bccdbcbb3d20e39aabc5b376e5e
|
||||
environments/surveys/edit/code: 343bc5386149b97cece2b093c39034b2
|
||||
environments/surveys/edit/color: 9d53d1d120e8b8954bcae9a322573748
|
||||
environments/surveys/edit/column_used_in_logic_error: deffbd3e8f4bd71a5e522682e8ee60dd
|
||||
environments/surveys/edit/columns: 14896556dc1535d70198854757f704ec
|
||||
@@ -1371,6 +1375,7 @@ checksums:
|
||||
environments/surveys/edit/customize_survey_logo: 7f7e26026c88a727228f2d7a00d914e2
|
||||
environments/surveys/edit/darken_or_lighten_background_of_your_choice: 304a64a8050ebf501d195e948cd25b6f
|
||||
environments/surveys/edit/days_before_showing_this_survey_again: 9ee757e5c3a07844b12ceb406dc65b04
|
||||
environments/surveys/edit/default_language: 06d01d2598419e36ba97d2d8719f849b
|
||||
environments/surveys/edit/delete_anyways: cc8683ab625280eefc9776bd381dc2e8
|
||||
environments/surveys/edit/delete_block: c00617cb0724557e486304276063807a
|
||||
environments/surveys/edit/delete_choice: fd750208d414b9ad8c980c161a0199e1
|
||||
@@ -1390,7 +1395,6 @@ checksums:
|
||||
environments/surveys/edit/duplicate_question: 910751de01fdd327165968214717711b
|
||||
environments/surveys/edit/edit_link: 40ba9e15beac77a46c5baf30be84ac54
|
||||
environments/surveys/edit/edit_recall: 38a4a7378d02453e35d06f2532eef318
|
||||
environments/surveys/edit/edit_translations: 2b21bea4b53e88342559272701e9fbf3
|
||||
environments/surveys/edit/element_not_found: 196777ff6811dd177971ffc8e27a72c1
|
||||
environments/surveys/edit/enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey: c70466147d49dcbb3686452f35c46428
|
||||
environments/surveys/edit/enable_recaptcha_to_protect_your_survey_from_spam: 4483a5763718d201ac97caa1e1216e13
|
||||
@@ -1526,11 +1530,13 @@ checksums:
|
||||
environments/surveys/edit/long_answer: 3a97f8d2e90aba6e679917a0c5670c53
|
||||
environments/surveys/edit/long_answer_toggle_description: 86bcdfeb74d9825c2f2d5a215e92d111
|
||||
environments/surveys/edit/lower_label: 45985bca022d4370bd6e013af75d5160
|
||||
environments/surveys/edit/manage_languages: 9c56d5afee8a73dfc283a452470f3a10
|
||||
environments/surveys/edit/manage_languages: fe82303bc27b55ccfc076b527b185e39
|
||||
environments/surveys/edit/manage_translations: 09b01c5c251e6dbc3dc6cd8b33fb6301
|
||||
environments/surveys/edit/matrix_all_fields: 187240509163b2f52a400a565e57c67f
|
||||
environments/surveys/edit/matrix_rows: 8f41f34e6ca28221cf1ebd948af4c151
|
||||
environments/surveys/edit/max_file_size: 3d35a22048f4d22e24da698fb5fb77d7
|
||||
environments/surveys/edit/max_file_size_limit_is: 78998639cde3587cecb272ba47e05f9e
|
||||
environments/surveys/edit/missing_first: a0c8802636ade7bac86a0dacba00b8d4
|
||||
environments/surveys/edit/move_question_to_block: e8d7ef1e2f727921cb7f5788849492ad
|
||||
environments/surveys/edit/multiply: 89a0bb629167f97750ae1645a46ced0d
|
||||
environments/surveys/edit/needed_for_self_hosted_cal_com_instance: d241e72f0332177d32ce6c35070757dc
|
||||
@@ -1538,7 +1544,7 @@ checksums:
|
||||
environments/surveys/edit/next_button_label: 39f1e82ae1dea5e400e8ed7c98c6ad9c
|
||||
environments/surveys/edit/no_hidden_fields_yet_add_first_one_below: 9cc6cab3a6a42dbf835215897b5b8516
|
||||
environments/surveys/edit/no_images_found_for: 7dabcbcc7084f59c6ec0971895dfcd29
|
||||
environments/surveys/edit/no_languages_found_add_first_one_to_get_started: 22d7782c8504daf693cab3cf7135d6e3
|
||||
environments/surveys/edit/no_languages_found_add_first_one_to_get_started: 4e66397232da6a463708220dc020bf42
|
||||
environments/surveys/edit/no_option_found: a1a3aa7e6c13b6bb8df20a1a104c7c04
|
||||
environments/surveys/edit/no_recall_items_found: 729e2b02e412cdc79f5ad94b1918620c
|
||||
environments/surveys/edit/no_variables_yet_add_first_one_below: c8704b9ebc9c26c0e9dd50c099ba88cd
|
||||
@@ -1565,6 +1571,7 @@ checksums:
|
||||
environments/surveys/edit/please_enter_a_valid_url: 25d43dfb802c31cb59dc88453ea72fc4
|
||||
environments/surveys/edit/please_set_a_survey_trigger: 0358142df37dd1724f629008a1db453a
|
||||
environments/surveys/edit/please_specify: e1faa6cd085144f7339c7e74dc6fb366
|
||||
environments/surveys/edit/present_your_survey_in_multiple_languages: 37f28b0a092d68322fedbc2e0c221ef3
|
||||
environments/surveys/edit/prevent_double_submission: afc502baa2da81d9c9618da1c3b5a57a
|
||||
environments/surveys/edit/prevent_double_submission_description: ef7d2aa22d43bdc6ccebb076c6aa9ce5
|
||||
environments/surveys/edit/progress_saved: d7bfc189571f08bbb4d0240cb9363ffa
|
||||
@@ -1654,6 +1661,7 @@ checksums:
|
||||
environments/surveys/edit/seven_points: 4ead50fdfda45e8710767e1b1a84bf42
|
||||
environments/surveys/edit/show_block_settings: bad99d99c9908874e45f5c350a88cc79
|
||||
environments/surveys/edit/show_button: 6b364aac9d7ac71f34a438607c9693bc
|
||||
environments/surveys/edit/show_in_order: 15784a59572eb8a6dba6b918c31a9493
|
||||
environments/surveys/edit/show_language_switch: b6915a7f26d7079f2d4d844d74440413
|
||||
environments/surveys/edit/show_multiple_times: 05239c532c9c05ef5d2990ba6ce12f60
|
||||
environments/surveys/edit/show_only_once: 31858baf60ebcf193c7e35d9084af0af
|
||||
@@ -1685,7 +1693,6 @@ checksums:
|
||||
environments/surveys/edit/survey_preview: 33644451073149383d3ace08be930739
|
||||
environments/surveys/edit/survey_styling: 7f96d6563e934e65687b74374a33b1dc
|
||||
environments/surveys/edit/survey_trigger: f0c7014a684ca566698b87074fad5579
|
||||
environments/surveys/edit/switch_multi_language_on_to_get_started: cca0ef91ee49095da30cd1e3f26c406f
|
||||
environments/surveys/edit/target_block_not_found: 0a0c401017ab32364fec2fcbf815d832
|
||||
environments/surveys/edit/targeted: ca615f1fc3b490d5a2187b27fb4a2073
|
||||
environments/surveys/edit/ten_points: a1317b82003859f77fb3138c55450d63
|
||||
@@ -1693,9 +1700,11 @@ checksums:
|
||||
environments/surveys/edit/the_survey_will_be_shown_once_even_if_person_doesnt_respond: e45beba7ae126775f4966776c982a3b4
|
||||
environments/surveys/edit/then: 5e941fb7dd51a18651fcfb865edd5ba6
|
||||
environments/surveys/edit/this_action_will_remove_all_the_translations_from_this_survey: 3340c89696f10bdc01b9a1047ff0b987
|
||||
environments/surveys/edit/this_will_remove_the_language_and_all_its_translations: 6a71ae70abbd61f13f15323d825a47f6
|
||||
environments/surveys/edit/three_points: d7f299aec752d7d690ef0ab6373327ae
|
||||
environments/surveys/edit/times: 5ab156c13df6bfd75c0b17ad0a92c78a
|
||||
environments/surveys/edit/to_keep_the_placement_over_all_surveys_consistent_you_can: 7a078e6a39d4c30b465137d2b6ef3e67
|
||||
environments/surveys/edit/translated: 5b9d805410310b726f12bacb06da44e3
|
||||
environments/surveys/edit/trigger_survey_when_one_of_the_actions_is_fired: 8570291668ec9879d204f10e861112db
|
||||
environments/surveys/edit/try_lollipop_or_mountain: c550a0f07b3ae40a237e30a4314a249c
|
||||
environments/surveys/edit/type_field_id: 714b845806236bb8a9d6a09933b836e9
|
||||
@@ -1768,6 +1777,7 @@ checksums:
|
||||
environments/surveys/edit/verify_email_before_submission_description: 434ab3ee6134367513b633a9d4f7d772
|
||||
environments/surveys/edit/visibility_and_recontact: c27cb4ff3a4262266902a335c3ad5d84
|
||||
environments/surveys/edit/visibility_and_recontact_description: 2969ab679e1f6111dd96e95cee26e219
|
||||
environments/surveys/edit/visible: 54ea1310fe55664c24a712eb17070fbd
|
||||
environments/surveys/edit/wait: 014d18ade977bf08d75b995076596708
|
||||
environments/surveys/edit/wait_a_few_seconds_after_the_trigger_before_showing_the_survey: 13d5521cf73be5afeba71f5db5847919
|
||||
environments/surveys/edit/waiting_time_across_surveys: 6873c18d51830e2cadef67cce6a2c95c
|
||||
@@ -1950,7 +1960,6 @@ checksums:
|
||||
environments/surveys/summary/downloading_qr_code: 3c46bf636e617848a4fca9b6c5b51dac
|
||||
environments/surveys/summary/drop_offs: 605ee950f82110132d6c5780926af109
|
||||
environments/surveys/summary/drop_offs_tooltip: 2a01683380be45f17636365886cf3452
|
||||
environments/surveys/summary/failed_to_copy_link: 4e891c757c80e770674e8e74d1c08487
|
||||
environments/surveys/summary/filter_added_successfully: e247f65020cd87454bcec0da6f0fd034
|
||||
environments/surveys/summary/filter_updated_successfully: 01146bc7e6394e271836be2f1b3a257b
|
||||
environments/surveys/summary/filtered_responses_csv: aad66a98be6a09cac8bef9e4db4a75cf
|
||||
@@ -2035,7 +2044,6 @@ checksums:
|
||||
environments/surveys/summary/youre_not_plugged_in_yet: f19da3cd474b9a3cf28e956fd811fb00
|
||||
environments/surveys/survey_deleted_successfully: a6b654cc914b344a4475fd2fd4a98cc5
|
||||
environments/surveys/survey_duplicated_successfully: 91e244f1e7a33640bb4817166a01ff46
|
||||
environments/surveys/survey_duplication_error: 35994330aed844ce37d8b4f09df24581
|
||||
environments/surveys/templates/all_channels: 6be67a82fc7326dc2304b23ab3348b87
|
||||
environments/surveys/templates/all_industries: c7354412fe34585526ff2232aadace41
|
||||
environments/surveys/templates/all_roles: 6582ccd0a2349c162a7ae1574cdf76be
|
||||
@@ -2112,7 +2120,6 @@ checksums:
|
||||
environments/workspace/languages/duplicate_language_or_language_id: 0e17e3794b24e2428ca6ffadae0d08f3
|
||||
environments/workspace/languages/edit_languages: c9d36f6b28557cc7d54e87c37dc18fdd
|
||||
environments/workspace/languages/identifier: 7d8ade6b85e96216bcd73adeeeeecd8c
|
||||
environments/workspace/languages/incomplete_translations: d82908b5725f18f5849c7876ad497ebc
|
||||
environments/workspace/languages/language: 277fd1a41cc237a437cd1d5e4a80463b
|
||||
environments/workspace/languages/language_deleted_successfully: 4a805d030491f3fe608d2371b0cfcd83
|
||||
environments/workspace/languages/languages_updated_successfully: 60de474c99c5059c0458cddd0b016c15
|
||||
@@ -2123,7 +2130,6 @@ checksums:
|
||||
environments/workspace/languages/remove_language: 1a64563b0f37109f97b78eddd493e381
|
||||
environments/workspace/languages/remove_language_from_surveys_to_remove_it_from_workspace: 61bc96f9db31a29a649cc9ecd684bc39
|
||||
environments/workspace/languages/search_items: b54b751c8b075200be579d6c8e58096b
|
||||
environments/workspace/languages/translate: 59f9803b27e2030ba7323ed239116cf7
|
||||
environments/workspace/look/add_background_color: 9be512ee1246e32d3958c56097d202d9
|
||||
environments/workspace/look/add_background_color_description: adb6fcb392862b3d0e9420d9b5405ddb
|
||||
environments/workspace/look/advanced_styling_field_border_radius: 63b8f3541a9792d705e67d5aca7b6451
|
||||
@@ -2181,12 +2187,12 @@ checksums:
|
||||
environments/workspace/look/advanced_styling_field_track_bg_description: 8a56258273dfe49e83fe752ea9e8daed
|
||||
environments/workspace/look/advanced_styling_field_track_height: 9ce57cb4583039c224a37e013efb6b8f
|
||||
environments/workspace/look/advanced_styling_field_track_height_description: 90243a4374e15d9118ad0fd93d5f3614
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color: 65d75c60dfdba88e5fed38bcb24a0a5d
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color_description: ae2276506807c7ceeb7a8b87723a8dd4
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size: ea0ca9a3ffa1650f97a31df453b0afc7
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size_description: 061668625be0f7a68ebc2e2ebe49e5a9
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight: 946c5836d2cfaaee21e494424d550887
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight_description: 916b03c719a8dead351679336aabcf53
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color: 2767a5db32742073a01aac16488e93dc
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color_description: 58f43ce21b7f6539cc937aa80c7e8060
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size: 3342babd1df61a3bdf7a3284137f7c24
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size_description: 867a89a79ed7ac7f1c6b0f3481a67f26
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight: a9a0de9e840518d282cfdbcb02d059b5
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight_description: 3cee88e1c8e75548dcb6004f0e44f31c
|
||||
environments/workspace/look/advanced_styling_section_buttons: 3b44d6e2800e7bf3f133f1bce435f4c2
|
||||
environments/workspace/look/advanced_styling_section_headlines: 6def704c0ac2ecb5951400c806856a41
|
||||
environments/workspace/look/advanced_styling_section_inputs: 76bbeb561122a72fd3ec8c49eff7c563
|
||||
@@ -2719,6 +2725,11 @@ checksums:
|
||||
templates/gauge_feature_satisfaction_question_2_headline: 0fcbefbfcf5c21e42de8a36cb2cad854
|
||||
templates/identify_customer_goals_description: c30d06df9e5c76334e4c3d470ee6e4d8
|
||||
templates/identify_customer_goals_name: f8123dbfa22e169517a811fae7496595
|
||||
templates/identify_customer_goals_question_1_choice_1: a6803cfbdbd6208eedf5c691f9e106a5
|
||||
templates/identify_customer_goals_question_1_choice_2: 7461749517d62030ec2e3915cf1d223b
|
||||
templates/identify_customer_goals_question_1_choice_3: 725eb3ee0d4f2d229fcf588c21e66a86
|
||||
templates/identify_customer_goals_question_1_choice_4: 3985521036afaf1cbd2bdc7a4d86d351
|
||||
templates/identify_customer_goals_question_1_headline: bd9cd414fb723110d7f0a786bbf89d6c
|
||||
templates/identify_sign_up_barriers_description: 5b2fbee8c425d7a4d0706ec3628cea11
|
||||
templates/identify_sign_up_barriers_name: 3bbc5352dfa7a9c237bc2c6b21b608dd
|
||||
templates/identify_sign_up_barriers_question_1_button_label: 080fd22c580f56ffdcea6c3d60448b84
|
||||
@@ -2793,12 +2804,14 @@ checksums:
|
||||
templates/improve_trial_conversion_question_1_subheader: 67c7047ba2365d461df14dbed3f9506d
|
||||
templates/improve_trial_conversion_question_2_button_label: 89ddbcf710eba274963494f312bdc8a9
|
||||
templates/improve_trial_conversion_question_2_headline: 05dd4820f60b9d267a9affc7e662f029
|
||||
templates/improve_trial_conversion_question_3_button_label: 89ddbcf710eba274963494f312bdc8a9
|
||||
templates/improve_trial_conversion_question_3_headline: 3daeccf3dfc7bf8e9868c10fb3ea0b19
|
||||
templates/improve_trial_conversion_question_4_button_label: d94a6a11cfdf4ebde4c5332e585e2e96
|
||||
templates/improve_trial_conversion_question_4_headline: 9b07341f65574c4165086ec107cebb45
|
||||
templates/improve_trial_conversion_question_4_html: 8ce95691eeeae7ad61c4d2f867b918ca
|
||||
templates/improve_trial_conversion_question_5_button_label: 89ddbcf710eba274963494f312bdc8a9
|
||||
templates/improve_trial_conversion_question_5_headline: dbd99e216fcbf8693b8e77fbd77e1c84
|
||||
templates/improve_trial_conversion_question_5_subheader: b9b478e967930358b0c74324a7c18fc8
|
||||
templates/improve_trial_conversion_question_5_subheader: 859876a442a633f4aa0d78fd0ee4ab4c
|
||||
templates/improve_trial_conversion_question_6_headline: f15239ecc4f1a6bd8bea77a38b39c844
|
||||
templates/improve_trial_conversion_question_6_subheader: e147ddbb609fff6e6fc78fb1f4add0ac
|
||||
templates/integration_setup_survey_description: 696ccab07d7098cdb79c224fa1208889
|
||||
|
||||
@@ -3,7 +3,6 @@ import { logger } from "@formbricks/logger";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
import { TIntegrationItem } from "@formbricks/types/integration";
|
||||
import {
|
||||
TIntegrationAirtable,
|
||||
TIntegrationAirtableConfigData,
|
||||
TIntegrationAirtableCredential,
|
||||
ZIntegrationAirtableBases,
|
||||
@@ -24,6 +23,11 @@ export const getBases = async (key: string) => {
|
||||
},
|
||||
});
|
||||
|
||||
if (!req.ok) {
|
||||
const body = await req.text().catch(() => "");
|
||||
throw new Error(`Airtable API error fetching bases: ${req.status} ${req.statusText} ${body}`);
|
||||
}
|
||||
|
||||
const res = await req.json();
|
||||
return ZIntegrationAirtableBases.parse(res);
|
||||
};
|
||||
@@ -35,6 +39,11 @@ const tableFetcher = async (key: TIntegrationAirtableCredential, baseId: string)
|
||||
},
|
||||
});
|
||||
|
||||
if (!req.ok) {
|
||||
const body = await req.text().catch(() => "");
|
||||
throw new Error(`Airtable API error fetching tables: ${req.status} ${req.statusText} ${body}`);
|
||||
}
|
||||
|
||||
const res = await req.json();
|
||||
|
||||
return res;
|
||||
@@ -78,10 +87,7 @@ export const fetchAirtableAuthToken = async (formData: Record<string, any>) => {
|
||||
|
||||
export const getAirtableToken = async (environmentId: string) => {
|
||||
try {
|
||||
const airtableIntegration = (await getIntegrationByType(
|
||||
environmentId,
|
||||
"airtable"
|
||||
)) as TIntegrationAirtable;
|
||||
const airtableIntegration = await getIntegrationByType(environmentId, "airtable");
|
||||
|
||||
const { access_token, expiry_date, refresh_token } = ZIntegrationAirtableCredential.parse(
|
||||
airtableIntegration?.config.key
|
||||
|
||||
@@ -182,6 +182,7 @@ export const AVAILABLE_LOCALES: TUserLocale[] = [
|
||||
"ro-RO",
|
||||
"ru-RU",
|
||||
"sv-SE",
|
||||
"tr-TR",
|
||||
"zh-Hans-CN",
|
||||
"zh-Hant-TW",
|
||||
];
|
||||
|
||||
@@ -213,6 +213,13 @@ export const appLanguages = [
|
||||
native: "Svenska",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "tr-TR",
|
||||
label: {
|
||||
"en-US": "Turkish",
|
||||
native: "Türkçe",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "zh-Hans-CN",
|
||||
label: {
|
||||
|
||||
@@ -5,7 +5,12 @@ import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { ZId, ZOptionalNumber, ZString } from "@formbricks/types/common";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
import { TIntegration, TIntegrationInput, ZIntegrationType } from "@formbricks/types/integration";
|
||||
import {
|
||||
TIntegration,
|
||||
TIntegrationByType,
|
||||
TIntegrationInput,
|
||||
ZIntegrationType,
|
||||
} from "@formbricks/types/integration";
|
||||
import { ITEMS_PER_PAGE } from "../constants";
|
||||
import { validateInputs } from "../utils/validate";
|
||||
|
||||
@@ -94,7 +99,10 @@ export const getIntegration = reactCache(async (integrationId: string): Promise<
|
||||
});
|
||||
|
||||
export const getIntegrationByType = reactCache(
|
||||
async (environmentId: string, type: TIntegrationInput["type"]): Promise<TIntegration | null> => {
|
||||
async <T extends TIntegrationInput["type"]>(
|
||||
environmentId: string,
|
||||
type: T
|
||||
): Promise<TIntegrationByType<T> | null> => {
|
||||
validateInputs([environmentId, ZId], [type, ZIntegrationType]);
|
||||
|
||||
try {
|
||||
@@ -106,7 +114,7 @@ export const getIntegrationByType = reactCache(
|
||||
},
|
||||
},
|
||||
});
|
||||
return integration ? transformIntegration(integration) : null;
|
||||
return integration ? (transformIntegration(integration) as TIntegrationByType<T>) : null;
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseError(error.message);
|
||||
|
||||
@@ -6,11 +6,13 @@ import {
|
||||
createEmailChangeToken,
|
||||
createEmailToken,
|
||||
createInviteToken,
|
||||
createSsoRelinkIntent,
|
||||
createToken,
|
||||
createTokenForLinkSurvey,
|
||||
getEmailFromEmailToken,
|
||||
verifyEmailChangeToken,
|
||||
verifyInviteToken,
|
||||
verifySsoRelinkIntent,
|
||||
verifyToken,
|
||||
verifyTokenForLinkSurvey,
|
||||
} from "./jwt";
|
||||
@@ -380,6 +382,7 @@ describe("JWT Functions - Comprehensive Security Tests", () => {
|
||||
expect(verified).toEqual({
|
||||
id: mockUser.id, // Returns the decrypted user ID
|
||||
email: mockUser.email,
|
||||
purpose: "email_verification",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -414,6 +417,7 @@ describe("JWT Functions - Comprehensive Security Tests", () => {
|
||||
expect(verified).toEqual({
|
||||
id: mockUser.id, // Returns the raw ID from payload
|
||||
email: mockUser.email,
|
||||
purpose: "email_verification",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -425,6 +429,7 @@ describe("JWT Functions - Comprehensive Security Tests", () => {
|
||||
expect(verified).toEqual({
|
||||
id: mockUser.id, // Returns the decrypted user ID
|
||||
email: mockUser.email,
|
||||
purpose: "email_verification",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1004,5 +1009,78 @@ describe("JWT Functions - Comprehensive Security Tests", () => {
|
||||
expect(results.every((result: any) => result.id === mockUser.id)).toBe(true); // Returns decrypted user ID
|
||||
});
|
||||
});
|
||||
|
||||
describe("SSO recovery support", () => {
|
||||
test("creates verification tokens that preserve the recovery purpose", async () => {
|
||||
const token = createToken(mockUser.id, { purpose: "sso_recovery", expiresIn: "15m" });
|
||||
|
||||
await expect(verifyToken(token)).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
id: mockUser.id,
|
||||
email: mockUser.email,
|
||||
purpose: "sso_recovery",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("defaults legacy verification tokens to email_verification when purpose is missing", async () => {
|
||||
const legacyToken = jwt.sign({ id: `encrypted_${mockUser.id}` }, TEST_NEXTAUTH_SECRET);
|
||||
|
||||
await expect(verifyToken(legacyToken)).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
id: mockUser.id,
|
||||
email: mockUser.email,
|
||||
purpose: "email_verification",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("round-trips SSO relink intents without losing callback state", () => {
|
||||
const intent = createSsoRelinkIntent({
|
||||
userId: mockUser.id,
|
||||
email: mockUser.email,
|
||||
provider: "google",
|
||||
providerAccountId: "provider-123",
|
||||
callbackUrl: "http://localhost:3000/invite?token=invite-token",
|
||||
});
|
||||
|
||||
expect(verifySsoRelinkIntent(intent)).toEqual({
|
||||
userId: mockUser.id,
|
||||
email: mockUser.email,
|
||||
provider: "google",
|
||||
providerAccountId: "provider-123",
|
||||
callbackUrl: "http://localhost:3000/invite?token=invite-token",
|
||||
});
|
||||
});
|
||||
|
||||
test("rejects expired SSO relink intents", () => {
|
||||
const expiredIntent = jwt.sign(
|
||||
{
|
||||
userId: crypto.symmetricEncrypt(mockUser.id, TEST_ENCRYPTION_KEY),
|
||||
email: crypto.symmetricEncrypt(mockUser.email, TEST_ENCRYPTION_KEY),
|
||||
provider: "google",
|
||||
providerAccountId: crypto.symmetricEncrypt("provider-123", TEST_ENCRYPTION_KEY),
|
||||
callbackUrl: crypto.symmetricEncrypt("http://localhost:3000", TEST_ENCRYPTION_KEY),
|
||||
exp: Math.floor(Date.now() / 1000) - 3600,
|
||||
},
|
||||
TEST_NEXTAUTH_SECRET
|
||||
);
|
||||
|
||||
expect(() => verifySsoRelinkIntent(expiredIntent)).toThrow();
|
||||
});
|
||||
|
||||
test("rejects tampered SSO relink intents", () => {
|
||||
const intent = createSsoRelinkIntent({
|
||||
userId: mockUser.id,
|
||||
email: mockUser.email,
|
||||
provider: "google",
|
||||
providerAccountId: "provider-123",
|
||||
callbackUrl: "http://localhost:3000",
|
||||
});
|
||||
|
||||
const tamperedIntent = `${intent.slice(0, -1)}x`;
|
||||
expect(() => verifySsoRelinkIntent(tamperedIntent)).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+108
-5
@@ -1,4 +1,4 @@
|
||||
import jwt, { JwtPayload } from "jsonwebtoken";
|
||||
import jwt, { JwtPayload, SignOptions } from "jsonwebtoken";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { ENCRYPTION_KEY, NEXTAUTH_SECRET } from "@/lib/constants";
|
||||
@@ -13,7 +13,39 @@ const decryptWithFallback = (encryptedText: string, key: string): string => {
|
||||
}
|
||||
};
|
||||
|
||||
export const createToken = (userId: string, options = {}): string => {
|
||||
export const VERIFICATION_TOKEN_PURPOSES = ["email_verification", "sso_recovery"] as const;
|
||||
|
||||
export type TVerificationTokenPurpose = (typeof VERIFICATION_TOKEN_PURPOSES)[number];
|
||||
|
||||
export type TVerifyTokenPayload = JwtPayload & {
|
||||
id: string;
|
||||
email: string;
|
||||
purpose: TVerificationTokenPurpose;
|
||||
};
|
||||
|
||||
type TVerificationTokenOptions = SignOptions & {
|
||||
purpose?: TVerificationTokenPurpose;
|
||||
};
|
||||
|
||||
type TSsoRelinkIntentPayload = {
|
||||
callbackUrl: string;
|
||||
email: string;
|
||||
provider: string;
|
||||
providerAccountId: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
const DEFAULT_VERIFICATION_TOKEN_PURPOSE: TVerificationTokenPurpose = "email_verification";
|
||||
|
||||
const getVerificationTokenPurpose = (purpose: unknown): TVerificationTokenPurpose => {
|
||||
if (purpose && VERIFICATION_TOKEN_PURPOSES.includes(purpose as TVerificationTokenPurpose)) {
|
||||
return purpose as TVerificationTokenPurpose;
|
||||
}
|
||||
|
||||
return DEFAULT_VERIFICATION_TOKEN_PURPOSE;
|
||||
};
|
||||
|
||||
export const createToken = (userId: string, options: TVerificationTokenOptions = {}): string => {
|
||||
if (!NEXTAUTH_SECRET) {
|
||||
throw new Error("NEXTAUTH_SECRET is not set");
|
||||
}
|
||||
@@ -23,7 +55,9 @@ export const createToken = (userId: string, options = {}): string => {
|
||||
}
|
||||
|
||||
const encryptedUserId = symmetricEncrypt(userId, ENCRYPTION_KEY);
|
||||
return jwt.sign({ id: encryptedUserId }, NEXTAUTH_SECRET, options);
|
||||
const { purpose = DEFAULT_VERIFICATION_TOKEN_PURPOSE, ...jwtOptions } = options;
|
||||
|
||||
return jwt.sign({ id: encryptedUserId, purpose }, NEXTAUTH_SECRET, jwtOptions);
|
||||
};
|
||||
export const createTokenForLinkSurvey = (surveyId: string, userEmail: string): string => {
|
||||
if (!NEXTAUTH_SECRET) {
|
||||
@@ -224,7 +258,72 @@ const getUserEmailForLegacyVerification = async (
|
||||
return { userId: decryptedId, userEmail: foundUser.email };
|
||||
};
|
||||
|
||||
export const verifyToken = async (token: string): Promise<JwtPayload> => {
|
||||
const DEFAULT_SSO_RELINK_INTENT_OPTIONS: SignOptions = {
|
||||
expiresIn: "15m",
|
||||
};
|
||||
|
||||
export const createSsoRelinkIntent = (
|
||||
payload: TSsoRelinkIntentPayload,
|
||||
options: SignOptions = DEFAULT_SSO_RELINK_INTENT_OPTIONS
|
||||
): string => {
|
||||
if (!NEXTAUTH_SECRET) {
|
||||
throw new Error("NEXTAUTH_SECRET is not set");
|
||||
}
|
||||
|
||||
if (!ENCRYPTION_KEY) {
|
||||
throw new Error("ENCRYPTION_KEY is not set");
|
||||
}
|
||||
|
||||
return jwt.sign(
|
||||
{
|
||||
userId: symmetricEncrypt(payload.userId, ENCRYPTION_KEY),
|
||||
email: symmetricEncrypt(payload.email, ENCRYPTION_KEY),
|
||||
provider: payload.provider,
|
||||
providerAccountId: symmetricEncrypt(payload.providerAccountId, ENCRYPTION_KEY),
|
||||
callbackUrl: symmetricEncrypt(payload.callbackUrl, ENCRYPTION_KEY),
|
||||
},
|
||||
NEXTAUTH_SECRET,
|
||||
options
|
||||
);
|
||||
};
|
||||
|
||||
export const verifySsoRelinkIntent = (token: string): TSsoRelinkIntentPayload => {
|
||||
if (!NEXTAUTH_SECRET) {
|
||||
throw new Error("NEXTAUTH_SECRET is not set");
|
||||
}
|
||||
|
||||
if (!ENCRYPTION_KEY) {
|
||||
throw new Error("ENCRYPTION_KEY is not set");
|
||||
}
|
||||
|
||||
const payload = jwt.verify(token, NEXTAUTH_SECRET, { algorithms: ["HS256"] }) as JwtPayload & {
|
||||
userId: string;
|
||||
email: string;
|
||||
provider: string;
|
||||
providerAccountId: string;
|
||||
callbackUrl: string;
|
||||
};
|
||||
|
||||
if (
|
||||
!payload?.userId ||
|
||||
!payload?.email ||
|
||||
!payload?.provider ||
|
||||
!payload?.providerAccountId ||
|
||||
!payload?.callbackUrl
|
||||
) {
|
||||
throw new Error("Token is invalid or missing required fields");
|
||||
}
|
||||
|
||||
return {
|
||||
userId: decryptWithFallback(payload.userId, ENCRYPTION_KEY),
|
||||
email: decryptWithFallback(payload.email, ENCRYPTION_KEY),
|
||||
provider: payload.provider,
|
||||
providerAccountId: decryptWithFallback(payload.providerAccountId, ENCRYPTION_KEY),
|
||||
callbackUrl: decryptWithFallback(payload.callbackUrl, ENCRYPTION_KEY),
|
||||
};
|
||||
};
|
||||
|
||||
export const verifyToken = async (token: string): Promise<TVerifyTokenPayload> => {
|
||||
if (!NEXTAUTH_SECRET) {
|
||||
throw new Error("NEXTAUTH_SECRET is not set");
|
||||
}
|
||||
@@ -263,7 +362,11 @@ export const verifyToken = async (token: string): Promise<JwtPayload> => {
|
||||
// Get user email if we don't have it yet
|
||||
userData ??= await getUserEmailForLegacyVerification(token, payload.id);
|
||||
|
||||
return { id: userData.userId, email: userData.userEmail };
|
||||
return {
|
||||
id: userData.userId,
|
||||
email: userData.userEmail,
|
||||
purpose: getVerificationTokenPurpose(payload.purpose),
|
||||
};
|
||||
};
|
||||
|
||||
export const verifyInviteToken = (token: string): { inviteId: string; email: string } => {
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
TIntegrationNotion,
|
||||
TIntegrationNotionConfig,
|
||||
TIntegrationNotionDatabase,
|
||||
} from "@formbricks/types/integration/notion";
|
||||
import { TIntegrationNotionConfig, TIntegrationNotionDatabase } from "@formbricks/types/integration/notion";
|
||||
import { ENCRYPTION_KEY } from "@/lib/constants";
|
||||
import { symmetricDecrypt } from "@/lib/crypto";
|
||||
import { getIntegrationByType } from "../integration/service";
|
||||
@@ -29,7 +25,7 @@ const fetchPages = async (config: TIntegrationNotionConfig) => {
|
||||
export const getNotionDatabases = async (environmentId: string): Promise<TIntegrationNotionDatabase[]> => {
|
||||
let results: TIntegrationNotionDatabase[] = [];
|
||||
try {
|
||||
const notionIntegration = (await getIntegrationByType(environmentId, "notion")) as TIntegrationNotion;
|
||||
const notionIntegration = await getIntegrationByType(environmentId, "notion");
|
||||
if (notionIntegration && notionIntegration.config?.key.bot_id) {
|
||||
results = await fetchPages(notionIntegration.config);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ const mapOrganizationBilling = (billing: TOrganizationWithBilling["billing"]): T
|
||||
stripeCustomerId: billing.stripeCustomerId,
|
||||
limits: billing.limits,
|
||||
usageCycleAnchor: billing.usageCycleAnchor,
|
||||
...(billing.stripe === undefined ? {} : { stripe: billing.stripe }),
|
||||
...(billing.stripe == null ? {} : { stripe: billing.stripe }),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import structuredClonePolyfill from "@ungap/structured-clone";
|
||||
|
||||
const structuredCloneExport =
|
||||
typeof structuredClone === "undefined" ? structuredClonePolyfill : structuredClone;
|
||||
const structuredCloneExport = globalThis.structuredClone;
|
||||
|
||||
export { structuredCloneExport as structuredClone };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { DatabaseError, UnknownError } from "@formbricks/types/errors";
|
||||
import { TIntegration, TIntegrationItem } from "@formbricks/types/integration";
|
||||
import { TIntegrationSlack, TIntegrationSlackCredential } from "@formbricks/types/integration/slack";
|
||||
import { TIntegrationSlackCredential } from "@formbricks/types/integration/slack";
|
||||
import { SLACK_MESSAGE_LIMIT } from "../constants";
|
||||
import { deleteIntegration, getIntegrationByType } from "../integration/service";
|
||||
import { truncateText } from "../utils/strings";
|
||||
@@ -58,7 +58,7 @@ export const fetchChannels = async (slackIntegration: TIntegration): Promise<TIn
|
||||
export const getSlackChannels = async (environmentId: string): Promise<TIntegrationItem[]> => {
|
||||
let channels: TIntegrationItem[] = [];
|
||||
try {
|
||||
const slackIntegration = (await getIntegrationByType(environmentId, "slack")) as TIntegrationSlack;
|
||||
const slackIntegration = await getIntegrationByType(environmentId, "slack");
|
||||
if (slackIntegration && slackIntegration.config?.key) {
|
||||
channels = await fetchChannels(slackIntegration);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,14 @@ const mockWelcomeCard: TSurveyWelcomeCard = {
|
||||
showResponseCount: false,
|
||||
};
|
||||
|
||||
const mockBlocks = [
|
||||
{
|
||||
id: "block1",
|
||||
name: "Block 1",
|
||||
elements: [mockQuestion],
|
||||
},
|
||||
];
|
||||
|
||||
const baseSurveyProperties = {
|
||||
id: mockId,
|
||||
name: "Mock Survey",
|
||||
@@ -201,13 +209,7 @@ const baseSurveyProperties = {
|
||||
displayLimit: 3,
|
||||
welcomeCard: mockWelcomeCard,
|
||||
questions: [],
|
||||
blocks: [
|
||||
{
|
||||
id: "block1",
|
||||
name: "Block 1",
|
||||
elements: [mockQuestion],
|
||||
},
|
||||
],
|
||||
blocks: mockBlocks as unknown as SurveyMock["blocks"],
|
||||
isBackButtonHidden: false,
|
||||
isAutoProgressingEnabled: false,
|
||||
isCaptureIpEnabled: false,
|
||||
@@ -304,6 +306,7 @@ export const createSurveyInput: TSurveyCreateInput = {
|
||||
displayOption: "respondMultiple",
|
||||
triggers: [{ actionClass: mockActionClass }],
|
||||
...baseSurveyProperties,
|
||||
blocks: mockBlocks,
|
||||
};
|
||||
|
||||
export const updateSurveyInput: TSurvey = {
|
||||
@@ -326,6 +329,7 @@ export const updateSurveyInput: TSurvey = {
|
||||
followUps: [],
|
||||
...baseSurveyProperties,
|
||||
...commonMockProperties,
|
||||
blocks: mockBlocks,
|
||||
slug: null,
|
||||
customHeadScripts: null,
|
||||
customHeadScriptsMode: null,
|
||||
|
||||
@@ -5,7 +5,8 @@ import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { ZId, ZOptionalNumber } from "@formbricks/types/common";
|
||||
import { DatabaseError, InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { TSegment, ZSegmentFilters } from "@formbricks/types/segment";
|
||||
import { ZSegmentFilters } from "@formbricks/types/segment";
|
||||
import { TSurveyBlock } from "@formbricks/types/surveys/blocks";
|
||||
import { TSurvey, TSurveyCreateInput, ZSurvey, ZSurveyCreateInput } from "@formbricks/types/surveys/types";
|
||||
import {
|
||||
getOrganizationByEnvironmentId,
|
||||
@@ -558,22 +559,7 @@ export const updateSurveyInternal = async (
|
||||
select: selectSurvey,
|
||||
});
|
||||
|
||||
let surveySegment: TSegment | null = null;
|
||||
if (prismaSurvey.segment) {
|
||||
surveySegment = {
|
||||
...prismaSurvey.segment,
|
||||
surveys: prismaSurvey.segment.surveys.map((survey) => survey.id),
|
||||
};
|
||||
}
|
||||
|
||||
const modifiedSurvey: TSurvey = {
|
||||
...prismaSurvey, // Properties from prismaSurvey
|
||||
displayPercentage: Number(prismaSurvey.displayPercentage) || null,
|
||||
segment: surveySegment,
|
||||
customHeadScriptsMode: prismaSurvey.customHeadScriptsMode,
|
||||
};
|
||||
|
||||
return modifiedSurvey;
|
||||
return transformPrismaSurvey<TSurvey>(prismaSurvey);
|
||||
} catch (error) {
|
||||
logger.error(error, "Error updating survey");
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
@@ -648,8 +634,8 @@ export const createSurvey = async (
|
||||
}
|
||||
|
||||
// Validate and prepare blocks for persistence
|
||||
if (data.blocks && data.blocks.length > 0) {
|
||||
data.blocks = validateMediaAndPrepareBlocks(data.blocks);
|
||||
if (Array.isArray(data.blocks) && data.blocks.length > 0) {
|
||||
data.blocks = validateMediaAndPrepareBlocks(data.blocks as unknown as TSurveyBlock[]);
|
||||
}
|
||||
|
||||
const survey = await prisma.survey.create({
|
||||
@@ -773,21 +759,7 @@ export const loadNewSegmentInSurvey = async (surveyId: string, newSegmentId: str
|
||||
});
|
||||
}
|
||||
|
||||
let surveySegment: TSegment | null = null;
|
||||
if (prismaSurvey.segment) {
|
||||
surveySegment = {
|
||||
...prismaSurvey.segment,
|
||||
surveys: prismaSurvey.segment.surveys.map((survey) => survey.id),
|
||||
};
|
||||
}
|
||||
|
||||
const modifiedSurvey = {
|
||||
...prismaSurvey,
|
||||
segment: surveySegment,
|
||||
customHeadScriptsMode: prismaSurvey.customHeadScriptsMode,
|
||||
};
|
||||
|
||||
return modifiedSurvey as TSurvey;
|
||||
return transformPrismaSurvey<TSurvey>(prismaSurvey);
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseError(error.message);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type Locale, formatDistance } from "date-fns";
|
||||
import { de, enUS, es, fr, hu, ja, nl, pt, ptBR, ro, ru, sv, zhCN, zhTW } from "date-fns/locale";
|
||||
import { de, enUS, es, fr, hu, ja, nl, pt, ptBR, ro, ru, sv, tr, zhCN, zhTW } from "date-fns/locale";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { formatDateForDisplay } from "./utils/datetime";
|
||||
|
||||
@@ -17,6 +17,7 @@ const TIME_SINCE_LOCALES: Record<TUserLocale, Locale> = {
|
||||
"ro-RO": ro,
|
||||
"ru-RU": ru,
|
||||
"sv-SE": sv,
|
||||
"tr-TR": tr,
|
||||
"zh-Hans-CN": zhCN,
|
||||
"zh-Hant-TW": zhTW,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
export const publicUserSelect = {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
emailVerified: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
twoFactorEnabled: true,
|
||||
identityProvider: true,
|
||||
notificationSettings: true,
|
||||
locale: true,
|
||||
lastLoginAt: true,
|
||||
isActive: true,
|
||||
} as const satisfies Prisma.UserSelect;
|
||||
|
||||
export type TPublicUser = Prisma.UserGetPayload<{
|
||||
select: typeof publicUserSelect;
|
||||
}>;
|
||||
@@ -6,6 +6,7 @@ import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { TOrganization } from "@formbricks/types/organizations";
|
||||
import { TUserLocale, TUserUpdateInput } from "@formbricks/types/user";
|
||||
import { deleteOrganization, getOrganizationsWhereUserIsSingleOwner } from "@/lib/organization/service";
|
||||
import { publicUserSelect } from "./public-user";
|
||||
import { deleteUser, getUser, getUserByEmail, getUsersWithOrganization, updateUser } from "./service";
|
||||
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
@@ -47,11 +48,6 @@ describe("User Service", () => {
|
||||
locale: "en-US" as TUserLocale,
|
||||
lastLoginAt: new Date(),
|
||||
isActive: true,
|
||||
twoFactorSecret: null,
|
||||
backupCodes: null,
|
||||
password: null,
|
||||
identityProviderAccountId: null,
|
||||
groupId: null,
|
||||
};
|
||||
|
||||
const mockOrganizations: TOrganization[] = [
|
||||
@@ -102,8 +98,12 @@ describe("User Service", () => {
|
||||
expect(result).toEqual(mockPrismaUser);
|
||||
expect(prisma.user.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: "user1" },
|
||||
select: expect.any(Object),
|
||||
select: publicUserSelect,
|
||||
});
|
||||
expect(result).not.toHaveProperty("password");
|
||||
expect(result).not.toHaveProperty("twoFactorSecret");
|
||||
expect(result).not.toHaveProperty("backupCodes");
|
||||
expect(result).not.toHaveProperty("identityProviderAccountId");
|
||||
});
|
||||
|
||||
test("should return null when user not found", async () => {
|
||||
@@ -134,7 +134,7 @@ describe("User Service", () => {
|
||||
expect(result).toEqual(mockPrismaUser);
|
||||
expect(prisma.user.findFirst).toHaveBeenCalledWith({
|
||||
where: { email: "test@example.com" },
|
||||
select: expect.any(Object),
|
||||
select: publicUserSelect,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -176,7 +176,7 @@ describe("User Service", () => {
|
||||
expect(prisma.user.update).toHaveBeenCalledWith({
|
||||
where: { id: "user1" },
|
||||
data: updateData,
|
||||
select: expect.any(Object),
|
||||
select: publicUserSelect,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -204,7 +204,7 @@ describe("User Service", () => {
|
||||
expect(deleteOrganization).toHaveBeenCalledWith("org1");
|
||||
expect(prisma.user.delete).toHaveBeenCalledWith({
|
||||
where: { id: "user1" },
|
||||
select: expect.any(Object),
|
||||
select: publicUserSelect,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -236,7 +236,7 @@ describe("User Service", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
select: expect.any(Object),
|
||||
select: publicUserSelect,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -10,21 +10,7 @@ import { TUser, TUserLocale, TUserUpdateInput, ZUserUpdateInput } from "@formbri
|
||||
import { deleteOrganization, getOrganizationsWhereUserIsSingleOwner } from "@/lib/organization/service";
|
||||
import { deleteBrevoCustomerByEmail } from "@/modules/auth/lib/brevo";
|
||||
import { validateInputs } from "../utils/validate";
|
||||
|
||||
const responseSelection = {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
emailVerified: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
twoFactorEnabled: true,
|
||||
identityProvider: true,
|
||||
notificationSettings: true,
|
||||
locale: true,
|
||||
lastLoginAt: true,
|
||||
isActive: true,
|
||||
};
|
||||
import { publicUserSelect } from "./public-user";
|
||||
|
||||
// function to retrive basic information about a user's user
|
||||
export const getUser = reactCache(async (id: string): Promise<TUser | null> => {
|
||||
@@ -35,7 +21,7 @@ export const getUser = reactCache(async (id: string): Promise<TUser | null> => {
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
select: responseSelection,
|
||||
select: publicUserSelect,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
@@ -59,7 +45,7 @@ export const getUserByEmail = reactCache(async (email: string): Promise<TUser |
|
||||
where: {
|
||||
email,
|
||||
},
|
||||
select: responseSelection,
|
||||
select: publicUserSelect,
|
||||
});
|
||||
|
||||
return user;
|
||||
@@ -82,7 +68,7 @@ export const updateUser = async (personId: string, data: TUserUpdateInput): Prom
|
||||
id: personId,
|
||||
},
|
||||
data: data,
|
||||
select: responseSelection,
|
||||
select: publicUserSelect,
|
||||
});
|
||||
|
||||
return updatedUser;
|
||||
@@ -105,7 +91,7 @@ const deleteUserById = async (id: string): Promise<TUser> => {
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
select: responseSelection,
|
||||
select: publicUserSelect,
|
||||
});
|
||||
return user;
|
||||
} catch (error) {
|
||||
@@ -153,7 +139,7 @@ export const getUsersWithOrganization = async (organizationId: string): Promise<
|
||||
},
|
||||
},
|
||||
},
|
||||
select: responseSelection,
|
||||
select: publicUserSelect,
|
||||
});
|
||||
|
||||
return users;
|
||||
@@ -174,7 +160,7 @@ export const getUserLocale = reactCache(async (id: string): Promise<TUserLocale
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
select: responseSelection,
|
||||
select: publicUserSelect,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
export type DebouncedFunction<T extends (...args: any[]) => void> = ((...args: Parameters<T>) => void) & {
|
||||
cancel: () => void;
|
||||
};
|
||||
|
||||
export const debounce = <T extends (...args: any[]) => void>(
|
||||
callback: T,
|
||||
delay: number
|
||||
): DebouncedFunction<T> => {
|
||||
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
||||
|
||||
const debounced = ((...args: Parameters<T>) => {
|
||||
if (timeoutId !== undefined) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
timeoutId = setTimeout(() => callback(...args), delay);
|
||||
}) as DebouncedFunction<T>;
|
||||
|
||||
debounced.cancel = () => {
|
||||
if (timeoutId !== undefined) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
return debounced;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
export const capitalize = (value: string): string => {
|
||||
if (!value) return "";
|
||||
|
||||
return `${value.charAt(0).toUpperCase()}${value.slice(1).toLowerCase()}`;
|
||||
};
|
||||
|
||||
export const isDeepEqual = (left: unknown, right: unknown): boolean => {
|
||||
if (Object.is(left, right)) return true;
|
||||
|
||||
if (left instanceof Date && right instanceof Date) {
|
||||
return left.getTime() === right.getTime();
|
||||
}
|
||||
|
||||
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.isArray(left) || Array.isArray(right)) {
|
||||
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
|
||||
|
||||
return left.every((item, index) => isDeepEqual(item, right[index]));
|
||||
}
|
||||
|
||||
const leftRecord = left as Record<string, unknown>;
|
||||
const rightRecord = right as Record<string, unknown>;
|
||||
const leftKeys = Object.keys(leftRecord);
|
||||
const rightKeys = Object.keys(rightRecord);
|
||||
|
||||
if (leftKeys.length !== rightKeys.length) return false;
|
||||
|
||||
return leftKeys.every(
|
||||
(key) =>
|
||||
Object.prototype.hasOwnProperty.call(rightRecord, key) && isDeepEqual(leftRecord[key], rightRecord[key])
|
||||
);
|
||||
};
|
||||
@@ -54,7 +54,7 @@ export const findRecallInfoById = (text: string, id: string): string | null => {
|
||||
return match ? match[0] : null;
|
||||
};
|
||||
|
||||
const getRecallItemLabel = <T extends TSurvey>(
|
||||
export const getRecallItemLabel = <T extends TSurvey>(
|
||||
recallItemId: string,
|
||||
survey: T,
|
||||
languageCode: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { isSafeIdentifier } from "./safe-identifier";
|
||||
import { isSafeIdentifier, toSafeIdentifier } from "./safe-identifier";
|
||||
|
||||
describe("safe-identifier", () => {
|
||||
describe("isSafeIdentifier", () => {
|
||||
@@ -32,4 +32,23 @@ describe("safe-identifier", () => {
|
||||
expect(isSafeIdentifier("")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("toSafeIdentifier", () => {
|
||||
test("normalizes free-form labels into safe identifiers", () => {
|
||||
expect(toSafeIdentifier("Date of Birth")).toBe("date_of_birth");
|
||||
expect(toSafeIdentifier("Customer-ID")).toBe("customer_id");
|
||||
expect(toSafeIdentifier(" Preferred Language ")).toBe("preferred_language");
|
||||
expect(toSafeIdentifier("city__name")).toBe("city_name");
|
||||
});
|
||||
|
||||
test("strips invalid leading characters until first lowercase letter", () => {
|
||||
expect(toSafeIdentifier("123 Date")).toBe("date");
|
||||
expect(toSafeIdentifier("__name")).toBe("name");
|
||||
expect(toSafeIdentifier("99")).toBe("");
|
||||
});
|
||||
|
||||
test("keeps already safe identifiers unchanged", () => {
|
||||
expect(toSafeIdentifier("country_code")).toBe("country_code");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,44 @@ export const isSafeIdentifier = (value: string): boolean => {
|
||||
return /^[a-z0-9_]+$/.test(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a free-form string to a safe identifier candidate.
|
||||
* The output only contains lowercase letters, numbers, and underscores.
|
||||
* It also ensures the identifier starts with a lowercase letter by stripping invalid leading chars.
|
||||
*/
|
||||
export const toSafeIdentifier = (value: string): string => {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
let safeIdentifier = "";
|
||||
let shouldInsertUnderscore = false;
|
||||
|
||||
for (const char of normalized) {
|
||||
const isLowercaseLetter = char >= "a" && char <= "z";
|
||||
const isDigit = char >= "0" && char <= "9";
|
||||
|
||||
if (isLowercaseLetter || isDigit) {
|
||||
if (shouldInsertUnderscore && safeIdentifier.length > 0) {
|
||||
safeIdentifier += "_";
|
||||
}
|
||||
safeIdentifier += char;
|
||||
shouldInsertUnderscore = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (safeIdentifier.length > 0) {
|
||||
shouldInsertUnderscore = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < safeIdentifier.length; i++) {
|
||||
const char = safeIdentifier[i];
|
||||
if (char >= "a" && char <= "z") {
|
||||
return safeIdentifier.slice(i);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a snake_case string to Title Case for display as a label.
|
||||
* Example: "job_description" -> "Job Description"
|
||||
|
||||
+45
-29
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Dein Link ist abgelaufen.",
|
||||
"link_expired_description": "Der von dir verwendete Link ist nicht mehr gültig."
|
||||
"link_expired_description": "Der von dir verwendete Link ist nicht mehr gültig.",
|
||||
"link_expired_heading": "Dein Link ist abgelaufen."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Akzeptiert",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Zentriertes Modalfenster",
|
||||
"change_organization": "Organisation wechseln",
|
||||
"change_workspace": "Workspace wechseln",
|
||||
"choice_n": "Auswahl {{n}}",
|
||||
"choices": "Entscheidungen",
|
||||
"choose_environment": "Umgebung auswählen",
|
||||
"choose_organization": "Organisation auswählen",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Schließen",
|
||||
"code": "Code",
|
||||
"collapse_rows": "Zeilen einklappen",
|
||||
"column_n": "Spalte {{n}}",
|
||||
"completed": "Abgeschlossen",
|
||||
"configuration": "Konfiguration",
|
||||
"confirm": "Bestätigen",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Fehler beim Kopieren in die Zwischenablage",
|
||||
"failed_to_load_organizations": "Fehler beim Laden der Organisationen",
|
||||
"failed_to_load_workspaces": "Projekte konnten nicht geladen werden",
|
||||
"field_placeholder": "{{field}}-Platzhalter",
|
||||
"filter": "Filter",
|
||||
"finish": "Fertigstellen",
|
||||
"first_name": "Vorname",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Generieren",
|
||||
"go_back": "Geh zurück",
|
||||
"go_to_dashboard": "Zum Dashboard gehen",
|
||||
"headline": "Überschrift",
|
||||
"hidden": "Versteckt",
|
||||
"hidden_field": "Verstecktes Feld",
|
||||
"hidden_fields": "Versteckte Felder",
|
||||
"hide_column": "Spalte ausblenden",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Bild",
|
||||
"images": "Bilder",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "Monate",
|
||||
"move_down": "Nach unten bewegen",
|
||||
"move_up": "Nach oben bewegen",
|
||||
"multiple_languages": "Mehrsprachigkeit",
|
||||
"my_product": "mein Produkt",
|
||||
"name": "Name",
|
||||
"new": "Neu",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Kein Ergebnis gefunden",
|
||||
"no_results": "Keine Ergebnisse",
|
||||
"no_surveys_found": "Keine Umfragen gefunden.",
|
||||
"no_text_found": "Kein Text gefunden",
|
||||
"none_of_the_above": "Keine der oben genannten Optionen",
|
||||
"not_authenticated": "Du bist nicht authentifiziert, um diese Aktion durchzuführen.",
|
||||
"not_authorized": "Nicht berechtigt",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Organisationseinstellungen",
|
||||
"other": "Andere",
|
||||
"other_filters": "Weitere Filter",
|
||||
"others": "Andere",
|
||||
"other_placeholder": "Sonstiger Platzhalter",
|
||||
"overlay_color": "Overlay-Farbe",
|
||||
"overview": "Überblick",
|
||||
"password": "Passwort",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Bitte aktualisieren Sie Ihren Plan",
|
||||
"powered_by_formbricks": "Bereitgestellt von Formbricks",
|
||||
"preview": "Vorschau",
|
||||
"preview_survey": "Umfragevorschau",
|
||||
"privacy": "Datenschutz",
|
||||
"product_manager": "Produktmanager",
|
||||
"production": "Produktion",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Antworten",
|
||||
"restart": "Neustart",
|
||||
"role": "Rolle",
|
||||
"row_n": "Zeile {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Vertrieb",
|
||||
"save": "Speichern",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Dateispeicher nicht eingerichtet, Uploads werden wahrscheinlich fehlschlagen",
|
||||
"string": "Text",
|
||||
"styling": "Styling",
|
||||
"subheader": "Unterüberschrift",
|
||||
"submit": "Abschicken",
|
||||
"summary": "Zusammenfassung",
|
||||
"survey": "Umfrage",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "z. B. Formbricks",
|
||||
"workspaces": "Projekte",
|
||||
"years": "Jahre",
|
||||
"you": "Du",
|
||||
"you_are_downgraded_to_the_community_edition": "Du wurdest auf die Community Edition herabgestuft.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Du bist nicht berechtigt, diese Aktion durchzuführen.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Sie haben Ihr Limit von {projectLimit} Workspaces erreicht.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Sende Daten an deine Notion Datenbank",
|
||||
"please_select_a_survey_error": "Bitte wähle eine Umfrage aus",
|
||||
"reconnect_button": "Erneut verbinden",
|
||||
"reconnect_button_description": "Deine Integrationsverbindung ist abgelaufen. Bitte verbinde dich erneut, um weiterhin Antworten zu synchronisieren. Deine bestehenden Links und Daten bleiben erhalten.",
|
||||
"reconnect_button_tooltip": "Verbinde die Integration erneut, um deinen Zugriff zu aktualisieren. Deine bestehenden Links und Daten bleiben erhalten.",
|
||||
"select_at_least_one_question_error": "Bitte wähle mindestens eine Frage aus",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Du hast bereits eine andere Umfrage mit diesem Kanal verbunden.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Alles klar! Zeit, deine erste Umfrage zu erstellen",
|
||||
"alphabetical": "alphabetisch",
|
||||
"copy_survey": "Umfrage kopieren",
|
||||
"copy_survey_description": "Kopiere diese Umfrage in eine andere Umgebung",
|
||||
"copy_survey_error": "Kopieren der Umfrage fehlgeschlagen",
|
||||
"copy_survey_link_to_clipboard": "Umfragelink in die Zwischenablage kopieren",
|
||||
"copy_survey_partially_success": "{success} Umfragen erfolgreich kopiert, {error} fehlgeschlagen.",
|
||||
"copy_survey_success": "Umfrage erfolgreich kopiert!",
|
||||
"delete_survey_and_responses_warning": "Bist Du sicher, dass Du diese Umfrage und alle ihre Antworten löschen möchtest?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Wähle die Standardsprache für diese Umfrage:",
|
||||
"2_activate_translation_for_specific_languages": "2. Übersetzung für bestimmte Sprachen aktivieren:",
|
||||
"activate_translations": "Übersetzungen aktivieren",
|
||||
"add": "+ hinzufügen",
|
||||
"add_a_delay_or_auto_close_the_survey": "Füge eine Verzögerung hinzu oder schließe die Umfrage automatisch.",
|
||||
"add_a_four_digit_pin": "Füge eine vierstellige PIN hinzu",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Publikum",
|
||||
"auto_close_on_inactivity": "Automatisches Schließen bei Inaktivität",
|
||||
"auto_progress_rating_and_nps": "Bewertungs- und NPS-Fragen automatisch fortsetzen",
|
||||
"auto_progress_rating_and_nps_description": "Fahre automatisch fort, sobald Befragte eine Antwort bei Bewertungs- oder NPS-Fragen auswählen. Dies gilt nur für Blöcke mit einer einzelnen Frage. Bei Pflichtfragen wird die Weiter-Schaltfläche ausgeblendet; bei optionalen Fragen bleibt sie zum Überspringen sichtbar.",
|
||||
"auto_progress_rating_and_nps_description": "Automatisches Weitergehen bei Einzelfragen-Blöcken. Pflichtfragen blenden Weiter aus, außer wenn \"Sonstiges\" ausgewählt ist.",
|
||||
"auto_save_disabled": "Automatisches Speichern deaktiviert",
|
||||
"auto_save_disabled_tooltip": "Ihre Umfrage wird nur im Entwurfsmodus automatisch gespeichert. So wird sichergestellt, dass öffentliche Umfragen nicht unbeabsichtigt aktualisiert werden.",
|
||||
"auto_save_on": "Automatisches Speichern an",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Änderungen werden zu Inkonsistenzen führen",
|
||||
"change_anyway": "Trotzdem ändern",
|
||||
"change_background": "Hintergrund ändern",
|
||||
"change_default": "Standard ändern",
|
||||
"change_question_type": "Fragetyp ändern",
|
||||
"change_survey_type": "Die Änderung des Umfragetypen kann vorhandenen Zugriff beeinträchtigen",
|
||||
"change_the_background_to_a_color_image_or_animation": "Hintergrund zu einer Farbe, einem Bild oder einer Animation ändern.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Wähle, wo die Umfrage durchgeführt werden soll.",
|
||||
"city": "Stadt",
|
||||
"close_survey_on_response_limit": "Umfrage bei Erreichen des Antwortlimits schließen",
|
||||
"code": "Code",
|
||||
"color": "Farbe",
|
||||
"column_used_in_logic_error": "Diese Spalte wird in der Logik der Frage {questionIndex} verwendet. Bitte entferne sie zuerst aus der Logik.",
|
||||
"columns": "Spalten",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Umfragelogo anpassen",
|
||||
"darken_or_lighten_background_of_your_choice": "Hintergrund deiner Wahl abdunkeln oder aufhellen.",
|
||||
"days_before_showing_this_survey_again": "oder mehr Tage müssen zwischen der zuletzt angezeigten Umfrage und der Anzeige dieser Umfrage vergehen.",
|
||||
"default_language": "Standardsprache",
|
||||
"delete_anyways": "Trotzdem löschen",
|
||||
"delete_block": "Block löschen",
|
||||
"delete_choice": "Auswahl löschen",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Frage duplizieren",
|
||||
"edit_link": "Bearbeitungslink",
|
||||
"edit_recall": "Erinnerung bearbeiten",
|
||||
"edit_translations": "{lang} -Übersetzungen bearbeiten",
|
||||
"element_not_found": "Frage nicht gefunden",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Befragten erlauben, die Sprache jederzeit zu wechseln. Benötigt mind. 2 aktive Sprachen.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "Spamschutz verwendet reCAPTCHA v3, um Spam-Antworten herauszufiltern.",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "Ermöglichen Sie den Befragten, längere Antworten über mehrere Zeilen zu schreiben.",
|
||||
"lower_label": "Unteres Label",
|
||||
"manage_languages": "Sprachen verwalten",
|
||||
"manage_translations": "Übersetzungen verwalten",
|
||||
"matrix_all_fields": "Alle Felder",
|
||||
"matrix_rows": "Zeilen",
|
||||
"max_file_size": "Maximale Dateigröße",
|
||||
"max_file_size_limit_is": "Die maximale Dateigrößenbeschränkung beträgt",
|
||||
"missing_first": "Fehlende zuerst",
|
||||
"move_question_to_block": "Frage in Block verschieben",
|
||||
"multiply": "Multiplizieren *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Benötigt für eine selbstgehostete Cal.com-Instanz",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Beschriftung der Schaltfläche \"Weiter\"",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Noch keine versteckten Felder. Füge das erste unten hinzu.",
|
||||
"no_images_found_for": "Keine Bilder gefunden für ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "Keine Sprachen gefunden. Füge die erste hinzu, um loszulegen.",
|
||||
"no_languages_found_add_first_one_to_get_started": "In diesem Workspace wurden keine Umfragesprachen gefunden. Füge bitte eine hinzu, um loszulegen.",
|
||||
"no_option_found": "Keine Option gefunden",
|
||||
"no_recall_items_found": "Keine Recall-Elemente gefunden",
|
||||
"no_variables_yet_add_first_one_below": "Noch keine Variablen. Füge die erste hinzu.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Bitte geben Sie eine gültige URL ein (z. B. https://beispiel.de)",
|
||||
"please_set_a_survey_trigger": "Bitte richte einen Umfrage-Trigger ein",
|
||||
"please_specify": "Bitte angeben",
|
||||
"present_your_survey_in_multiple_languages": "Präsentiere deine Umfrage in mehreren Sprachen",
|
||||
"prevent_double_submission": "Doppeltes Anbschicken verhindern",
|
||||
"prevent_double_submission_description": "Nur eine Antwort pro E-Mail-Adresse zulassen (beta)",
|
||||
"progress_saved": "Fortschritt gespeichert",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 Punkte",
|
||||
"show_block_settings": "Block-Einstellungen anzeigen",
|
||||
"show_button": "Button anzeigen",
|
||||
"show_in_order": "In Reihenfolge anzeigen",
|
||||
"show_language_switch": "Sprachwechsel anzeigen",
|
||||
"show_multiple_times": "Begrenzte Anzahl von Malen anzeigen",
|
||||
"show_only_once": "Nur einmal anzeigen",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Umfragevorschau 👀",
|
||||
"survey_styling": "Umfrage Styling",
|
||||
"survey_trigger": "Auslöser der Umfrage",
|
||||
"switch_multi_language_on_to_get_started": "Aktiviere Mehrsprachigkeit, um loszulegen 👉",
|
||||
"target_block_not_found": "Zielblock nicht gefunden",
|
||||
"targeted": "Gezielt",
|
||||
"ten_points": "10 Punkte",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Einmal anzeigen, auch wenn sie nicht antworten.",
|
||||
"then": "dann",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Diese Aktion entfernt alle Übersetzungen aus dieser Umfrage.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Dies entfernt diese Sprache und alle zugehörigen Übersetzungen aus dieser Umfrage. Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"three_points": "3 Punkte",
|
||||
"times": "Zeiten",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Um die Platzierung über alle Umfragen hinweg konsistent zu halten, kannst du",
|
||||
"translated": "Übersetzt",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Umfrage auslösen, wenn eine der Aktionen ausgeführt wird...",
|
||||
"try_lollipop_or_mountain": "Versuch 'Lolli' oder 'Berge'...",
|
||||
"type_field_id": "Feld-ID eingeben",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Lass nur Leute mit einer echten E-Mail antworten.",
|
||||
"visibility_and_recontact": "Sichtbarkeit & erneute Kontaktaufnahme",
|
||||
"visibility_and_recontact_description": "Steuern Sie, wann diese Umfrage erscheinen kann und wie oft sie erneut erscheinen kann.",
|
||||
"visible": "Sichtbar",
|
||||
"wait": "Warte",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Warte ein paar Sekunden nach dem Auslöser, bevor Du die Umfrage anzeigst",
|
||||
"waiting_time_across_surveys": "Abkühlphase (umfrageübergreifend)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "QR-Code wird heruntergeladen",
|
||||
"drop_offs": "Drop-Off Rate",
|
||||
"drop_offs_tooltip": "So oft wurde die Umfrage gestartet, aber nicht abgeschlossen.",
|
||||
"failed_to_copy_link": "Kopieren des Links fehlgeschlagen",
|
||||
"filter_added_successfully": "Filter erfolgreich hinzugefügt",
|
||||
"filter_updated_successfully": "Filter erfolgreich aktualisiert",
|
||||
"filtered_responses_csv": "Gefilterte Antworten (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Umfrage erfolgreich gelöscht",
|
||||
"survey_duplicated_successfully": "Umfrage erfolgreich dupliziert",
|
||||
"survey_duplication_error": "Duplizieren der Umfrage fehlgeschlagen",
|
||||
"templates": {
|
||||
"all_channels": "Alle Kanäle",
|
||||
"all_industries": "Alle Branchen",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Doppelte Sprache oder Sprach-ID",
|
||||
"edit_languages": "Sprachen bearbeiten",
|
||||
"identifier": "Kennung (ISO)",
|
||||
"incomplete_translations": "Unvollständige Übersetzungen",
|
||||
"language": "Sprache",
|
||||
"language_deleted_successfully": "Sprache erfolgreich gelöscht",
|
||||
"languages_updated_successfully": "Sprachen erfolgreich aktualisiert",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Bitte wähle eine Sprache aus",
|
||||
"remove_language": "Sprache entfernen",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Bitte entferne die Sprache aus diesen Umfragen, um sie aus dem Workspace zu entfernen.",
|
||||
"search_items": "Elemente suchen",
|
||||
"translate": "Übersetzen"
|
||||
"search_items": "Elemente suchen"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Hintergrundfarbe hinzufügen",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Färbt den nicht ausgefüllten Teil des Balkens.",
|
||||
"advanced_styling_field_track_height": "Track-Höhe",
|
||||
"advanced_styling_field_track_height_description": "Steuert die Dicke des Fortschrittsbalkens.",
|
||||
"advanced_styling_field_upper_label_color": "Farbe des oberen Labels",
|
||||
"advanced_styling_field_upper_label_color_description": "Färbt die kleine Beschriftung über Eingabefeldern.",
|
||||
"advanced_styling_field_upper_label_size": "Schriftgröße des oberen Labels",
|
||||
"advanced_styling_field_upper_label_size_description": "Skaliert die kleine Beschriftung über Eingabefeldern.",
|
||||
"advanced_styling_field_upper_label_weight": "Schriftstärke des oberen Labels",
|
||||
"advanced_styling_field_upper_label_weight_description": "Macht die Beschriftung leichter oder fetter.",
|
||||
"advanced_styling_field_upper_label_color": "Labelfarbe",
|
||||
"advanced_styling_field_upper_label_color_description": "Färbt die kleinen Labels über Eingabefeldern und Skalenbeschriftungen ein.",
|
||||
"advanced_styling_field_upper_label_size": "Label-Schriftgröße",
|
||||
"advanced_styling_field_upper_label_size_description": "Skaliert die kleinen Labels über Eingabefeldern und Skalenbeschriftungen.",
|
||||
"advanced_styling_field_upper_label_weight": "Label-Schriftstärke",
|
||||
"advanced_styling_field_upper_label_weight_description": "Macht die Labels dünner oder fetter.",
|
||||
"advanced_styling_section_buttons": "Buttons",
|
||||
"advanced_styling_section_headlines": "Überschriften & Beschreibungen",
|
||||
"advanced_styling_section_inputs": "Eingabefelder",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Bestätige deine E-Mail, um zu antworten",
|
||||
"verify_email_before_submission_button": "Überprüfen",
|
||||
"verify_email_before_submission_description": "Um an dieser Umfrage teilzunehmen, bitte bestätige deine E-Mail",
|
||||
"want_to_respond": "Möchtest Du antworten?"
|
||||
"want_to_respond": "Möchtest Du antworten?",
|
||||
"paused_heading": "Pausiert",
|
||||
"completed_heading": "Abgeschlossen"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Was könnten wir besser machen?",
|
||||
"identify_customer_goals_description": "Besser verstehen, ob deine Botschaften die richtigen Erwartungen an dein Produkt schaffen.",
|
||||
"identify_customer_goals_name": "Kundenziele identifizieren",
|
||||
"identify_customer_goals_question_1_choice_1": "Meine Nutzerbasis tiefgehend verstehen",
|
||||
"identify_customer_goals_question_1_choice_2": "Upselling-Möglichkeiten identifizieren",
|
||||
"identify_customer_goals_question_1_choice_3": "Das bestmögliche Produkt entwickeln",
|
||||
"identify_customer_goals_question_1_choice_4": "Die Welt beherrschen, um allen Rosenkohl zum Frühstück zu servieren",
|
||||
"identify_customer_goals_question_1_headline": "Was ist Ihr Hauptziel bei der Nutzung von $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Biete einen Rabatt an, um Einblicke in Anmeldebarrieren zu gewinnen.",
|
||||
"identify_sign_up_barriers_name": "Identifiziere Anmeldebarrieren",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Erhalte 10% Rabatt",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Hilf uns, Dich besser zu verstehen:",
|
||||
"improve_trial_conversion_question_2_button_label": "Weiter",
|
||||
"improve_trial_conversion_question_2_headline": "Das tut mir leid zu hören. Was war das größte Problem bei der Nutzung von $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Weiter",
|
||||
"improve_trial_conversion_question_3_headline": "Was haben Sie von $[projectName] erwartet?",
|
||||
"improve_trial_conversion_question_4_button_label": "Erhalte 20% Rabatt",
|
||||
"improve_trial_conversion_question_4_headline": "Das tut mir leid zu hören! Erhalte 20% Rabatt im ersten Jahr.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Wir freuen uns, dir einen 20% Rabatt auf einen Jahresplan anzubieten.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Weiter",
|
||||
"improve_trial_conversion_question_5_headline": "Was möchtest Du erreichen?",
|
||||
"improve_trial_conversion_question_5_subheader": "Bitte wähle eine der folgenden Optionen aus:",
|
||||
"improve_trial_conversion_question_5_subheader": "Bitte beschreibe unten:",
|
||||
"improve_trial_conversion_question_6_headline": "Wie löst Du dein Problem heutzutage?",
|
||||
"improve_trial_conversion_question_6_subheader": "Bitte nenne alternative Lösungen:",
|
||||
"integration_setup_survey_description": "Bewerte, wie einfach Nutzer Integrationen zu deinem Produkt hinzufügen können.",
|
||||
|
||||
+46
-30
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Your link is expired.",
|
||||
"link_expired_description": "The link you used is no longer valid."
|
||||
"link_expired_description": "The link you used is no longer valid.",
|
||||
"link_expired_heading": "Your link is expired."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Accepted",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Centered Modal",
|
||||
"change_organization": "Change organization",
|
||||
"change_workspace": "Change workspace",
|
||||
"choice_n": "Choice {{n}}",
|
||||
"choices": "Choices",
|
||||
"choose_environment": "Choose environment",
|
||||
"choose_organization": "Choose organization",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Close",
|
||||
"code": "Code",
|
||||
"collapse_rows": "Collapse rows",
|
||||
"column_n": "Column {{n}}",
|
||||
"completed": "Completed",
|
||||
"configuration": "Configuration",
|
||||
"confirm": "Confirm",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Failed to copy to clipboard",
|
||||
"failed_to_load_organizations": "Failed to load organizations",
|
||||
"failed_to_load_workspaces": "Failed to load workspaces",
|
||||
"field_placeholder": "{{field}} Placeholder",
|
||||
"filter": "Filter",
|
||||
"finish": "Finish",
|
||||
"first_name": "First Name",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Generate",
|
||||
"go_back": "Go Back",
|
||||
"go_to_dashboard": "Go to Dashboard",
|
||||
"headline": "Headline",
|
||||
"hidden": "Hidden",
|
||||
"hidden_field": "Hidden field",
|
||||
"hidden_fields": "Hidden fields",
|
||||
"hide_column": "Hide column",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Image",
|
||||
"images": "Images",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "months",
|
||||
"move_down": "Move down",
|
||||
"move_up": "Move up",
|
||||
"multiple_languages": "Multiple languages",
|
||||
"my_product": "my Product",
|
||||
"name": "Name",
|
||||
"new": "New",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "No result found",
|
||||
"no_results": "No results",
|
||||
"no_surveys_found": "No surveys found.",
|
||||
"no_text_found": "No text found",
|
||||
"none_of_the_above": "None of the above",
|
||||
"not_authenticated": "You are not authenticated to perform this action.",
|
||||
"not_authorized": "Not authorized",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Organization settings",
|
||||
"other": "Other",
|
||||
"other_filters": "Other Filters",
|
||||
"others": "Others",
|
||||
"other_placeholder": "Other Placeholder",
|
||||
"overlay_color": "Overlay color",
|
||||
"overview": "Overview",
|
||||
"password": "Password",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Please upgrade your plan",
|
||||
"powered_by_formbricks": "Powered by Formbricks",
|
||||
"preview": "Preview",
|
||||
"preview_survey": "Preview Survey",
|
||||
"privacy": "Privacy Policy",
|
||||
"product_manager": "Product Manager",
|
||||
"production": "Production",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Responses",
|
||||
"restart": "Restart",
|
||||
"role": "Role",
|
||||
"row_n": "Row {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Sales",
|
||||
"save": "Save",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "File storage not set up, uploads will likely fail",
|
||||
"string": "Text",
|
||||
"styling": "Styling",
|
||||
"subheader": "Subheader",
|
||||
"submit": "Submit",
|
||||
"summary": "Summary",
|
||||
"survey": "Survey",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "e.g. Formbricks",
|
||||
"workspaces": "Workspaces",
|
||||
"years": "years",
|
||||
"you": "You",
|
||||
"you_are_downgraded_to_the_community_edition": "You are downgraded to the Community Edition.",
|
||||
"you_are_not_authorized_to_perform_this_action": "You are not authorized to perform this action.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "You have reached your limit of {projectLimit} workspaces.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Send data to your Notion database",
|
||||
"please_select_a_survey_error": "Please select a survey",
|
||||
"reconnect_button": "Reconnect",
|
||||
"reconnect_button_description": "Your integration connection has expired. Please reconnect to continue syncing responses. Your existing links and data will be preserved.",
|
||||
"reconnect_button_tooltip": "Reconnect the integration to refresh your access. Your existing links and data will be preserved.",
|
||||
"select_at_least_one_question_error": "Please select at least one question",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "You have already connected another survey to this channel.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "You are all set! Time to create your first survey",
|
||||
"alphabetical": "Alphabetical",
|
||||
"copy_survey": "Copy survey",
|
||||
"copy_survey_description": "Copy this survey to another environment",
|
||||
"copy_survey_error": "Failed to copy survey",
|
||||
"copy_survey_link_to_clipboard": "Copy survey link to clipboard",
|
||||
"copy_survey_partially_success": "{success} surveys copied successfully, {error} failed.",
|
||||
"copy_survey_success": "Survey copied successfully",
|
||||
"delete_survey_and_responses_warning": "Are you sure you want to delete this survey and all of its responses?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Choose the default language for this survey:",
|
||||
"2_activate_translation_for_specific_languages": "2. Activate translation for specific languages:",
|
||||
"activate_translations": "Activate translations",
|
||||
"add": "Add +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Add a delay or auto-close the survey",
|
||||
"add_a_four_digit_pin": "Add a four digit PIN",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Audience",
|
||||
"auto_close_on_inactivity": "Auto close on inactivity",
|
||||
"auto_progress_rating_and_nps": "Auto-progress rating and NPS questions",
|
||||
"auto_progress_rating_and_nps_description": "Automatically advance when respondents select an answer on rating or NPS questions. This only applies to single-question blocks. Required questions hide the Next button; optional questions still show it for skipping.",
|
||||
"auto_progress_rating_and_nps_description": "Auto-advance in single-question blocks. Required questions hide Next, except when \"Other\" is selected.",
|
||||
"auto_save_disabled": "Auto-save disabled",
|
||||
"auto_save_disabled_tooltip": "Your survey is only auto-saved when in draft. This assures public surveys are not unintentionally updated.",
|
||||
"auto_save_on": "Auto-save on",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Changes will lead to inconsistencies",
|
||||
"change_anyway": "Change anyway",
|
||||
"change_background": "Change background",
|
||||
"change_default": "Change default",
|
||||
"change_question_type": "Change question type",
|
||||
"change_survey_type": "Switching survey type affects existing access",
|
||||
"change_the_background_to_a_color_image_or_animation": "Change the background to a color, image or animation.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Choose where to run the survey.",
|
||||
"city": "City",
|
||||
"close_survey_on_response_limit": "Close survey on response limit",
|
||||
"code": "Code",
|
||||
"color": "Color",
|
||||
"column_used_in_logic_error": "This column is used in logic of question {questionIndex}. Please remove it from logic first.",
|
||||
"columns": "Columns",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Customize the survey logo",
|
||||
"darken_or_lighten_background_of_your_choice": "Darken or lighten background of your choice.",
|
||||
"days_before_showing_this_survey_again": "or more days to pass between the last shown survey and showing this survey.",
|
||||
"default_language": "Default language",
|
||||
"delete_anyways": "Delete anyways",
|
||||
"delete_block": "Delete block",
|
||||
"delete_choice": "Delete choice",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Duplicate question",
|
||||
"edit_link": "Edit link",
|
||||
"edit_recall": "Edit Recall",
|
||||
"edit_translations": "Edit {lang} translations",
|
||||
"element_not_found": "Question not found",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Allow respondents to switch language at any time. Needs min. 2 active languages.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "Spam protection uses reCAPTCHA v3 to filter out the spam responses.",
|
||||
@@ -1597,11 +1602,13 @@
|
||||
"long_answer": "Long answer",
|
||||
"long_answer_toggle_description": "Allow respondents to write longer, multi-line answers.",
|
||||
"lower_label": "Lower Label",
|
||||
"manage_languages": "Manage Languages",
|
||||
"manage_languages": "Manage languages",
|
||||
"manage_translations": "Manage translations",
|
||||
"matrix_all_fields": "All fields",
|
||||
"matrix_rows": "Rows",
|
||||
"max_file_size": "Max file size",
|
||||
"max_file_size_limit_is": "Max file size limit is",
|
||||
"missing_first": "Missing first",
|
||||
"move_question_to_block": "Move question to block",
|
||||
"multiply": "Multiply *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Needed for a self-hosted Cal.com instance",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "“Next” button label",
|
||||
"no_hidden_fields_yet_add_first_one_below": "No hidden fields yet. Add the first one below.",
|
||||
"no_images_found_for": "No images found for “{query}”",
|
||||
"no_languages_found_add_first_one_to_get_started": "No languages found. Add the first one to get started.",
|
||||
"no_languages_found_add_first_one_to_get_started": "No survey languages found in this workspace. Please add one to get started.",
|
||||
"no_option_found": "No option found",
|
||||
"no_recall_items_found": "No recall items found",
|
||||
"no_variables_yet_add_first_one_below": "No variables yet. Add the first one below.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Please enter a valid URL (e.g., https://example.com)",
|
||||
"please_set_a_survey_trigger": "Please set a survey trigger",
|
||||
"please_specify": "Please specify",
|
||||
"present_your_survey_in_multiple_languages": "Present your survey in multiple languages",
|
||||
"prevent_double_submission": "Prevent double submission",
|
||||
"prevent_double_submission_description": "Only allow 1 response per email address",
|
||||
"progress_saved": "Progress saved",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 points",
|
||||
"show_block_settings": "Show Block settings",
|
||||
"show_button": "Show Button",
|
||||
"show_in_order": "Show in order",
|
||||
"show_language_switch": "Show language switch",
|
||||
"show_multiple_times": "Show a limited number of times",
|
||||
"show_only_once": "Show only once",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Survey Preview 👀",
|
||||
"survey_styling": "Survey styling",
|
||||
"survey_trigger": "Survey Trigger",
|
||||
"switch_multi_language_on_to_get_started": "Switch multi-language on to get started 👉",
|
||||
"target_block_not_found": "Target block not found",
|
||||
"targeted": "Targeted",
|
||||
"ten_points": "10 points",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Show a single time, even if they do not respond.",
|
||||
"then": "Then",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "This action will remove all the translations from this survey.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "This will remove this language and all its translations from this survey. This action cannot be undone.",
|
||||
"three_points": "3 points",
|
||||
"times": "times",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "To keep the placement over all surveys consistent, you can",
|
||||
"translated": "Translated",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Trigger survey when one of the actions is fired…",
|
||||
"try_lollipop_or_mountain": "Try “lollipop” or “mountain”…",
|
||||
"type_field_id": "Type field id",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Only let people with a real email respond.",
|
||||
"visibility_and_recontact": "Visibility & Recontact",
|
||||
"visibility_and_recontact_description": "Control when this survey can appear and how often it can reappear.",
|
||||
"visible": "Visible",
|
||||
"wait": "Wait",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Wait a few seconds after the trigger before showing the survey",
|
||||
"waiting_time_across_surveys": "Cooldown Period (across surveys)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Downloading QR code",
|
||||
"drop_offs": "Drop-Offs",
|
||||
"drop_offs_tooltip": "Number of times the survey has been started but not completed.",
|
||||
"failed_to_copy_link": "Failed to copy link",
|
||||
"filter_added_successfully": "Filter added successfully",
|
||||
"filter_updated_successfully": "Filter updated successfully",
|
||||
"filtered_responses_csv": "Filtered responses (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Survey deleted successfully",
|
||||
"survey_duplicated_successfully": "Survey duplicated successfully",
|
||||
"survey_duplication_error": "Failed to duplicate the survey.",
|
||||
"templates": {
|
||||
"all_channels": "All channels",
|
||||
"all_industries": "All industries",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Duplicate language or language ID",
|
||||
"edit_languages": "Edit languages",
|
||||
"identifier": "Identifier (ISO)",
|
||||
"incomplete_translations": "Incomplete translations",
|
||||
"language": "Language",
|
||||
"language_deleted_successfully": "Language deleted successfully",
|
||||
"languages_updated_successfully": "Languages updated successfully",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Please select a language",
|
||||
"remove_language": "Remove Language",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Please remove the language from these surveys in order to remove it from the workspace.",
|
||||
"search_items": "Search items",
|
||||
"translate": "Translate"
|
||||
"search_items": "Search items"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Add background color",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colors the unfilled portion of the bar.",
|
||||
"advanced_styling_field_track_height": "Track Height",
|
||||
"advanced_styling_field_track_height_description": "Controls the progress bar thickness.",
|
||||
"advanced_styling_field_upper_label_color": "Headline Label Color",
|
||||
"advanced_styling_field_upper_label_color_description": "Colors the small label above inputs.",
|
||||
"advanced_styling_field_upper_label_size": "Headline Label Font Size",
|
||||
"advanced_styling_field_upper_label_size_description": "Scales the small label above inputs.",
|
||||
"advanced_styling_field_upper_label_weight": "Headline Label Font Weight",
|
||||
"advanced_styling_field_upper_label_weight_description": "Makes the label lighter or bolder.",
|
||||
"advanced_styling_field_upper_label_color": "Label Color",
|
||||
"advanced_styling_field_upper_label_color_description": "Colors the small labels above inputs and scale labels.",
|
||||
"advanced_styling_field_upper_label_size": "Label Font Size",
|
||||
"advanced_styling_field_upper_label_size_description": "Scales the small labels above inputs and scale labels.",
|
||||
"advanced_styling_field_upper_label_weight": "Label Font Weight",
|
||||
"advanced_styling_field_upper_label_weight_description": "Makes the labels lighter or bolder.",
|
||||
"advanced_styling_section_buttons": "Buttons",
|
||||
"advanced_styling_section_headlines": "Headlines & Descriptions",
|
||||
"advanced_styling_section_inputs": "Inputs",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verify your email to respond",
|
||||
"verify_email_before_submission_button": "Verify",
|
||||
"verify_email_before_submission_description": "To respond to this survey, please verify your email",
|
||||
"want_to_respond": "Want to respond?"
|
||||
"want_to_respond": "Want to respond?",
|
||||
"paused_heading": "Paused",
|
||||
"completed_heading": "Completed"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "What is one thing we could do better?",
|
||||
"identify_customer_goals_description": "Better understand if your messaging creates the right expectations of the value your product provides.",
|
||||
"identify_customer_goals_name": "Identify Customer Goals",
|
||||
"identify_customer_goals_question_1_choice_1": "Understand my user base deeply",
|
||||
"identify_customer_goals_question_1_choice_2": "Identify upselling opportunities",
|
||||
"identify_customer_goals_question_1_choice_3": "Build the best possible product",
|
||||
"identify_customer_goals_question_1_choice_4": "Rule the world to make everyone breakfast brussels sprouts",
|
||||
"identify_customer_goals_question_1_headline": "What is your primary goal for using $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Offer a discount to gather insights about sign up barriers.",
|
||||
"identify_sign_up_barriers_name": "Identify Sign Up Barriers",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Get 10% discount",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Help us understand you better:",
|
||||
"improve_trial_conversion_question_2_button_label": "Next",
|
||||
"improve_trial_conversion_question_2_headline": "Sorry to hear. What was the biggest problem using $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Next",
|
||||
"improve_trial_conversion_question_3_headline": "What did you expect $[projectName] to do?",
|
||||
"improve_trial_conversion_question_4_button_label": "Get 20% off",
|
||||
"improve_trial_conversion_question_4_headline": "Sorry to hear! Get 20% off the first year.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>We are happy to offer you a 20% discount on a yearly plan.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Next",
|
||||
"improve_trial_conversion_question_5_headline": "What would you like to achieve?",
|
||||
"improve_trial_conversion_question_5_subheader": "Please select one of the following options:",
|
||||
"improve_trial_conversion_question_5_subheader": "Please describe below:",
|
||||
"improve_trial_conversion_question_6_headline": "How are you solving your problem now?",
|
||||
"improve_trial_conversion_question_6_subheader": "Please name alternative solutions:",
|
||||
"integration_setup_survey_description": "Evaluate how easily users can add integrations to your product. Find blind spots.",
|
||||
|
||||
+45
-29
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Tu enlace ha caducado.",
|
||||
"link_expired_description": "El enlace que has utilizado ya no es válido."
|
||||
"link_expired_description": "El enlace que has utilizado ya no es válido.",
|
||||
"link_expired_heading": "Tu enlace ha caducado."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Aceptado",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Modal centrado",
|
||||
"change_organization": "Cambiar organización",
|
||||
"change_workspace": "Cambiar espacio de trabajo",
|
||||
"choice_n": "Opción {{n}}",
|
||||
"choices": "Opciones",
|
||||
"choose_environment": "Elegir entorno",
|
||||
"choose_organization": "Elegir organización",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Cerrar",
|
||||
"code": "Código",
|
||||
"collapse_rows": "Contraer filas",
|
||||
"column_n": "Columna {{n}}",
|
||||
"completed": "Completado",
|
||||
"configuration": "Configuración",
|
||||
"confirm": "Confirmar",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Error al copiar al portapapeles",
|
||||
"failed_to_load_organizations": "Error al cargar organizaciones",
|
||||
"failed_to_load_workspaces": "Error al cargar los proyectos",
|
||||
"field_placeholder": "Marcador de posición de {{field}}",
|
||||
"filter": "Filtro",
|
||||
"finish": "Finalizar",
|
||||
"first_name": "Nombre",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Generar",
|
||||
"go_back": "Volver",
|
||||
"go_to_dashboard": "Ir al panel de control",
|
||||
"headline": "Titular",
|
||||
"hidden": "Oculto",
|
||||
"hidden_field": "Campo oculto",
|
||||
"hidden_fields": "Campos ocultos",
|
||||
"hide_column": "Ocultar columna",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Imagen",
|
||||
"images": "Imágenes",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "meses",
|
||||
"move_down": "Mover hacia abajo",
|
||||
"move_up": "Mover hacia arriba",
|
||||
"multiple_languages": "Múltiples idiomas",
|
||||
"my_product": "mi producto",
|
||||
"name": "Nombre",
|
||||
"new": "Nuevo",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "No se encontró resultado",
|
||||
"no_results": "Sin resultados",
|
||||
"no_surveys_found": "No se encontraron encuestas.",
|
||||
"no_text_found": "No se encontró texto",
|
||||
"none_of_the_above": "Ninguna de las anteriores",
|
||||
"not_authenticated": "No estás autenticado para realizar esta acción.",
|
||||
"not_authorized": "No autorizado",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Ajustes de la organización",
|
||||
"other": "Otro",
|
||||
"other_filters": "Otros Filtros",
|
||||
"others": "Otros",
|
||||
"other_placeholder": "Otro marcador de posición",
|
||||
"overlay_color": "Color de superposición",
|
||||
"overview": "Resumen",
|
||||
"password": "Contraseña",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Por favor, actualiza tu plan",
|
||||
"powered_by_formbricks": "Desarrollado por Formbricks",
|
||||
"preview": "Vista previa",
|
||||
"preview_survey": "Vista previa de la encuesta",
|
||||
"privacy": "Política de privacidad",
|
||||
"product_manager": "Gestor de producto",
|
||||
"production": "Producción",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Respuestas",
|
||||
"restart": "Reiniciar",
|
||||
"role": "Rol",
|
||||
"row_n": "Fila {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Ventas",
|
||||
"save": "Guardar",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Almacenamiento de archivos no configurado, es probable que fallen las subidas",
|
||||
"string": "Texto",
|
||||
"styling": "Estilo",
|
||||
"subheader": "Subtítulo",
|
||||
"submit": "Enviar",
|
||||
"summary": "Resumen",
|
||||
"survey": "Encuesta",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "p. ej. Formbricks",
|
||||
"workspaces": "Proyectos",
|
||||
"years": "años",
|
||||
"you": "Tú",
|
||||
"you_are_downgraded_to_the_community_edition": "Has sido degradado a la edición Community.",
|
||||
"you_are_not_authorized_to_perform_this_action": "No tienes autorización para realizar esta acción.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Has alcanzado tu límite de {projectLimit} espacios de trabajo.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Envía datos a tu base de datos de Notion",
|
||||
"please_select_a_survey_error": "Por favor, selecciona una encuesta",
|
||||
"reconnect_button": "Reconectar",
|
||||
"reconnect_button_description": "Tu conexión de integración ha caducado. Por favor, reconecta para seguir sincronizando las respuestas. Tus enlaces y datos existentes se conservarán.",
|
||||
"reconnect_button_tooltip": "Reconecta la integración para actualizar tu acceso. Tus enlaces y datos existentes se conservarán.",
|
||||
"select_at_least_one_question_error": "Por favor, selecciona al menos una pregunta",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Ya has conectado otra encuesta a este canal.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "¡Todo listo! Es hora de crear tu primera encuesta",
|
||||
"alphabetical": "Alfabético",
|
||||
"copy_survey": "Copiar encuesta",
|
||||
"copy_survey_description": "Copia esta encuesta a otro entorno",
|
||||
"copy_survey_error": "Error al copiar la encuesta",
|
||||
"copy_survey_link_to_clipboard": "Copiar enlace de la encuesta al portapapeles",
|
||||
"copy_survey_partially_success": "{success} encuestas copiadas correctamente, {error} fallidas.",
|
||||
"copy_survey_success": "¡Encuesta copiada correctamente!",
|
||||
"delete_survey_and_responses_warning": "¿Estás seguro de que quieres eliminar esta encuesta y todas sus respuestas?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Elige el idioma predeterminado para esta encuesta:",
|
||||
"2_activate_translation_for_specific_languages": "2. Activa la traducción para idiomas específicos:",
|
||||
"activate_translations": "Activar traducciones",
|
||||
"add": "Añadir +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Añadir un retraso o cerrar automáticamente la encuesta",
|
||||
"add_a_four_digit_pin": "Añadir un PIN de cuatro dígitos",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Audiencia",
|
||||
"auto_close_on_inactivity": "Cierre automático por inactividad",
|
||||
"auto_progress_rating_and_nps": "Avanzar automáticamente en preguntas de valoración y NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avanza automáticamente cuando los encuestados seleccionen una respuesta en preguntas de valoración o NPS. Esto solo se aplica a bloques de una sola pregunta. Las preguntas obligatorias ocultan el botón Siguiente; las preguntas opcionales aún lo muestran para omitirlas.",
|
||||
"auto_progress_rating_and_nps_description": "Avance automático en bloques de una sola pregunta. Las preguntas obligatorias ocultan Siguiente, excepto cuando se selecciona \"Otro\".",
|
||||
"auto_save_disabled": "Guardado automático desactivado",
|
||||
"auto_save_disabled_tooltip": "Su encuesta solo se guarda automáticamente cuando está en borrador. Esto asegura que las encuestas públicas no se actualicen involuntariamente.",
|
||||
"auto_save_on": "Guardado automático activado",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Los cambios provocarán inconsistencias",
|
||||
"change_anyway": "Cambiar de todos modos",
|
||||
"change_background": "Cambiar fondo",
|
||||
"change_default": "Cambiar predeterminado",
|
||||
"change_question_type": "Cambiar tipo de pregunta",
|
||||
"change_survey_type": "Cambiar el tipo de encuesta afecta al acceso existente",
|
||||
"change_the_background_to_a_color_image_or_animation": "Cambiar el fondo a un color, imagen o animación.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Elige dónde ejecutar la encuesta.",
|
||||
"city": "Ciudad",
|
||||
"close_survey_on_response_limit": "Cerrar encuesta al alcanzar el límite de respuestas",
|
||||
"code": "Código",
|
||||
"color": "Color",
|
||||
"column_used_in_logic_error": "Esta columna se usa en la lógica de la pregunta {questionIndex}. Por favor, elimínala de la lógica primero.",
|
||||
"columns": "Columnas",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Personalizar el logotipo de la encuesta",
|
||||
"darken_or_lighten_background_of_your_choice": "Oscurece o aclara el fondo de tu elección.",
|
||||
"days_before_showing_this_survey_again": "o más días deben transcurrir entre la última encuesta mostrada y la visualización de esta encuesta.",
|
||||
"default_language": "Idioma predeterminado",
|
||||
"delete_anyways": "Eliminar de todos modos",
|
||||
"delete_block": "Eliminar bloque",
|
||||
"delete_choice": "Eliminar opción",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Duplicar pregunta",
|
||||
"edit_link": "Editar enlace",
|
||||
"edit_recall": "Editar recuperación",
|
||||
"edit_translations": "Editar traducciones de {lang}",
|
||||
"element_not_found": "Pregunta no encontrada",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permitir a los participantes cambiar el idioma de la encuesta en cualquier momento durante la encuesta.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "La protección contra spam utiliza reCAPTCHA v3 para filtrar las respuestas spam.",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "Permitir a los encuestados escribir respuestas más largas y de varias líneas.",
|
||||
"lower_label": "Etiqueta inferior",
|
||||
"manage_languages": "Gestionar idiomas",
|
||||
"manage_translations": "Gestionar traducciones",
|
||||
"matrix_all_fields": "Todos los campos",
|
||||
"matrix_rows": "Filas",
|
||||
"max_file_size": "Tamaño máximo de archivo",
|
||||
"max_file_size_limit_is": "El límite de tamaño máximo de archivo es",
|
||||
"missing_first": "Faltantes primero",
|
||||
"move_question_to_block": "Mover pregunta al bloque",
|
||||
"multiply": "Multiplicar *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Necesario para una instancia Cal.com autohospedada",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Etiqueta del botón \"Siguiente\"",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Aún no hay campos ocultos. Añade el primero a continuación.",
|
||||
"no_images_found_for": "No se encontraron imágenes para ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "No se encontraron idiomas. Añade el primero para comenzar.",
|
||||
"no_languages_found_add_first_one_to_get_started": "No se encontraron idiomas de encuesta en este espacio de trabajo. Por favor, añade uno para comenzar.",
|
||||
"no_option_found": "No se encontró ninguna opción",
|
||||
"no_recall_items_found": "No se encontraron elementos de recuperación",
|
||||
"no_variables_yet_add_first_one_below": "No hay variables todavía. Añade la primera a continuación.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Por favor, introduce una URL válida (p. ej., https://example.com)",
|
||||
"please_set_a_survey_trigger": "Establece un disparador de encuesta",
|
||||
"please_specify": "Por favor, especifica",
|
||||
"present_your_survey_in_multiple_languages": "Presenta tu encuesta en varios idiomas",
|
||||
"prevent_double_submission": "Evitar envío duplicado",
|
||||
"prevent_double_submission_description": "Permitir solo 1 respuesta por dirección de correo electrónico",
|
||||
"progress_saved": "Progreso guardado",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 puntos",
|
||||
"show_block_settings": "Mostrar ajustes del bloque",
|
||||
"show_button": "Mostrar botón",
|
||||
"show_in_order": "Mostrar en orden",
|
||||
"show_language_switch": "Mostrar cambio de idioma",
|
||||
"show_multiple_times": "Mostrar un número limitado de veces",
|
||||
"show_only_once": "Mostrar solo una vez",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Vista previa de la encuesta 👀",
|
||||
"survey_styling": "Estilo del formulario",
|
||||
"survey_trigger": "Activador de la encuesta",
|
||||
"switch_multi_language_on_to_get_started": "Activa el modo multiidioma para comenzar 👉",
|
||||
"target_block_not_found": "Bloque objetivo no encontrado",
|
||||
"targeted": "Dirigido",
|
||||
"ten_points": "10 puntos",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Mostrar una sola vez, incluso si no responden.",
|
||||
"then": "Entonces",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Esta acción eliminará todas las traducciones de esta encuesta.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Esto eliminará este idioma y todas sus traducciones de esta encuesta. Esta acción no se puede deshacer.",
|
||||
"three_points": "3 puntos",
|
||||
"times": "veces",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Para mantener la ubicación coherente en todas las encuestas, puedes",
|
||||
"translated": "Traducido",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Activar encuesta cuando se dispare una de las acciones...",
|
||||
"try_lollipop_or_mountain": "Prueba 'piruleta' o 'montaña'...",
|
||||
"type_field_id": "Escribe el id del campo",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Solo permite responder a personas con un correo electrónico real.",
|
||||
"visibility_and_recontact": "Visibilidad y recontacto",
|
||||
"visibility_and_recontact_description": "Controla cuándo puede aparecer esta encuesta y con qué frecuencia puede volver a aparecer.",
|
||||
"visible": "Visible",
|
||||
"wait": "Esperar",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Esperar unos segundos después del disparador antes de mostrar la encuesta",
|
||||
"waiting_time_across_surveys": "Periodo de espera (entre encuestas)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Descargando código QR",
|
||||
"drop_offs": "Abandonos",
|
||||
"drop_offs_tooltip": "Número de veces que se ha iniciado la encuesta pero no se ha completado.",
|
||||
"failed_to_copy_link": "Error al copiar el enlace",
|
||||
"filter_added_successfully": "Filtro añadido correctamente",
|
||||
"filter_updated_successfully": "Filtro actualizado correctamente",
|
||||
"filtered_responses_csv": "Respuestas filtradas (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "¡Encuesta eliminada correctamente!",
|
||||
"survey_duplicated_successfully": "Encuesta duplicada correctamente.",
|
||||
"survey_duplication_error": "Error al duplicar la encuesta.",
|
||||
"templates": {
|
||||
"all_channels": "Todos los canales",
|
||||
"all_industries": "Todas las industrias",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Idioma o ID de idioma duplicado",
|
||||
"edit_languages": "Editar idiomas",
|
||||
"identifier": "Identificador (ISO)",
|
||||
"incomplete_translations": "Traducciones incompletas",
|
||||
"language": "Idioma",
|
||||
"language_deleted_successfully": "Idioma eliminado correctamente",
|
||||
"languages_updated_successfully": "Idiomas actualizados correctamente",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Por favor, selecciona un idioma",
|
||||
"remove_language": "Eliminar idioma",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Por favor, elimina el idioma de estas encuestas para poder eliminarlo del espacio de trabajo.",
|
||||
"search_items": "Buscar elementos",
|
||||
"translate": "Traducir"
|
||||
"search_items": "Buscar elementos"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Añadir color de fondo",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colorea la parte no rellenada de la barra.",
|
||||
"advanced_styling_field_track_height": "Altura de la pista",
|
||||
"advanced_styling_field_track_height_description": "Controla el grosor de la barra de progreso.",
|
||||
"advanced_styling_field_upper_label_color": "Color de la etiqueta del titular",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorea la etiqueta pequeña sobre los campos de entrada.",
|
||||
"advanced_styling_field_upper_label_size": "Tamaño de fuente de la etiqueta del titular",
|
||||
"advanced_styling_field_upper_label_size_description": "Escala la etiqueta pequeña sobre los campos de entrada.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosor de fuente de la etiqueta del titular",
|
||||
"advanced_styling_field_upper_label_weight_description": "Hace que la etiqueta sea más ligera o más gruesa.",
|
||||
"advanced_styling_field_upper_label_color": "Color de etiqueta",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorea las pequeñas etiquetas sobre los campos de entrada y las etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_size": "Tamaño de fuente de etiqueta",
|
||||
"advanced_styling_field_upper_label_size_description": "Escala las pequeñas etiquetas sobre los campos de entrada y las etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosor de fuente de etiqueta",
|
||||
"advanced_styling_field_upper_label_weight_description": "Hace que las etiquetas sean más ligeras o más gruesas.",
|
||||
"advanced_styling_section_buttons": "Botones",
|
||||
"advanced_styling_section_headlines": "Títulos y descripciones",
|
||||
"advanced_styling_section_inputs": "Campos de entrada",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verifica tu correo electrónico para responder",
|
||||
"verify_email_before_submission_button": "Verificar",
|
||||
"verify_email_before_submission_description": "Para responder a esta encuesta, por favor verifica tu correo electrónico",
|
||||
"want_to_respond": "¿Quieres responder?"
|
||||
"want_to_respond": "¿Quieres responder?",
|
||||
"paused_heading": "Pausado",
|
||||
"completed_heading": "Completado"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "¿Qué es una cosa que podríamos mejorar?",
|
||||
"identify_customer_goals_description": "Comprende mejor si tus mensajes crean las expectativas correctas sobre el valor que proporciona tu producto.",
|
||||
"identify_customer_goals_name": "Identificar objetivos del cliente",
|
||||
"identify_customer_goals_question_1_choice_1": "Comprender en profundidad a mi base de usuarios",
|
||||
"identify_customer_goals_question_1_choice_2": "Identificar oportunidades de venta adicional",
|
||||
"identify_customer_goals_question_1_choice_3": "Construir el mejor producto posible",
|
||||
"identify_customer_goals_question_1_choice_4": "Conquistar el mundo para que todos desayunen coles de Bruselas",
|
||||
"identify_customer_goals_question_1_headline": "¿Cuál es tu objetivo principal al usar $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Ofrece un descuento para obtener información sobre las barreras de registro.",
|
||||
"identify_sign_up_barriers_name": "Identificar barreras de registro",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Obtener 10 % de descuento",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Ayúdanos a entenderte mejor:",
|
||||
"improve_trial_conversion_question_2_button_label": "Siguiente",
|
||||
"improve_trial_conversion_question_2_headline": "Lamentamos oír eso. ¿Cuál fue el mayor problema al usar $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Siguiente",
|
||||
"improve_trial_conversion_question_3_headline": "¿Qué esperabas que hiciera $[projectName]?",
|
||||
"improve_trial_conversion_question_4_button_label": "Obtener 20 % de descuento",
|
||||
"improve_trial_conversion_question_4_headline": "¡Sentimos oírlo! Obtén un 20 % de descuento en el primer año.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Nos complace ofrecerte un 20 % de descuento en un plan anual.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Siguiente",
|
||||
"improve_trial_conversion_question_5_headline": "¿Qué te gustaría conseguir?",
|
||||
"improve_trial_conversion_question_5_subheader": "Por favor, selecciona una de las siguientes opciones:",
|
||||
"improve_trial_conversion_question_5_subheader": "Por favor, describe a continuación:",
|
||||
"improve_trial_conversion_question_6_headline": "¿Cómo estás solucionando tu problema ahora?",
|
||||
"improve_trial_conversion_question_6_subheader": "Por favor, nombra soluciones alternativas:",
|
||||
"integration_setup_survey_description": "Evalúa con qué facilidad los usuarios pueden añadir integraciones a tu producto. Encuentra puntos ciegos.",
|
||||
|
||||
+45
-29
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Votre lien est expiré.",
|
||||
"link_expired_description": "Le lien que vous avez utilisé n'est plus valide."
|
||||
"link_expired_description": "Le lien que vous avez utilisé n'est plus valide.",
|
||||
"link_expired_heading": "Votre lien est expiré."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Accepté",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Au centre",
|
||||
"change_organization": "Changer d'organisation",
|
||||
"change_workspace": "Changer d'espace de travail",
|
||||
"choice_n": "Choix {{n}}",
|
||||
"choices": "Choix",
|
||||
"choose_environment": "Choisir l'environnement",
|
||||
"choose_organization": "Choisir l'organisation",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Fermer",
|
||||
"code": "Code",
|
||||
"collapse_rows": "Réduire les lignes",
|
||||
"column_n": "Colonne {{n}}",
|
||||
"completed": "Terminé",
|
||||
"configuration": "Configuration",
|
||||
"confirm": "Confirmer",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Échec de la copie dans le presse-papiers",
|
||||
"failed_to_load_organizations": "Échec du chargement des organisations",
|
||||
"failed_to_load_workspaces": "Échec du chargement des projets",
|
||||
"field_placeholder": "Espace réservé {{field}}",
|
||||
"filter": "Filtre",
|
||||
"finish": "Terminer",
|
||||
"first_name": "Prénom",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Générer",
|
||||
"go_back": "Retourner",
|
||||
"go_to_dashboard": "Aller au tableau de bord",
|
||||
"headline": "Titre principal",
|
||||
"hidden": "Caché",
|
||||
"hidden_field": "Champ caché",
|
||||
"hidden_fields": "Champs cachés",
|
||||
"hide_column": "Cacher la colonne",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Image",
|
||||
"images": "Images",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "mois",
|
||||
"move_down": "Déplacer vers le bas",
|
||||
"move_up": "Déplacer vers le haut",
|
||||
"multiple_languages": "Plusieurs langues",
|
||||
"my_product": "mon produit",
|
||||
"name": "Nom",
|
||||
"new": "Nouveau",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Aucun résultat trouvé",
|
||||
"no_results": "Aucun résultat",
|
||||
"no_surveys_found": "Aucun sondage trouvé.",
|
||||
"no_text_found": "Aucun texte trouvé",
|
||||
"none_of_the_above": "Aucun des éléments ci-dessus",
|
||||
"not_authenticated": "Vous n'êtes pas authentifié pour effectuer cette action.",
|
||||
"not_authorized": "Non autorisé",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Paramètres de l'organisation",
|
||||
"other": "Autre",
|
||||
"other_filters": "Autres filtres",
|
||||
"others": "Autres",
|
||||
"other_placeholder": "Autre espace réservé",
|
||||
"overlay_color": "Couleur de superposition",
|
||||
"overview": "Aperçu",
|
||||
"password": "Mot de passe",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Veuillez mettre à niveau votre plan",
|
||||
"powered_by_formbricks": "Propulsé par Formbricks",
|
||||
"preview": "Aperçu",
|
||||
"preview_survey": "Aperçu de l'enquête",
|
||||
"privacy": "Politique de confidentialité",
|
||||
"product_manager": "Chef de produit",
|
||||
"production": "Production",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Réponses",
|
||||
"restart": "Recommencer",
|
||||
"role": "Rôle",
|
||||
"row_n": "Ligne {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Ventes",
|
||||
"save": "Enregistrer",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Stockage de fichiers non configuré, les téléchargements risquent d'échouer",
|
||||
"string": "Texte",
|
||||
"styling": "Style",
|
||||
"subheader": "Sous-titre",
|
||||
"submit": "Soumettre",
|
||||
"summary": "Résumé",
|
||||
"survey": "Enquête",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "par ex. Formbricks",
|
||||
"workspaces": "Projets",
|
||||
"years": "années",
|
||||
"you": "Vous",
|
||||
"you_are_downgraded_to_the_community_edition": "Vous êtes rétrogradé à l'édition communautaire.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Vous n'êtes pas autorisé à effectuer cette action.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Vous avez atteint votre limite de {projectLimit} espaces de travail.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Envoyez des données à votre base de données Notion.",
|
||||
"please_select_a_survey_error": "Veuillez sélectionner une enquête.",
|
||||
"reconnect_button": "Reconnecter",
|
||||
"reconnect_button_description": "Ta connexion à l'intégration a expiré. Reconnecte-toi pour continuer à synchroniser les réponses. Tes liens et données existants seront conservés.",
|
||||
"reconnect_button_tooltip": "Reconnecte l'intégration pour actualiser ton accès. Tes liens et données existants seront conservés.",
|
||||
"select_at_least_one_question_error": "Veuillez sélectionner au moins une question.",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Vous avez déjà connecté une autre enquête à ce canal.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Vous êtes prêt ! Il est temps de créer votre première enquête.",
|
||||
"alphabetical": "Alphabétique",
|
||||
"copy_survey": "Copier l'enquête",
|
||||
"copy_survey_description": "Copier cette enquête dans un autre environnement",
|
||||
"copy_survey_error": "Échec de la copie du sondage",
|
||||
"copy_survey_link_to_clipboard": "Copier le lien du sondage dans le presse-papiers",
|
||||
"copy_survey_partially_success": "{success} enquêtes copiées avec succès, {error} échouées.",
|
||||
"copy_survey_success": "Enquête copiée avec succès !",
|
||||
"delete_survey_and_responses_warning": "Êtes-vous sûr de vouloir supprimer cette enquête et toutes ses réponses?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Choisissez la langue par défaut pour ce sondage :",
|
||||
"2_activate_translation_for_specific_languages": "2. Activer la traduction pour des langues spécifiques:",
|
||||
"activate_translations": "Activer les traductions",
|
||||
"add": "Ajouter +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Ajouter un délai ou fermer automatiquement l'enquête",
|
||||
"add_a_four_digit_pin": "Ajoutez un code PIN à quatre chiffres.",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Public",
|
||||
"auto_close_on_inactivity": "Fermeture automatique en cas d'inactivité",
|
||||
"auto_progress_rating_and_nps": "Progression automatique pour les questions d'évaluation et NPS",
|
||||
"auto_progress_rating_and_nps_description": "Passe automatiquement à la question suivante lorsque les répondants sélectionnent une réponse aux questions d'évaluation ou NPS. Cela s'applique uniquement aux blocs à question unique. Les questions obligatoires masquent le bouton Suivant ; les questions facultatives l'affichent toujours pour permettre de passer la question.",
|
||||
"auto_progress_rating_and_nps_description": "Avancement automatique dans les blocs à question unique. Les questions obligatoires masquent le bouton Suivant, sauf lorsque « Autre » est sélectionné.",
|
||||
"auto_save_disabled": "Sauvegarde automatique désactivée",
|
||||
"auto_save_disabled_tooltip": "Votre sondage n'est sauvegardé automatiquement que lorsqu'il est en brouillon. Cela garantit que les sondages publics ne sont pas mis à jour involontairement.",
|
||||
"auto_save_on": "Sauvegarde automatique activée",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Les changements entraîneront des incohérences.",
|
||||
"change_anyway": "Changer de toute façon",
|
||||
"change_background": "Changer l'arrière-plan",
|
||||
"change_default": "Modifier la langue par défaut",
|
||||
"change_question_type": "Changer le type de question",
|
||||
"change_survey_type": "Le changement de type de sondage affecte l'accès existant",
|
||||
"change_the_background_to_a_color_image_or_animation": "Changez l'arrière-plan en une couleur, une image ou une animation.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Choisissez où réaliser l'enquête.",
|
||||
"city": "Ville",
|
||||
"close_survey_on_response_limit": "Fermer l'enquête sur la limite de réponse",
|
||||
"code": "Code",
|
||||
"color": "Couleur",
|
||||
"column_used_in_logic_error": "Cette colonne est utilisée dans la logique de la question {questionIndex}. Veuillez d'abord la supprimer de la logique.",
|
||||
"columns": "Colonnes",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Personnaliser le logo de l'enquête",
|
||||
"darken_or_lighten_background_of_your_choice": "Assombrir ou éclaircir l'arrière-plan de votre choix.",
|
||||
"days_before_showing_this_survey_again": "ou plus de jours doivent s'écouler entre le dernier sondage affiché et l'affichage de ce sondage.",
|
||||
"default_language": "Langue par défaut",
|
||||
"delete_anyways": "Supprimer quand même",
|
||||
"delete_block": "Supprimer le bloc",
|
||||
"delete_choice": "Supprimer l'option",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Dupliquer la question",
|
||||
"edit_link": "Modifier le lien",
|
||||
"edit_recall": "Modifier le rappel",
|
||||
"edit_translations": "Modifier les traductions {lang}",
|
||||
"element_not_found": "Question non trouvée",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permettre aux répondants de changer de langue à tout moment. Nécessite au moins 2 langues actives.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "La protection contre le spam utilise reCAPTCHA v3 pour filtrer les réponses indésirables.",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "Permettre aux répondants d'écrire des réponses plus longues et sur plusieurs lignes.",
|
||||
"lower_label": "Étiquette inférieure",
|
||||
"manage_languages": "Gérer les langues",
|
||||
"manage_translations": "Gérer les traductions",
|
||||
"matrix_all_fields": "Tous les champs",
|
||||
"matrix_rows": "Lignes",
|
||||
"max_file_size": "Taille maximale du fichier",
|
||||
"max_file_size_limit_is": "La limite de taille maximale du fichier est",
|
||||
"missing_first": "Manquantes en premier",
|
||||
"move_question_to_block": "Déplacer la question vers le bloc",
|
||||
"multiply": "Multiplier *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Nécessaire pour une instance Cal.com auto-hébergée",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Libellé du bouton « Suivant »",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Aucun champ caché pour le moment. Ajoutez le premier ci-dessous.",
|
||||
"no_images_found_for": "Aucune image trouvée pour ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "Aucune langue trouvée. Ajoutez la première pour commencer.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Aucune langue d'enquête trouvée dans cet espace de travail. Veuillez en ajouter une pour commencer.",
|
||||
"no_option_found": "Aucune option trouvée",
|
||||
"no_recall_items_found": "Aucun élément de rappel trouvé",
|
||||
"no_variables_yet_add_first_one_below": "Aucune variable pour le moment. Ajoutez la première ci-dessous.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Veuillez entrer une URL valide (par exemple, https://example.com)",
|
||||
"please_set_a_survey_trigger": "Veuillez définir un déclencheur d'enquête.",
|
||||
"please_specify": "Veuillez préciser",
|
||||
"present_your_survey_in_multiple_languages": "Présente ton questionnaire dans plusieurs langues",
|
||||
"prevent_double_submission": "Empêcher la double soumission",
|
||||
"prevent_double_submission_description": "Autoriser uniquement 1 réponse par adresse e-mail",
|
||||
"progress_saved": "Progression enregistrée",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 points",
|
||||
"show_block_settings": "Afficher les paramètres du bloc",
|
||||
"show_button": "Afficher le bouton",
|
||||
"show_in_order": "Afficher dans l'ordre",
|
||||
"show_language_switch": "Afficher le changement de langue",
|
||||
"show_multiple_times": "Afficher un nombre limité de fois",
|
||||
"show_only_once": "Afficher une seule fois",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Aperçu du sondage 👀",
|
||||
"survey_styling": "Style de formulaire",
|
||||
"survey_trigger": "Déclencheur d'enquête",
|
||||
"switch_multi_language_on_to_get_started": "Activez le mode multilingue pour commencer 👉",
|
||||
"target_block_not_found": "Bloc cible non trouvé",
|
||||
"targeted": "Ciblé",
|
||||
"ten_points": "10 points",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Afficher une seule fois, même si la personne ne répond pas.",
|
||||
"then": "Alors",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Cette action supprimera toutes les traductions de cette enquête.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Cela supprimera cette langue et toutes ses traductions de ce questionnaire. Cette action est irréversible.",
|
||||
"three_points": "3 points",
|
||||
"times": "fois",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Pour maintenir la cohérence du placement sur tous les sondages, vous pouvez",
|
||||
"translated": "Traduit",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Déclencher l'enquête lorsqu'une des actions est déclenchée...",
|
||||
"try_lollipop_or_mountain": "Essayez 'sucette' ou 'montagne'...",
|
||||
"type_field_id": "Identifiant de champ de type",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Ne laissez répondre que les personnes ayant une véritable adresse e-mail.",
|
||||
"visibility_and_recontact": "Visibilité et recontact",
|
||||
"visibility_and_recontact_description": "Contrôlez quand cette enquête peut apparaître et à quelle fréquence elle peut réapparaître.",
|
||||
"visible": "Visible",
|
||||
"wait": "Attendre",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Attendez quelques secondes après le déclencheur avant de montrer l'enquête.",
|
||||
"waiting_time_across_surveys": "Période de refroidissement (entre les sondages)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Téléchargement du code QR",
|
||||
"drop_offs": "Dépôts",
|
||||
"drop_offs_tooltip": "Nombre de fois que l'enquête a été commencée mais non terminée.",
|
||||
"failed_to_copy_link": "Échec de la copie du lien",
|
||||
"filter_added_successfully": "Filtre ajouté avec succès",
|
||||
"filter_updated_successfully": "Filtre mis à jour avec succès",
|
||||
"filtered_responses_csv": "Réponses filtrées (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Enquête supprimée avec succès !",
|
||||
"survey_duplicated_successfully": "Enquête dupliquée avec succès.",
|
||||
"survey_duplication_error": "Échec de la duplication de l'enquête.",
|
||||
"templates": {
|
||||
"all_channels": "Tous les canaux",
|
||||
"all_industries": "Tous les secteurs",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Langue ou identifiant de langue en double",
|
||||
"edit_languages": "Modifier les langues",
|
||||
"identifier": "Identifiant (ISO)",
|
||||
"incomplete_translations": "Traductions incomplètes",
|
||||
"language": "Langue",
|
||||
"language_deleted_successfully": "Langue supprimée avec succès",
|
||||
"languages_updated_successfully": "Langues mises à jour avec succès",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Veuillez sélectionner une langue",
|
||||
"remove_language": "Supprimer la langue",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Veuillez supprimer la langue de ces sondages afin de la retirer de l'espace de travail.",
|
||||
"search_items": "Rechercher des éléments",
|
||||
"translate": "Traduire"
|
||||
"search_items": "Rechercher des éléments"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Ajouter une couleur d'arrière-plan",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colore la partie non remplie de la barre.",
|
||||
"advanced_styling_field_track_height": "Hauteur de la piste",
|
||||
"advanced_styling_field_track_height_description": "Contrôle l'épaisseur de la barre de progression.",
|
||||
"advanced_styling_field_upper_label_color": "Couleur de l'étiquette du titre",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore le petit libellé au-dessus des champs de saisie.",
|
||||
"advanced_styling_field_upper_label_size": "Taille de police de l'étiquette du titre",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajuste la taille du petit libellé au-dessus des champs de saisie.",
|
||||
"advanced_styling_field_upper_label_weight": "Graisse de police de l'étiquette du titre",
|
||||
"advanced_styling_field_upper_label_weight_description": "Rend le libellé plus léger ou plus gras.",
|
||||
"advanced_styling_field_upper_label_color": "Couleur de l'étiquette",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore les petites étiquettes au-dessus des champs de saisie et des échelles.",
|
||||
"advanced_styling_field_upper_label_size": "Taille de police de l'étiquette",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajuste la taille des petites étiquettes au-dessus des champs de saisie et des échelles.",
|
||||
"advanced_styling_field_upper_label_weight": "Graisse de police de l'étiquette",
|
||||
"advanced_styling_field_upper_label_weight_description": "Rend les étiquettes plus légères ou plus grasses.",
|
||||
"advanced_styling_section_buttons": "Boutons",
|
||||
"advanced_styling_section_headlines": "Titres et descriptions",
|
||||
"advanced_styling_section_inputs": "Champs de saisie",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Vérifiez votre email pour répondre.",
|
||||
"verify_email_before_submission_button": "Vérifier",
|
||||
"verify_email_before_submission_description": "Pour répondre à cette enquête, veuillez vérifier votre e-mail.",
|
||||
"want_to_respond": "Voulez-vous répondre ?"
|
||||
"want_to_respond": "Voulez-vous répondre ?",
|
||||
"paused_heading": "En pause",
|
||||
"completed_heading": "Terminé"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Quelle est une chose que nous pourrions améliorer ?",
|
||||
"identify_customer_goals_description": "Mieux comprendre si votre message crée les bonnes attentes quant à la valeur que votre produit apporte.",
|
||||
"identify_customer_goals_name": "Identifier les objectifs des clients",
|
||||
"identify_customer_goals_question_1_choice_1": "Comprendre ma base d'utilisateurs en profondeur",
|
||||
"identify_customer_goals_question_1_choice_2": "Identifier des opportunités de montée en gamme",
|
||||
"identify_customer_goals_question_1_choice_3": "Créer le meilleur produit possible",
|
||||
"identify_customer_goals_question_1_choice_4": "Conquérir le monde pour imposer des choux de Bruxelles au petit-déjeuner à tout le monde",
|
||||
"identify_customer_goals_question_1_headline": "Quel est votre objectif principal pour l'utilisation de $[projectName] ?",
|
||||
"identify_sign_up_barriers_description": "Offrir une remise pour recueillir des informations sur les obstacles à l'inscription.",
|
||||
"identify_sign_up_barriers_name": "Identifier les obstacles à l'inscription",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Obtenez 10 % de réduction",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Aidez-nous à mieux vous comprendre :",
|
||||
"improve_trial_conversion_question_2_button_label": "Suivant",
|
||||
"improve_trial_conversion_question_2_headline": "Désolé d'apprendre cela. Quel était le plus gros problème rencontré avec $[projectName] ?",
|
||||
"improve_trial_conversion_question_3_button_label": "Suivant",
|
||||
"improve_trial_conversion_question_3_headline": "Qu'attendiez-vous de $[projectName] ?",
|
||||
"improve_trial_conversion_question_4_button_label": "Obtenez 20 % de réduction",
|
||||
"improve_trial_conversion_question_4_headline": "Désolé d'apprendre cela ! Bénéficiez de 20 % de réduction sur la première année.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Nous sommes heureux de vous offrir une remise de 20 % sur un plan annuel.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Suivant",
|
||||
"improve_trial_conversion_question_5_headline": "Que souhaitez-vous accomplir ?",
|
||||
"improve_trial_conversion_question_5_subheader": "Veuillez sélectionner l'une des options suivantes :",
|
||||
"improve_trial_conversion_question_5_subheader": "Merci de décrire ci-dessous :",
|
||||
"improve_trial_conversion_question_6_headline": "Comment résolvez-vous votre problème maintenant ?",
|
||||
"improve_trial_conversion_question_6_subheader": "Veuillez nommer des solutions alternatives :",
|
||||
"integration_setup_survey_description": "Évaluez la facilité avec laquelle les utilisateurs peuvent ajouter des intégrations à votre produit. Identifiez les points aveugles.",
|
||||
|
||||
+91
-75
@@ -63,8 +63,8 @@
|
||||
"login_with_email": "Bejelentkezés e-mail-címmel",
|
||||
"lost_access": "Elvesztette a hozzáférést?",
|
||||
"new_to_formbricks": "Új a Formbicksen?",
|
||||
"oauth_account_not_linked_description": "This SSO provider is not linked to an existing Formbricks account. Please sign in with the method you used originally. If that was email and password, complete email verification first if you are prompted.",
|
||||
"oauth_account_not_linked_title": "This SSO sign-in could not be linked",
|
||||
"oauth_account_not_linked_description": "Ez az SSO-szolgáltató nincs összekapcsolva egy meglévő Formbricks-fiókkal. Jelentkezzen be az eredetileg használt módszerrel. Ha ez e-mail és jelszó páros volt, akkor először végezze el az e-mail-ellenőrzést, ha a rendszer erre kéri.",
|
||||
"oauth_account_not_linked_title": "Ezt az SSO-bejelentkezést nem sikerült összekapcsolni",
|
||||
"use_a_backup_code": "Visszaszerzési kód használata"
|
||||
},
|
||||
"saml_connection_error": "Valami probléma történt. A további részletekért nézze meg az alkalmazás konzolját.",
|
||||
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "A hivatkozása lejárt.",
|
||||
"link_expired_description": "Az Ön által használt hivatkozás már nem érvényes."
|
||||
"link_expired_description": "Az Ön által használt hivatkozás már nem érvényes.",
|
||||
"link_expired_heading": "A hivatkozása lejárt."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Elfogadva",
|
||||
@@ -150,8 +151,9 @@
|
||||
"bottom_right": "Jobbra lent",
|
||||
"cancel": "Mégse",
|
||||
"centered_modal": "Középre helyezett kizárólagos",
|
||||
"change_organization": "Szervezet módosítása",
|
||||
"change_workspace": "Munkaterület módosítása",
|
||||
"change_organization": "Szervezet megváltoztatása",
|
||||
"change_workspace": "Munkaterület megváltoztatása",
|
||||
"choice_n": "{{n}}. választás",
|
||||
"choices": "Választási lehetőségek",
|
||||
"choose_environment": "Környezet kiválasztása",
|
||||
"choose_organization": "Szervezet kiválasztása",
|
||||
@@ -165,13 +167,14 @@
|
||||
"close": "Bezárás",
|
||||
"code": "Kód",
|
||||
"collapse_rows": "Sorok összecsukása",
|
||||
"column_n": "{{n}}. oszlop",
|
||||
"completed": "Befejezve",
|
||||
"configuration": "Beállítás",
|
||||
"confirm": "Megerősítés",
|
||||
"connect": "Kapcsolódás",
|
||||
"connect_formbricks": "Kapcsolódás a Formbrickshez",
|
||||
"connected": "Kapcsolódva",
|
||||
"contact": "Kapcsolat",
|
||||
"contact": "Partner",
|
||||
"contacts": "Partnerek",
|
||||
"continue": "Folytatás",
|
||||
"copied": "Másolva",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Nem sikerült másolni a vágólapra",
|
||||
"failed_to_load_organizations": "Nem sikerült betölteni a szervezeteket",
|
||||
"failed_to_load_workspaces": "Nem sikerült a munkaterületek betöltése",
|
||||
"field_placeholder": "{{field}} helykitöltője",
|
||||
"filter": "Szűrő",
|
||||
"finish": "Befejezés",
|
||||
"first_name": "Keresztnév",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Előállítás",
|
||||
"go_back": "Vissza",
|
||||
"go_to_dashboard": "Ugrás a vezérlőpultra",
|
||||
"headline": "Főcím",
|
||||
"hidden": "Rejtett",
|
||||
"hidden_field": "Rejtett mező",
|
||||
"hidden_fields": "Rejtett mezők",
|
||||
"hide_column": "Oszlop elrejtése",
|
||||
"html": "HTML",
|
||||
"id": "Azonosító",
|
||||
"image": "Kép",
|
||||
"images": "Képek",
|
||||
@@ -267,7 +273,7 @@
|
||||
"invite": "Meghívás",
|
||||
"invite_them": "Meghívó nekik",
|
||||
"javascript_required": "JavaScript szükséges",
|
||||
"javascript_required_description": "A Formbricks használatához JavaScript szükséges. Kérjük, engedélyezze a JavaScriptet a böngésző beállításaiban a folytatáshoz.",
|
||||
"javascript_required_description": "A Formbricks megfelelő működéséhez JavaScript szükséges. Engedélyezze a JavaScriptet a böngésző beállításaiban a folytatáshoz.",
|
||||
"key": "Kulcs",
|
||||
"label": "Címke",
|
||||
"language": "Nyelv",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "hónap",
|
||||
"move_down": "Mozgatás le",
|
||||
"move_up": "Mozgatás fel",
|
||||
"multiple_languages": "Több nyelv",
|
||||
"my_product": "saját termék",
|
||||
"name": "Név",
|
||||
"new": "Új",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Nem található eredmény",
|
||||
"no_results": "Nincs találat",
|
||||
"no_surveys_found": "Nem találhatók kérdőívek.",
|
||||
"no_text_found": "Nem található szöveg",
|
||||
"none_of_the_above": "A fentiek közül egyik sem",
|
||||
"not_authenticated": "Nincs jogosultsága ennek a műveletnek a végrehajtásához.",
|
||||
"not_authorized": "Nincs felhatalmazva",
|
||||
@@ -321,9 +327,9 @@
|
||||
"notifications": "Értesítések",
|
||||
"number": "Szám",
|
||||
"off": "Ki",
|
||||
"offline_all_responses_synced": "Az Ön válasza sikeresen mentésre került.",
|
||||
"offline_syncing_responses": "Az Ön válaszainak szinkronizálása folyamatban…",
|
||||
"offline_you_are_offline": "Ön offline állapotban van. Az Ön válasza a böngészőjében tárolásra került, és mentésre kerül, amint ismét online lesz.",
|
||||
"offline_all_responses_synced": "A válasz sikeresen el lett mentve.",
|
||||
"offline_syncing_responses": "Válaszok szinkronizálása…",
|
||||
"offline_you_are_offline": "Ön nem érhető el. A válasza a böngészőjében van tárolva, és akkor lesz elmentve, ha újra elérhető lesz.",
|
||||
"on": "Be",
|
||||
"only_one_file_allowed": "Csak egy fájl engedélyezett",
|
||||
"only_owners_managers_and_manage_access_members_can_perform_this_action": "Csak tulajdonosok és kezelők hajthatják végre ezt a műveletet.",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Szervezet beállításai",
|
||||
"other": "Egyéb",
|
||||
"other_filters": "Egyéb szűrők",
|
||||
"others": "Mások",
|
||||
"other_placeholder": "Egyéb helykitöltő",
|
||||
"overlay_color": "Rávetítés színe",
|
||||
"overview": "Áttekintés",
|
||||
"password": "Jelszó",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Váltson magasabb csomagra",
|
||||
"powered_by_formbricks": "A gépházban: Formbricks",
|
||||
"preview": "Előnézet",
|
||||
"preview_survey": "Kérdőív előnézete",
|
||||
"privacy": "Adatvédelmi irányelvek",
|
||||
"product_manager": "Termékmenedzser",
|
||||
"production": "Produktív",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Válaszok",
|
||||
"restart": "Újraindítás",
|
||||
"role": "Szerep",
|
||||
"row_n": "{{n}}. sor",
|
||||
"saas": "SaaS",
|
||||
"sales": "Értékesítés",
|
||||
"save": "Mentés",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "A fájltároló nincs beállítva, a feltöltések valószínűleg sikertelenek lesznek",
|
||||
"string": "Szöveg",
|
||||
"styling": "Stíluskészítés",
|
||||
"subheader": "Alcím",
|
||||
"submit": "Elküldés",
|
||||
"summary": "Összegzés",
|
||||
"survey": "Kérdőív",
|
||||
@@ -440,7 +447,7 @@
|
||||
"team_name": "Csapat neve",
|
||||
"team_role": "Csapatszerep",
|
||||
"teams": "Csapatok",
|
||||
"terms_of_service": "Felhasználási feltételek",
|
||||
"terms_of_service": "Használati feltételek",
|
||||
"text": "Szöveg",
|
||||
"time": "Idő",
|
||||
"time_to_finish": "Idő a befejezésig",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "például Formbricks",
|
||||
"workspaces": "Munkaterületek",
|
||||
"years": "év",
|
||||
"you": "Ön",
|
||||
"you_are_downgraded_to_the_community_edition": "Visszaváltott a közösségi kiadásra.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Nincs felhatalmazva ennek a műveletnek a végrehajtásához.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Elérte a(z) {projectLimit} munkaterületből álló korlátot.",
|
||||
@@ -550,7 +556,7 @@
|
||||
"verification_email_heading": "Már majdnem kész vagyunk!",
|
||||
"verification_email_hey": "Helló 👋",
|
||||
"verification_email_if_expired_request_new_token": "Ha lejárt, kérjen új tokent itt:",
|
||||
"verification_email_link_valid_for_24_hours": "A hivatkozás 24 órán keresztül érvényes.",
|
||||
"verification_email_link_valid_for_24_hours": "A hivatkozás 24 óráig érvényes.",
|
||||
"verification_email_request_new_verification": "Új ellenőrzés kérése",
|
||||
"verification_email_subject": "Ellenőrizze az e-mail-címét a Formbricks használatához",
|
||||
"verification_email_survey_name": "Kérdőív neve",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Adatok küldése a Notion-adatbázisba",
|
||||
"please_select_a_survey_error": "Válasszon kérdőívet",
|
||||
"reconnect_button": "Újracsatlakozás",
|
||||
"reconnect_button_description": "Az integráció kapcsolata lejárt. Kérjük, csatlakozzon újra a válaszok szinkronizálásának folytatásához. A meglévő hivatkozások és adatok megmaradnak.",
|
||||
"reconnect_button_tooltip": "Csatlakoztassa újra az integrációt a hozzáférés frissítéséhez. A meglévő hivatkozások és adatok megmaradnak.",
|
||||
"select_at_least_one_question_error": "Válasszon legalább egy kérdést",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Már hozzákapcsolt egy másik kérdőívet ehhez a csatornához.",
|
||||
@@ -859,16 +868,16 @@
|
||||
"created_by_third_party": "Harmadik fél által létrehozva",
|
||||
"discord_webhook_not_supported": "A Discord webhorgok jelenleg nem támogatottak.",
|
||||
"empty_webhook_message": "A webhorgai itt fognak megjelenni, amint hozzáadja azokat. ⏲️",
|
||||
"endpoint_bad_gateway_error": "Hibás átjáró (502): Proxy-/átjáróhiba, a szolgáltatás nem érhető el",
|
||||
"endpoint_gateway_timeout_error": "Átjáró időtúllépés (504): Átjáró időtúllépés, a szolgáltatás nem érhető el",
|
||||
"endpoint_internal_server_error": "Belső szerverhiba (500): A szolgáltatás váratlan hibába ütközött",
|
||||
"endpoint_method_not_allowed_error": "A metódus nem engedélyezett (405): A végpont létezik, de nem fogad POST kéréseket",
|
||||
"endpoint_not_found_error": "Nem található (404): A végpont nem létezik",
|
||||
"endpoint_bad_gateway_error": "Hibás átjáró (502): proxy- vagy átjáróhiba, a szolgáltatás nem érhető el",
|
||||
"endpoint_gateway_timeout_error": "Átjáró időtúllépés (504): átjáró időtúllépés, a szolgáltatás nem érhető el",
|
||||
"endpoint_internal_server_error": "Belső kiszolgálóhiba (500): a szolgáltatás váratlan hibába ütközött",
|
||||
"endpoint_method_not_allowed_error": "A módszer nem engedélyezett (405): a végpont létezik, de nem fogad POST-kéréseket",
|
||||
"endpoint_not_found_error": "Nem található (404): a végpont nem létezik",
|
||||
"endpoint_pinged": "Hurrá! Képesek vagyunk pingelni a webhorgot!",
|
||||
"endpoint_pinged_error": "Nem lehet pingelni a webhorgot!",
|
||||
"endpoint_service_unavailable_error": "A szolgáltatás nem érhető el (503): A szolgáltatás átmenetileg nem elérhető",
|
||||
"endpoint_service_unavailable_error": "A szolgáltatás nem érhető el (503): a szolgáltatás átmenetileg nem érhető el",
|
||||
"learn_to_verify": "Tudja meg, hogy kell ellenőrizni a webhorog aláírásait",
|
||||
"no_triggers": "Nincsenek Triggerek",
|
||||
"no_triggers": "Nincsenek aktiválók",
|
||||
"please_check_console": "További részletekért nézze meg a konzolt",
|
||||
"please_enter_a_url": "Adjon meg egy URL-t",
|
||||
"response_created": "Válasz létrehozva",
|
||||
@@ -884,7 +893,7 @@
|
||||
"webhook_created": "Webhorog létrehozva",
|
||||
"webhook_delete_confirmation": "Biztosan törölni szeretné ezt a webhorgot? Ez le fogja állítani a jövőbeli értesítések küldését.",
|
||||
"webhook_deleted_successfully": "A webhorog sikeresen törölve",
|
||||
"webhook_name_placeholder": "Választható: címkézze meg a webhorgot az egyszerű azonosításért",
|
||||
"webhook_name_placeholder": "Elhagyható: címkézze meg a webhorgot az egyszerű azonosításért",
|
||||
"webhook_test_failed_due_to": "A webhorog tesztelése sikertelen a következő miatt:",
|
||||
"webhook_updated_successfully": "A webhorog sikeresen frissítve",
|
||||
"webhook_url_placeholder": "Illessze be azt az URL-t, amelyen az eseményt aktiválni szeretné"
|
||||
@@ -1010,9 +1019,9 @@
|
||||
"plan_change_applied": "A csomag sikeresen frissítve.",
|
||||
"plan_change_scheduled": "A csomagváltoztatás sikeresen ütemezve.",
|
||||
"plan_custom": "Egyéni",
|
||||
"plan_feature_everything_in_hobby": "Minden a Hobbi csomagban",
|
||||
"plan_feature_everything_in_hobby": "Minden a Hobby csomagban",
|
||||
"plan_feature_everything_in_pro": "Minden a Pro csomagban",
|
||||
"plan_hobby": "Hobbi",
|
||||
"plan_hobby": "Hobby",
|
||||
"plan_hobby_description": "Magánszemélyeknek és kis csapatoknak, akik most teszik meg a kezdeti lépéseket a Formbricks Cloud szolgáltatással.",
|
||||
"plan_hobby_feature_responses": "250 válasz/hónap",
|
||||
"plan_hobby_feature_workspaces": "1 munkaterület",
|
||||
@@ -1020,11 +1029,11 @@
|
||||
"plan_pro_description": "Növekvő csapatoknak, akiknek magasabb korlátokra, automatizálásra és dinamikus túllépési lehetőségekre van szükségük.",
|
||||
"plan_pro_feature_responses": "2000 válasz/hónap (dinamikus túllépés)",
|
||||
"plan_pro_feature_workspaces": "3 munkaterület",
|
||||
"plan_scale": "Méretezés",
|
||||
"plan_scale": "Scale",
|
||||
"plan_scale_description": "Nagyobb csapatoknak, amelyeknek több kapacitásra, erősebb irányításra és nagyobb válaszmennyiségre van szükségük.",
|
||||
"plan_scale_feature_responses": "5000 válasz/hónap (dinamikus túllépés)",
|
||||
"plan_scale_feature_workspaces": "5 munkaterület",
|
||||
"plan_selection_description": "Hobbi, Pro és Méretezés csomagok összehasonlítása, majd csomagok közötti váltás közvetlenül a Formbricksben.",
|
||||
"plan_selection_description": "Hobby, Pro és Scale csomagok összehasonlítása, majd csomagok közötti váltás közvetlenül a Formbricksben.",
|
||||
"plan_selection_title": "Csomag kiválasztása",
|
||||
"plan_unknown": "Ismeretlen",
|
||||
"remove_branding": "Márkajel eltávolítása",
|
||||
@@ -1032,7 +1041,7 @@
|
||||
"select_plan_header_subtitle": "Nincs szükség hitelkártyára, nincs kötöttség.",
|
||||
"select_plan_header_title": "Zökkenőmentesen integrált kérdőívek, 100%-ban az Ön márkájához igazítva.",
|
||||
"status_trialing": "Próbaidőszak",
|
||||
"stay_on_hobby_plan": "A Hobbi csomagnál szeretnék maradni",
|
||||
"stay_on_hobby_plan": "A Hobby csomagnál szeretnék maradni",
|
||||
"stripe_setup_incomplete": "A számlázási beállítás befejezetlen",
|
||||
"stripe_setup_incomplete_description": "A számlázási beállítás nem fejeződött be sikeresen. Próbálja meg újra aktiválni az előfizetését.",
|
||||
"subscription": "Előfizetés",
|
||||
@@ -1137,17 +1146,17 @@
|
||||
"unlock_the_full_power_of_formbricks_free_for_30_days": "A Formbricks teljes erejének feloldása. 30 napig ingyen."
|
||||
},
|
||||
"general": {
|
||||
"ai_data_analysis_disabled_for_organization": "Az MI-alapú adatelemzés és adatgazdagítás ki van kapcsolva ennél a szervezetnél.",
|
||||
"ai_data_analysis_enabled": "Adatgazdagítás és elemzés (AI)",
|
||||
"ai_data_analysis_enabled_description": "AI segítségével többet hozhat ki az adataiból, irányítópultokat, diagramokat, jelentéseket és egyebeket állíthat be. Hozzáfér az élményekhez kapcsolódó adatokhoz.",
|
||||
"ai_enabled": "Formbricks AI",
|
||||
"ai_enabled_description": "AI-alapú funkciók kezelése ehhez a szervezethez.",
|
||||
"ai_data_analysis_disabled_for_organization": "Az MI-adatelemzés le van tiltva ennél a szervezetnél.",
|
||||
"ai_data_analysis_enabled": "Adatgazdagítás és -elemzés (MI)",
|
||||
"ai_data_analysis_enabled_description": "Mesterséges intelligencia ahhoz, hogy többet hozzon ki az adataiból. Vezérlőpultok, diagramok, jelentések és még sok más beállítása. Az élményadatokra is kiterjed.",
|
||||
"ai_enabled": "Formbricks MI",
|
||||
"ai_enabled_description": "MI-alapú funkciók kezelése ennél a szervezetnél.",
|
||||
"ai_features_not_enabled_for_organization": "Az MI-funkciók nincsenek engedélyezve ennél a szervezetnél.",
|
||||
"ai_instance_not_configured": "Az MI példányszinten, környezeti változókkal van konfigurálva. Kérd meg a rendszergazdát, hogy állítsa be az AI_PROVIDER értékét, a szolgáltató hitelesítő adatait és a megfelelő modelllistát, mielőtt engedélyezné az MI-funkciókat.",
|
||||
"ai_settings_updated_successfully": "AI beállítások sikeresen frissítve",
|
||||
"ai_smart_tools_disabled_for_organization": "Az MI intelligens funkciói ki vannak kapcsolva ennél a szervezetnél.",
|
||||
"ai_smart_tools_enabled": "Intelligens funkciók (AI)",
|
||||
"ai_smart_tools_enabled_description": "AI segítségével kevesebb idő alatt többet érhet el. Soha nem fér hozzá a Formbricks által gyűjtött adatokhoz. Csak például felmérések más nyelvekre történő fordításához használatos.",
|
||||
"ai_instance_not_configured": "Az MI példányszinten van beállítva környezeti változókon keresztül. Kérje meg az adminisztrátort, hogy állítsa be az AI_PROVIDER, AI_MODEL és a hozzájuk tartozó szolgáltató hitelesítési adatait, mielőtt engedélyezné az MI-funkciókat.",
|
||||
"ai_settings_updated_successfully": "Az MI-beállítások sikeresen frissítve",
|
||||
"ai_smart_tools_disabled_for_organization": "Az MI intelligens eszközei le vannak tiltva ennél a szervezetnél.",
|
||||
"ai_smart_tools_enabled": "Intelligens funkcionalitás (MI)",
|
||||
"ai_smart_tools_enabled_description": "Mesterséges intelligencia ahhoz, hogy segítsen Önnek többet elérni kevesebb idő alatt. Soha sem érinti a Formbricks segítségével gyűjtött adatokat. Csak például a kérdőívek más nyelvekre történő fordításához kerül felhasználásra.",
|
||||
"bulk_invite_warning_description": "Az ingyenes csomagban az összes szervezeti tag mindig a „Tulajdonos” szerephez van hozzárendelve.",
|
||||
"cannot_delete_only_organization": "Ez az egyetlen szervezete, nem lehet törölni. Először hozzon létre egy új szervezetet.",
|
||||
"cannot_leave_only_organization": "Nem hagyhatja el ezt a szervezetet, mivel ez az egyetlen szervezete. Először hozzon létre egy új szervezetet.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Mindent beállított! Ideje létrehozni az első kérdőívet",
|
||||
"alphabetical": "Ábécé-sorrend",
|
||||
"copy_survey": "Kérdőív másolása",
|
||||
"copy_survey_description": "A kérdőív másolása egy másik környezetbe",
|
||||
"copy_survey_error": "Nem sikerült másolni a kérdőívet",
|
||||
"copy_survey_link_to_clipboard": "Kérdőív hivatkozásának másolása a vágólapra",
|
||||
"copy_survey_partially_success": "{success} kérdőív sikeresen másolva, {error} sikertelen.",
|
||||
"copy_survey_success": "A kérdőív sikeresen másolva",
|
||||
"delete_survey_and_responses_warning": "Biztosan törölni szeretné ezt a kérdőívet és az összes válaszát?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Válassza ki a kérdőív alapértelmezett nyelvét:",
|
||||
"2_activate_translation_for_specific_languages": "2. Aktiválja a fordítást bizonyos nyelvekhez:",
|
||||
"activate_translations": "Fordítások aktiválása",
|
||||
"add": "Hozzáadás +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Késleltetés hozzáadása vagy a kérdőív automatikus lezárása",
|
||||
"add_a_four_digit_pin": "Négy számjegyű PIN-kód hozzáadása",
|
||||
@@ -1359,8 +1362,8 @@
|
||||
"assign": "= hozzárendelése",
|
||||
"audience": "Közönség",
|
||||
"auto_close_on_inactivity": "Automatikus lezárás tétlenségnél",
|
||||
"auto_progress_rating_and_nps": "Automatikus továbblépés értékelési és NPS kérdéseknél",
|
||||
"auto_progress_rating_and_nps_description": "Automatikus továbblépés, amikor a válaszadók kiválasztanak egy választ az értékelési vagy NPS kérdéseknél. Ez csak az egykérdéses blokkokra vonatkozik. A kötelező kérdések elrejtik a Tovább gombot; az opcionális kérdések továbbra is megjelenítik azt a kihagyás lehetősége érdekében.",
|
||||
"auto_progress_rating_and_nps": "Értékelés és valós ügyfél-támogatottsági érték kérdések automatikus feldolgozása",
|
||||
"auto_progress_rating_and_nps_description": "Automatikus továbblépés az egykérdéses blokkokban. A kötelező kérdések elrejtik a „Tovább” gombot, kivéve ha az „Egyéb” van kiválasztva.",
|
||||
"auto_save_disabled": "Az automatikus mentés letiltva",
|
||||
"auto_save_disabled_tooltip": "A kérdőív csak akkor kerül automatikusan mentésre, ha piszkozatban van. Ez biztosítja, hogy a nyilvános kérdőívek ne legyenek véletlenül frissítve.",
|
||||
"auto_save_on": "Automatikus mentés bekapcsolva",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "A változtatások következetlenségekhez vezetnek",
|
||||
"change_anyway": "Változtatás mindenképp",
|
||||
"change_background": "Háttér megváltoztatása",
|
||||
"change_default": "Alapértelmezett megváltoztatása",
|
||||
"change_question_type": "Kérdés típusának megváltoztatása",
|
||||
"change_survey_type": "A kérdőív típusának megváltoztatása befolyásolja a meglévő hozzáférést",
|
||||
"change_the_background_to_a_color_image_or_animation": "A háttér megváltoztatása színre, képre vagy animációra.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Annak kiválasztása, hogy hol fusson a kérdőív.",
|
||||
"city": "Város",
|
||||
"close_survey_on_response_limit": "Kérdőív lezárása a válaszkorlátnál",
|
||||
"code": "Kód",
|
||||
"color": "Szín",
|
||||
"column_used_in_logic_error": "Ez az oszlop használatban van a(z) {questionIndex}. kérdés logikájában. Először távolítsa el a logikából.",
|
||||
"columns": "Oszlopok",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "A kérdőív logójának személyre szabása",
|
||||
"darken_or_lighten_background_of_your_choice": "A választási lehetőség hátterének sötétítése vagy világosítása.",
|
||||
"days_before_showing_this_survey_again": "vagy több napnak kell eltelnie az utolsó megjelenített kérdőív és ezen kérdőív megjelenése között.",
|
||||
"default_language": "Alapértelmezett nyelv",
|
||||
"delete_anyways": "Törlés mindenképp",
|
||||
"delete_block": "Blokk törlése",
|
||||
"delete_choice": "Választási lehetőség törlése",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Kérdés kettőzése",
|
||||
"edit_link": "Hivatkozás szerkesztése",
|
||||
"edit_recall": "Visszahívás szerkesztése",
|
||||
"edit_translations": "{lang} fordítások szerkesztése",
|
||||
"element_not_found": "A kérdés nem található",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Lehetővé tétel a válaszadóknak, hogy bármikor nyelvet váltsanak. Legalább 2 aktív nyelvet igényel.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "A szemét elleni védekezés a reCAPTCHA v3-at használja a kéretlen válaszok kiszűréséhez.",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "Lehetővé tétel a válaszadóknak, hogy hosszabb, többsoros válaszokat írjanak.",
|
||||
"lower_label": "Alsó címke",
|
||||
"manage_languages": "Nyelvek kezelése",
|
||||
"manage_translations": "Fordítások kezelése",
|
||||
"matrix_all_fields": "Összes mező",
|
||||
"matrix_rows": "Sorok",
|
||||
"max_file_size": "Legnagyobb fájlméret",
|
||||
"max_file_size_limit_is": "A legnagyobb fájlméretkorlát",
|
||||
"missing_first": "Hiányzik az első",
|
||||
"move_question_to_block": "Kérdés áthelyezése egy blokkba",
|
||||
"multiply": "Szorzás *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Saját üzemeltetésű Cal.com-példányhoz szükséges",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "A „Következő” gomb címkéje",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Még nincsenek rejtett mezők. Adja hozzá az elsőt lent.",
|
||||
"no_images_found_for": "Nem találhatók képek a(z) „{query}” lekérdezéshez",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nem találhatók nyelvek. Adja hozzá az elsőt a kezdéshez.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nem találhatók kérdőívnyelvek ezen a munkaterületen. Adja hozzá egyet a kezdéshez.",
|
||||
"no_option_found": "Nem található lehetőség",
|
||||
"no_recall_items_found": "Nem találhatók visszahívási elemek",
|
||||
"no_variables_yet_add_first_one_below": "Még nincsenek változók. Adja hozzá az elsőt lent.",
|
||||
@@ -1620,7 +1627,7 @@
|
||||
"only_people_who_match_your_targeting_can_be_surveyed": "Csak azok a személyek kérdezhetők meg, akik megfelelnek a célcsoportnak.",
|
||||
"option_idx": "{choiceIndex}. lehetőség",
|
||||
"option_used_in_logic_error": "Ez a lehetőség használatban van a(z) {questionIndex}. kérdés logikájában. Először távolítsa el a logikából.",
|
||||
"optional": "Választható",
|
||||
"optional": "Elhagyható",
|
||||
"options": "Beállítások*",
|
||||
"options_used_in_logic_bulk_error": "A következő lehetőségek használatban vannak a logikában: {questionIndexes}. Először távolítsa el azokat a logikából.",
|
||||
"override_theme_with_individual_styles_for_this_survey": "A téma felülírása egyéni stílusokkal ennél a kérdőívnél.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Adjon meg egy érvényes URL-t (például https://example.com)",
|
||||
"please_set_a_survey_trigger": "Állítson be kérdőív-aktiválót",
|
||||
"please_specify": "Adja meg",
|
||||
"present_your_survey_in_multiple_languages": "A kérdőív bemutatása több nyelven",
|
||||
"prevent_double_submission": "Kettős beküldés megakadályozása",
|
||||
"prevent_double_submission_description": "E-mail-címenként csak 1 válasz engedélyezése",
|
||||
"progress_saved": "Folyamat elmentve",
|
||||
@@ -1704,8 +1712,8 @@
|
||||
"response_limit_needs_to_exceed_number_of_received_responses": "A válaszkorlátnak meg kell haladnia a kapott válaszok számát ({responseCount}).",
|
||||
"response_limits_redirections_and_more": "Válaszkorlátok, átirányítások és egyebek.",
|
||||
"response_options": "Válasz beállításai",
|
||||
"reverse_order_occasionally": "Sorrend alkalmi megfordítása",
|
||||
"reverse_order_occasionally_except_last": "Sorrend alkalmi megfordítása az utolsó kivételével",
|
||||
"reverse_order_occasionally": "Időnként fordított sorrendben",
|
||||
"reverse_order_occasionally_except_last": "Időnként fordított sorrendben, kivéve az utolsó",
|
||||
"roundness": "Kerekesség",
|
||||
"roundness_description": "Annak vezérlése, hogy a sarkok mennyire legyenek lekerekítve.",
|
||||
"row_used_in_logic_error": "Ez a sor használatban van a(z) {questionIndex}. kérdés logikájában. Először távolítsa el a logikából.",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 pont",
|
||||
"show_block_settings": "Blokkbeállítások megjelenítése",
|
||||
"show_button": "Gomb megjelenítése",
|
||||
"show_in_order": "Megjelenítés sorrendben",
|
||||
"show_language_switch": "Nyelvválasztó megjelenítése",
|
||||
"show_multiple_times": "Megjelenítés korlátozott számú alkalommal",
|
||||
"show_only_once": "Megjelenítés csak egyszer",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Kérdőív előnézete 👀",
|
||||
"survey_styling": "Kérdőív stílusának beállítása",
|
||||
"survey_trigger": "Kérdőív aktiválója",
|
||||
"switch_multi_language_on_to_get_started": "Kapcsolja be a többnyelvűséget a kezdéshez 👉",
|
||||
"target_block_not_found": "A célblokk nem található",
|
||||
"targeted": "Célzott",
|
||||
"ten_points": "10 pont",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Megjelenítés egyetlen alkalommal, még akkor is, ha nem válaszolnak.",
|
||||
"then": "Azután",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Ez a művelet eltávolítja az összes fordítást ebből a kérdőívből.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Ez el fogja távolítani ezt a nyelvet és annak összes fordítását ebből a kérdőívből. Ezt a műveletet nem lehet visszavonni.",
|
||||
"three_points": "3 pont",
|
||||
"times": "alkalom",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Ahhoz, hogy következetesen megtartsa az elhelyezést az összes kérdőívnél, az alábbiakat teheti:",
|
||||
"translated": "Lefordítva",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "A kérdőív aktiválása, ha a műveletek egyikét elindítják…",
|
||||
"try_lollipop_or_mountain": "A „nyalóka” vagy „hegy” kipróbálása…",
|
||||
"type_field_id": "Mezőazonosító beírása",
|
||||
@@ -1784,11 +1794,11 @@
|
||||
"upper_label": "Felső címke",
|
||||
"url_filters": "URL szűrők",
|
||||
"url_not_supported": "Az URL nem támogatott",
|
||||
"validate_id_duplicate": "A(z) {type} azonosító már létezik a kérdések, rejtett mezők vagy változók között.",
|
||||
"validate_id_empty": "Kérjük, adjon meg egy {type} azonosítót.",
|
||||
"validate_id_invalid_chars": "A(z) {type} azonosító nem engedélyezett. Kérjük, csak alfanumerikus karaktereket, kötőjeleket vagy aláhúzásjeleket használjon.",
|
||||
"validate_id_no_spaces": "A(z) {type} azonosító nem tartalmazhat szóközöket. Kérjük, távolítsa el a szóközöket.",
|
||||
"validate_id_reserved": "A(z) {type} azonosító \"{field}\" nem engedélyezett. Ez egy fenntartott kulcsszó.",
|
||||
"validate_id_duplicate": "A {type} azonosítója már létezik a kérdésekben, rejtett mezőkben vagy változókban.",
|
||||
"validate_id_empty": "Adja meg egy {type} azonosítóját.",
|
||||
"validate_id_invalid_chars": "A {type} azonosítója nem engedélyezett. Használjon csak alfanumerikus karaktereket, kötőjeleket vagy aláhúzásjeleket.",
|
||||
"validate_id_no_spaces": "A {type} azonosítója nem tartalmazhat szóközöket. Távolítsa el a szóközöket.",
|
||||
"validate_id_reserved": "A {type} „{field}” azonosítója nem engedélyezett. Ez egy foglalt kulcsszó.",
|
||||
"validation": {
|
||||
"add_validation_rule": "Ellenőrzési szabály hozzáadása",
|
||||
"answer_all_rows": "Válaszoljon az összes sorra",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Csak valódi e-mail-címmel rendelkező személyek válaszolhassanak.",
|
||||
"visibility_and_recontact": "Láthatóság és újbóli kapcsolatfelvétel",
|
||||
"visibility_and_recontact_description": "Annak vezérlése, hogy ez a kérdőív mikor jelenhet meg és milyen gyakran jelenhet meg újra.",
|
||||
"visible": "Látható",
|
||||
"wait": "Várakozás",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Várakozás néhány másodpercig az aktiválás után, mielőtt megjelenítené a kérdőívet",
|
||||
"waiting_time_across_surveys": "Várakozási időszak (kérdőívek között)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "QR-kód letöltése",
|
||||
"drop_offs": "Megszakítások",
|
||||
"drop_offs_tooltip": "A kérdőív elkezdési, de be nem fejezési alkalmainak száma.",
|
||||
"failed_to_copy_link": "Nem sikerült a hivatkozás másolása",
|
||||
"filter_added_successfully": "A szűrő sikeresen hozzáadva",
|
||||
"filter_updated_successfully": "A szűrő sikeresen frissítve",
|
||||
"filtered_responses_csv": "Szűrt válaszok (CSV)",
|
||||
@@ -2129,7 +2139,7 @@
|
||||
"this_quarter": "Ez a negyedév",
|
||||
"this_year": "Ez az év",
|
||||
"time_to_complete": "Kitöltéshez szükséges idő",
|
||||
"ttc_survey_tooltip": "A felmérés kitöltésének átlagos ideje.",
|
||||
"ttc_survey_tooltip": "A kérdőív megválaszolásának átlagos ideje.",
|
||||
"ttc_tooltip": "A kérdés megválaszolásának átlagos ideje.",
|
||||
"unknown_question_type": "Ismeretlen kérdéstípus",
|
||||
"use_personal_links": "Személyes hivatkozások használata",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "A kérdőív sikeresen törölve",
|
||||
"survey_duplicated_successfully": "A kérdőív sikeresen megkettőzve",
|
||||
"survey_duplication_error": "Nem sikerült megkettőzni a kérdőívet.",
|
||||
"templates": {
|
||||
"all_channels": "Összes csatorna",
|
||||
"all_industries": "Összes iparág",
|
||||
@@ -2219,7 +2228,7 @@
|
||||
"languages": {
|
||||
"add_language": "Nyelv hozzáadása",
|
||||
"alias": "Álnév",
|
||||
"alias_tooltip": "Az álnév egy alternatív név a hivatkozás-kérdőívekben és az SDK-ban lévő nyelv azonosításához (választható)",
|
||||
"alias_tooltip": "Az álnév egy alternatív név a hivatkozás-kérdőívekben és az SDK-ban lévő nyelv azonosításához (elhagyható)",
|
||||
"cannot_remove_language_warning": "Nem tudja eltávolítani ezt a nyelvet, mert még mindig használatban van ezekben a kérdőívekben:",
|
||||
"conflict_between_identifier_and_alias": "Ütközés van egy hozzáadott nyelv azonosítója és az álnevei egyike között. Az álnevek és az azonosítók nem lehetnek azonosak.",
|
||||
"conflict_between_selected_alias_and_another_language": "Ütközés van a kiválasztott álnév és egy másik, ezzel az azonosítóval rendelkező nyelv között. A következetlenségek elkerülése érdekében ezzel az azonosítóval adja hozzá a nyelvet a munkaterületéhez.",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Kettőzött nyelv vagy nyelvazonosító",
|
||||
"edit_languages": "Nyelvek szerkesztése",
|
||||
"identifier": "Azonosító (ISO)",
|
||||
"incomplete_translations": "Befejezetlen fordítások",
|
||||
"language": "Nyelv",
|
||||
"language_deleted_successfully": "A nyelv sikeresen törölve",
|
||||
"languages_updated_successfully": "A nyelvek sikeresen frissítve",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Válasszon egy nyelvet",
|
||||
"remove_language": "Nyelv eltávolítása",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Távolítsa el a nyelvet ezekből a kérdőívekből, hogy eltávolítsa azt a munkaterületről.",
|
||||
"search_items": "Elemek keresése",
|
||||
"translate": "Fordítás"
|
||||
"search_items": "Elemek keresése"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Háttérszín hozzáadása",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Kiszínezi a sáv kitöltetlen részét.",
|
||||
"advanced_styling_field_track_height": "Követés magassága",
|
||||
"advanced_styling_field_track_height_description": "A folyamatjelző vastagságát vezérli.",
|
||||
"advanced_styling_field_upper_label_color": "Címsor címkéjének színe",
|
||||
"advanced_styling_field_upper_label_color_description": "Kiszínezi a beviteli mezők fölötti kis címkéket.",
|
||||
"advanced_styling_field_upper_label_size": "Címsor címkéjének betűmérete",
|
||||
"advanced_styling_field_upper_label_size_description": "Átméretezi a beviteli mezők fölötti kis címkéket.",
|
||||
"advanced_styling_field_upper_label_weight": "Címsor címkéjének betűvastagsága",
|
||||
"advanced_styling_field_upper_label_weight_description": "Vékonyabbá vagy vastagabbá teszi a címkét.",
|
||||
"advanced_styling_field_upper_label_color": "Címke színe",
|
||||
"advanced_styling_field_upper_label_color_description": "Kiszínezi a beviteli mezők fölötti kis címkéket és a méretezés címkéit.",
|
||||
"advanced_styling_field_upper_label_size": "Címke betűmérete",
|
||||
"advanced_styling_field_upper_label_size_description": "Átméretezi a beviteli mezők fölötti kis címkéket és a méretezés címkéit.",
|
||||
"advanced_styling_field_upper_label_weight": "Címke betűvastagsága",
|
||||
"advanced_styling_field_upper_label_weight_description": "Vékonyabbá vagy vastagabbá teszi a címkéket.",
|
||||
"advanced_styling_section_buttons": "Gombok",
|
||||
"advanced_styling_section_headlines": "Címsorok és leírások",
|
||||
"advanced_styling_section_inputs": "Beviteli mezők",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Ellenőrizze az e-mail-címét a válaszadáshoz",
|
||||
"verify_email_before_submission_button": "Ellenőrzés",
|
||||
"verify_email_before_submission_description": "A kérdőívre való válaszadáshoz ellenőrizze az e-mail-címét",
|
||||
"want_to_respond": "Szeretne válaszolni?"
|
||||
"want_to_respond": "Szeretne válaszolni?",
|
||||
"paused_heading": "Szüneteltetve",
|
||||
"completed_heading": "Befejezve"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2640,7 +2649,7 @@
|
||||
"csat_question_1_headline": "Mennyire valószínű, hogy ezt a(z) $[projectName] projektet ajánlaná egy ismerősnek vagy kollégának?",
|
||||
"csat_question_1_lower_label": "Nem valószínű",
|
||||
"csat_question_1_upper_label": "Nagyon valószínű",
|
||||
"csat_question_2_choice_1": "Részben elégedett",
|
||||
"csat_question_2_choice_1": "Valamelyest elégedett",
|
||||
"csat_question_2_choice_2": "Nagyon elégedett",
|
||||
"csat_question_2_choice_3": "Sem elégedett, sem elégedetlen",
|
||||
"csat_question_2_choice_4": "Valamelyest elégedetlen",
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Mi az egyetlen dolog, amelyet jobban csinálhatnánk?",
|
||||
"identify_customer_goals_description": "Jobban megérteni, hogy az üzenetei a termék által nyújtott érték megfelelő elvárásait keltik-e.",
|
||||
"identify_customer_goals_name": "Ügyfélcélok azonosítása",
|
||||
"identify_customer_goals_question_1_choice_1": "A felhasználói bázisom alapos megértése",
|
||||
"identify_customer_goals_question_1_choice_2": "Felülértékesítési lehetőségek azonosítása",
|
||||
"identify_customer_goals_question_1_choice_3": "A lehető legjobb termék elkészítése",
|
||||
"identify_customer_goals_question_1_choice_4": "Világuralom szerezése, hogy mindenki kelbimbót egyen reggelire",
|
||||
"identify_customer_goals_question_1_headline": "Mi az elsődleges célja a(z) $[projectName] használatával?",
|
||||
"identify_sign_up_barriers_description": "Kedvezmény felajánlása a regisztrációs akadályokkal kapcsolatos tapasztalatok gyűjtéséhez.",
|
||||
"identify_sign_up_barriers_name": "Regisztrációs akadályok azonosítása",
|
||||
"identify_sign_up_barriers_question_1_button_label": "10% kedvezmény",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Segítsen nekünk jobban megérteni Önt:",
|
||||
"improve_trial_conversion_question_2_button_label": "Következő",
|
||||
"improve_trial_conversion_question_2_headline": "Sajnálattal halljuk. Mi volt a legnagyobb probléma a(z) $[projectName] projekt használatával?",
|
||||
"improve_trial_conversion_question_3_button_label": "Következő",
|
||||
"improve_trial_conversion_question_3_headline": "Mit vár el a(z) $[projectName] projekttől?",
|
||||
"improve_trial_conversion_question_4_button_label": "20% kedvezmény",
|
||||
"improve_trial_conversion_question_4_headline": "Sajnálattal halljuk! 20% kedvezményt kap az első évre.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Boldogan felajánlunk 20% kedvezményt az éves csomagra.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Következő",
|
||||
"improve_trial_conversion_question_5_headline": "Mit szeretne elérni?",
|
||||
"improve_trial_conversion_question_5_subheader": "Válassza ki a következő lehetőségek egyikét:",
|
||||
"improve_trial_conversion_question_5_subheader": "Írja le az alábbiakban:",
|
||||
"improve_trial_conversion_question_6_headline": "Hogyan oldja meg a problémáját most?",
|
||||
"improve_trial_conversion_question_6_subheader": "Nevezzen meg alternatív megoldásokat:",
|
||||
"integration_setup_survey_description": "Annak kiértékelése, hogy a felhasználók mennyire könnyen tudnak integrációkat hozzáadni a termékéhez. A vakfoltok megtalálása.",
|
||||
|
||||
+45
-29
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "リンクの有効期限が切れています。",
|
||||
"link_expired_description": "使用したリンクはすでに無効です。"
|
||||
"link_expired_description": "使用したリンクはすでに無効です。",
|
||||
"link_expired_heading": "リンクの有効期限が切れています。"
|
||||
},
|
||||
"common": {
|
||||
"accepted": "承認済み",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "中央モーダル",
|
||||
"change_organization": "組織を変更",
|
||||
"change_workspace": "ワークスペースを変更",
|
||||
"choice_n": "選択肢 {{n}}",
|
||||
"choices": "選択肢",
|
||||
"choose_environment": "環境を選択",
|
||||
"choose_organization": "組織を選択",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "閉じる",
|
||||
"code": "コード",
|
||||
"collapse_rows": "行を非表示",
|
||||
"column_n": "列 {{n}}",
|
||||
"completed": "完了",
|
||||
"configuration": "設定",
|
||||
"confirm": "確認",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "クリップボードへのコピーに失敗しました",
|
||||
"failed_to_load_organizations": "組織の読み込みに失敗しました",
|
||||
"failed_to_load_workspaces": "ワークスペースの読み込みに失敗しました",
|
||||
"field_placeholder": "{{field}} プレースホルダー",
|
||||
"filter": "フィルター",
|
||||
"finish": "完了",
|
||||
"first_name": "名",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "生成",
|
||||
"go_back": "戻る",
|
||||
"go_to_dashboard": "ダッシュボードへ移動",
|
||||
"headline": "見出し",
|
||||
"hidden": "非表示",
|
||||
"hidden_field": "非表示フィールド",
|
||||
"hidden_fields": "非表示フィールド",
|
||||
"hide_column": "列を非表示",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "画像",
|
||||
"images": "画像",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "ヶ月",
|
||||
"move_down": "下に移動",
|
||||
"move_up": "上に移動",
|
||||
"multiple_languages": "多言語",
|
||||
"my_product": "マイプロダクト",
|
||||
"name": "名前",
|
||||
"new": "新規",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "結果が見つかりません",
|
||||
"no_results": "結果なし",
|
||||
"no_surveys_found": "フォームが見つかりません。",
|
||||
"no_text_found": "テキストが見つかりません",
|
||||
"none_of_the_above": "いずれも該当しません",
|
||||
"not_authenticated": "このアクションを実行するための認証がされていません。",
|
||||
"not_authorized": "権限がありません",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "組織設定",
|
||||
"other": "その他",
|
||||
"other_filters": "その他のフィルター",
|
||||
"others": "その他",
|
||||
"other_placeholder": "その他のプレースホルダー",
|
||||
"overlay_color": "オーバーレイの色",
|
||||
"overview": "概要",
|
||||
"password": "パスワード",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "プランをアップグレードしてください",
|
||||
"powered_by_formbricks": "Powered by Formbricks",
|
||||
"preview": "プレビュー",
|
||||
"preview_survey": "フォームをプレビュー",
|
||||
"privacy": "プライバシーポリシー",
|
||||
"product_manager": "プロダクトマネージャー",
|
||||
"production": "本番",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "回答",
|
||||
"restart": "再開",
|
||||
"role": "役割",
|
||||
"row_n": "行 {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "セールス",
|
||||
"save": "保存",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "ファイルストレージが設定されていないため、アップロードは失敗する可能性があります",
|
||||
"string": "テキスト",
|
||||
"styling": "スタイル",
|
||||
"subheader": "小見出し",
|
||||
"submit": "送信",
|
||||
"summary": "概要",
|
||||
"survey": "フォーム",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "例: Formbricks",
|
||||
"workspaces": "ワークスペース",
|
||||
"years": "年",
|
||||
"you": "あなた",
|
||||
"you_are_downgraded_to_the_community_edition": "コミュニティ版にダウングレードされました。",
|
||||
"you_are_not_authorized_to_perform_this_action": "このアクションを実行する権限がありません。",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "ワークスペースの上限である{projectLimit}件に達しました。",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "回答を直接Notionに送信します",
|
||||
"please_select_a_survey_error": "フォームを選択してください",
|
||||
"reconnect_button": "再接続",
|
||||
"reconnect_button_description": "統合の接続が期限切れになりました。回答の同期を続けるには再接続してください。既存のリンクとデータは保持されます。",
|
||||
"reconnect_button_tooltip": "統合を再接続してアクセスを更新します。既存のリンクとデータは保持されます。",
|
||||
"select_at_least_one_question_error": "少なくとも1つの質問を選択してください",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "このチャンネルには別のフォームがすでに接続されています。",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "すべての準備が整いました!最初のフォームを作成しましょう",
|
||||
"alphabetical": "アルファベット順",
|
||||
"copy_survey": "フォームをコピー",
|
||||
"copy_survey_description": "このフォームを別の環境にコピー",
|
||||
"copy_survey_error": "フォームのコピーに失敗しました",
|
||||
"copy_survey_link_to_clipboard": "フォームのリンクをクリップボードにコピー",
|
||||
"copy_survey_partially_success": "{success} 個のフォームが正常にコピーされ、{error} 個が失敗しました。",
|
||||
"copy_survey_success": "フォームを正常にコピーしました!",
|
||||
"delete_survey_and_responses_warning": "本当にこのフォームとすべての回答を削除しますか?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. このフォームのデフォルト言語を選択してください:",
|
||||
"2_activate_translation_for_specific_languages": "2. 特定の言語の翻訳を有効にしてください:",
|
||||
"activate_translations": "翻訳を有効化",
|
||||
"add": "追加 +",
|
||||
"add_a_delay_or_auto_close_the_survey": "遅延を追加するか、フォームを自動的に閉じる",
|
||||
"add_a_four_digit_pin": "4桁のPINを追加",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "オーディエンス",
|
||||
"auto_close_on_inactivity": "非アクティブ時に自動閉鎖",
|
||||
"auto_progress_rating_and_nps": "評価とNPSの質問を自動進行",
|
||||
"auto_progress_rating_and_nps_description": "評価またはNPSの質問で回答者が選択肢を選んだ際に自動的に次へ進みます。これは単一質問ブロックにのみ適用されます。必須の質問では「次へ」ボタンが非表示になり、任意の質問ではスキップ用に引き続き表示されます。",
|
||||
"auto_progress_rating_and_nps_description": "単一質問ブロックで自動的に次へ進みます。必須質問では「次へ」ボタンが非表示になりますが、「その他」が選択された場合は表示されます。",
|
||||
"auto_save_disabled": "自動保存が無効",
|
||||
"auto_save_disabled_tooltip": "アンケートは下書き状態の時のみ自動保存されます。これにより、公開中のアンケートが意図せず更新されることを防ぎます。",
|
||||
"auto_save_on": "自動保存オン",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "変更は不整合を引き起こします",
|
||||
"change_anyway": "とにかく変更",
|
||||
"change_background": "背景を変更",
|
||||
"change_default": "デフォルトを変更",
|
||||
"change_question_type": "質問の種類を変更",
|
||||
"change_survey_type": "フォームの種類を変更すると、既存のアクセスに影響します",
|
||||
"change_the_background_to_a_color_image_or_animation": "背景を色、画像、またはアニメーションに変更します。",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "フォームを実行する場所を選択してください。",
|
||||
"city": "市区町村",
|
||||
"close_survey_on_response_limit": "回答数の上限でフォームを閉じる",
|
||||
"code": "コード",
|
||||
"color": "色",
|
||||
"column_used_in_logic_error": "この列は質問 {questionIndex} のロジックで使用されています。まず、ロジックから削除してください。",
|
||||
"columns": "列",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "アンケートのロゴをカスタマイズする",
|
||||
"darken_or_lighten_background_of_your_choice": "お好みの背景を暗くしたり明るくしたりします。",
|
||||
"days_before_showing_this_survey_again": "最後に表示されたアンケートとこのアンケートを表示するまでに、この日数以上の期間を空ける必要があります。",
|
||||
"default_language": "デフォルト言語",
|
||||
"delete_anyways": "削除する",
|
||||
"delete_block": "ブロックを削除",
|
||||
"delete_choice": "選択肢を削除",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "質問を複製",
|
||||
"edit_link": "編集 リンク",
|
||||
"edit_recall": "リコールを編集",
|
||||
"edit_translations": "{lang} 翻訳を編集",
|
||||
"element_not_found": "質問が見つかりません",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "回答者がいつでも言語を切り替えられるようにします。最低2つのアクティブな言語が必要です。",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "スパム対策はreCAPTCHA v3を使用してスパム回答をフィルタリングします。",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "回答者が長文の複数行の回答を書けるようにします。",
|
||||
"lower_label": "下限ラベル",
|
||||
"manage_languages": "言語を管理",
|
||||
"manage_translations": "翻訳を管理",
|
||||
"matrix_all_fields": "すべてのフィールド",
|
||||
"matrix_rows": "行",
|
||||
"max_file_size": "最大ファイルサイズ",
|
||||
"max_file_size_limit_is": "最大ファイルサイズの上限は",
|
||||
"missing_first": "未翻訳を優先",
|
||||
"move_question_to_block": "質問をブロックに移動",
|
||||
"multiply": "乗算 *",
|
||||
"needed_for_self_hosted_cal_com_instance": "セルフホストのCal.comインスタンスに必要",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "「次へ」ボタンのラベル",
|
||||
"no_hidden_fields_yet_add_first_one_below": "まだ非表示フィールドがありません。以下で最初のものを追加してください。",
|
||||
"no_images_found_for": "''{query}'' の画像が見つかりません",
|
||||
"no_languages_found_add_first_one_to_get_started": "言語が見つかりません。始めるには、最初のものを追加してください。",
|
||||
"no_languages_found_add_first_one_to_get_started": "このワークスペースにはアンケート言語が見つかりませんでした。開始するには言語を追加してください。",
|
||||
"no_option_found": "オプションが見つかりません",
|
||||
"no_recall_items_found": "リコール項目が見つかりません",
|
||||
"no_variables_yet_add_first_one_below": "まだ変数がありません。以下で最初のものを追加してください。",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "有効な URL を入力してください (例:https://example.com)",
|
||||
"please_set_a_survey_trigger": "フォームのトリガーを設定してください",
|
||||
"please_specify": "具体的に指定してください",
|
||||
"present_your_survey_in_multiple_languages": "アンケートを複数の言語で表示",
|
||||
"prevent_double_submission": "二重送信を防ぐ",
|
||||
"prevent_double_submission_description": "メールアドレスごとに1つの回答のみを許可する",
|
||||
"progress_saved": "進捗を保存しました",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7点",
|
||||
"show_block_settings": "ブロック設定を表示",
|
||||
"show_button": "ボタンを表示",
|
||||
"show_in_order": "順番に表示",
|
||||
"show_language_switch": "言語切り替えを表示",
|
||||
"show_multiple_times": "限られた回数表示する",
|
||||
"show_only_once": "一度だけ表示",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "アンケートプレビュー 👀",
|
||||
"survey_styling": "フォームのスタイル",
|
||||
"survey_trigger": "フォームのトリガー",
|
||||
"switch_multi_language_on_to_get_started": "多言語機能をオンにして開始 👉",
|
||||
"target_block_not_found": "対象ブロックが見つかりません",
|
||||
"targeted": "ターゲット",
|
||||
"ten_points": "10点",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "回答がなくても1回だけ表示します。",
|
||||
"then": "その後",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "このアクションは、このフォームからすべての翻訳を削除します。",
|
||||
"this_will_remove_the_language_and_all_its_translations": "この言語とすべての翻訳がこのアンケートから削除されます。この操作は元に戻せません。",
|
||||
"three_points": "3点",
|
||||
"times": "回",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "すべてのフォームの配置を一貫させるために、",
|
||||
"translated": "翻訳済み",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "以下のアクションのいずれかが発火したときにフォームをトリガーします...",
|
||||
"try_lollipop_or_mountain": "「lollipop」や「mountain」を試してみてください...",
|
||||
"type_field_id": "フィールドIDを入力",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "有効なメールアドレスを持つ人のみが回答できるようにする",
|
||||
"visibility_and_recontact": "表示と再接触",
|
||||
"visibility_and_recontact_description": "このフォームがいつ表示され、どのくらいの頻度で再表示できるかをコントロールします。",
|
||||
"visible": "表示",
|
||||
"wait": "待つ",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "トリガーから数秒待ってからフォームを表示します",
|
||||
"waiting_time_across_surveys": "クールダウン期間(アンケート全体)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "QRコードをダウンロード中",
|
||||
"drop_offs": "離脱",
|
||||
"drop_offs_tooltip": "フォームが開始されたが完了しなかった回数。",
|
||||
"failed_to_copy_link": "リンクのコピーに失敗しました",
|
||||
"filter_added_successfully": "フィルターを正常に追加しました",
|
||||
"filter_updated_successfully": "フィルターを正常に更新しました",
|
||||
"filtered_responses_csv": "フィルター済み回答 (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "フォームを正常に削除しました!",
|
||||
"survey_duplicated_successfully": "フォームを正常に複製しました。",
|
||||
"survey_duplication_error": "フォームの複製に失敗しました。",
|
||||
"templates": {
|
||||
"all_channels": "すべてのチャネル",
|
||||
"all_industries": "すべての業界",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "重複する言語または言語ID",
|
||||
"edit_languages": "言語を編集",
|
||||
"identifier": "識別子(ISO)",
|
||||
"incomplete_translations": "未完了の翻訳",
|
||||
"language": "言語",
|
||||
"language_deleted_successfully": "言語を正常に削除しました",
|
||||
"languages_updated_successfully": "言語を正常に更新しました",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "言語を選択してください",
|
||||
"remove_language": "言語を削除",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "ワークスペースから削除するには、これらのフォームから言語を削除してください。",
|
||||
"search_items": "アイテムを検索",
|
||||
"translate": "翻訳"
|
||||
"search_items": "アイテムを検索"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "背景色を追加",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "バーの未入力部分の色を設定します。",
|
||||
"advanced_styling_field_track_height": "トラックの高さ",
|
||||
"advanced_styling_field_track_height_description": "プログレスバーの太さを調整します。",
|
||||
"advanced_styling_field_upper_label_color": "見出しラベルの色",
|
||||
"advanced_styling_field_upper_label_color_description": "入力フィールド上部の小さなラベルの色を設定します。",
|
||||
"advanced_styling_field_upper_label_size": "見出しラベルのフォントサイズ",
|
||||
"advanced_styling_field_upper_label_size_description": "入力フィールド上部の小さなラベルのサイズを調整します。",
|
||||
"advanced_styling_field_upper_label_weight": "見出しラベルのフォントの太さ",
|
||||
"advanced_styling_field_upper_label_weight_description": "ラベルを細くまたは太くします。",
|
||||
"advanced_styling_field_upper_label_color": "ラベルの色",
|
||||
"advanced_styling_field_upper_label_color_description": "入力欄の上にある小さなラベルとスケールラベルの色を設定します。",
|
||||
"advanced_styling_field_upper_label_size": "ラベルのフォントサイズ",
|
||||
"advanced_styling_field_upper_label_size_description": "入力欄の上にある小さなラベルとスケールラベルのサイズを調整します。",
|
||||
"advanced_styling_field_upper_label_weight": "ラベルのフォント太さ",
|
||||
"advanced_styling_field_upper_label_weight_description": "ラベルの太さを細くしたり太くしたりします。",
|
||||
"advanced_styling_section_buttons": "ボタン",
|
||||
"advanced_styling_section_headlines": "見出しと説明",
|
||||
"advanced_styling_section_inputs": "入力フィールド",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "回答するにはメールアドレスを認証してください",
|
||||
"verify_email_before_submission_button": "認証",
|
||||
"verify_email_before_submission_description": "このフォームに回答するには、メールアドレスを認証してください",
|
||||
"want_to_respond": "回答しますか?"
|
||||
"want_to_respond": "回答しますか?",
|
||||
"paused_heading": "一時停止",
|
||||
"completed_heading": "完了"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "私たちがもっとうまくできることは何ですか?",
|
||||
"identify_customer_goals_description": "あなたのメッセージが製品の価値に対する正しい期待を抱かせているかどうかをよりよく理解する。",
|
||||
"identify_customer_goals_name": "顧客目標の特定",
|
||||
"identify_customer_goals_question_1_choice_1": "ユーザーベースを深く理解する",
|
||||
"identify_customer_goals_question_1_choice_2": "アップセルの機会を特定する",
|
||||
"identify_customer_goals_question_1_choice_3": "最高の製品を構築する",
|
||||
"identify_customer_goals_question_1_choice_4": "世界を支配して全員に朝食に芽キャベツを食べさせる",
|
||||
"identify_customer_goals_question_1_headline": "$[projectName]を使用する主な目的は何ですか?",
|
||||
"identify_sign_up_barriers_description": "サインアップの障壁に関する洞察を得るために割引を提供する。",
|
||||
"identify_sign_up_barriers_name": "サインアップの障壁を特定する",
|
||||
"identify_sign_up_barriers_question_1_button_label": "10%割引を取得",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "私たちをよりよく理解するためにお手伝いください:",
|
||||
"improve_trial_conversion_question_2_button_label": "次へ",
|
||||
"improve_trial_conversion_question_2_headline": "残念です。$[projectName]を使う上で最も大きな問題は何でしたか?",
|
||||
"improve_trial_conversion_question_3_button_label": "次へ",
|
||||
"improve_trial_conversion_question_3_headline": "$[projectName]に何を期待していましたか?",
|
||||
"improve_trial_conversion_question_4_button_label": "20%オフを取得",
|
||||
"improve_trial_conversion_question_4_headline": "残念です!初年度20%オフをゲット。",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>年間プランで20%の割引を提供させていただきます。</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "次へ",
|
||||
"improve_trial_conversion_question_5_headline": "何を達成したいですか?",
|
||||
"improve_trial_conversion_question_5_subheader": "以下のオプションから一つ選択してください:",
|
||||
"improve_trial_conversion_question_5_subheader": "以下に詳しくご記入ください:",
|
||||
"improve_trial_conversion_question_6_headline": "今、問題をどのように解決していますか?",
|
||||
"improve_trial_conversion_question_6_subheader": "代替ソリューションを挙げてください:",
|
||||
"integration_setup_survey_description": "ユーザーが製品に統合を追加するのがどれだけ簡単かを評価する。盲点を見つける。",
|
||||
|
||||
+46
-30
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Uw link is verlopen.",
|
||||
"link_expired_description": "De link die u gebruikte is niet meer geldig."
|
||||
"link_expired_description": "De link die u gebruikte is niet meer geldig.",
|
||||
"link_expired_heading": "Uw link is verlopen."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Geaccepteerd",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Gecentreerd modaal",
|
||||
"change_organization": "Organisatie wijzigen",
|
||||
"change_workspace": "Werkruimte wijzigen",
|
||||
"choice_n": "Keuze {{n}}",
|
||||
"choices": "Keuzes",
|
||||
"choose_environment": "Kies omgeving",
|
||||
"choose_organization": "Kies organisatie",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Dichtbij",
|
||||
"code": "Code",
|
||||
"collapse_rows": "Rijen samenvouwen",
|
||||
"column_n": "Kolom {{n}}",
|
||||
"completed": "Voltooid",
|
||||
"configuration": "Configuratie",
|
||||
"confirm": "Bevestigen",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Kopiëren naar klembord mislukt",
|
||||
"failed_to_load_organizations": "Laden van organisaties mislukt",
|
||||
"failed_to_load_workspaces": "Laden van werkruimtes mislukt",
|
||||
"field_placeholder": "Tijdelijke aanduiding voor {{field}}",
|
||||
"filter": "Filter",
|
||||
"finish": "Finish",
|
||||
"first_name": "Voornaam",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Genereren",
|
||||
"go_back": "Ga terug",
|
||||
"go_to_dashboard": "Ga naar Dashboard",
|
||||
"headline": "Kop",
|
||||
"hidden": "Verborgen",
|
||||
"hidden_field": "Verborgen veld",
|
||||
"hidden_fields": "Verborgen velden",
|
||||
"hide_column": "Kolom verbergen",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Afbeelding",
|
||||
"images": "Afbeeldingen",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "maanden",
|
||||
"move_down": "Ga naar beneden",
|
||||
"move_up": "Ga omhoog",
|
||||
"multiple_languages": "Meerdere talen",
|
||||
"my_product": "mijn product",
|
||||
"name": "Naam",
|
||||
"new": "Nieuw",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Geen resultaat gevonden",
|
||||
"no_results": "Geen resultaten",
|
||||
"no_surveys_found": "Geen enquêtes gevonden.",
|
||||
"no_text_found": "Geen tekst gevonden",
|
||||
"none_of_the_above": "Geen van bovenstaande",
|
||||
"not_authenticated": "U bent niet geverifieerd om deze actie uit te voeren.",
|
||||
"not_authorized": "Niet geautoriseerd",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Organisatie-instellingen",
|
||||
"other": "Ander",
|
||||
"other_filters": "Overige filters",
|
||||
"others": "Anderen",
|
||||
"other_placeholder": "Andere tijdelijke aanduiding",
|
||||
"overlay_color": "Overlaykleur",
|
||||
"overview": "Overzicht",
|
||||
"password": "Wachtwoord",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Upgrade je abonnement",
|
||||
"powered_by_formbricks": "Mogelijk gemaakt door Formbricks",
|
||||
"preview": "Voorbeeld",
|
||||
"preview_survey": "Voorbeeld van enquête",
|
||||
"privacy": "Privacybeleid",
|
||||
"product_manager": "Productmanager",
|
||||
"production": "Productie",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Reacties",
|
||||
"restart": "Opnieuw opstarten",
|
||||
"role": "Rol",
|
||||
"row_n": "Rij {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Verkoop",
|
||||
"save": "Redden",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Bestandsopslag is niet ingesteld, uploads zullen waarschijnlijk mislukken",
|
||||
"string": "Tekst",
|
||||
"styling": "Styling",
|
||||
"subheader": "Subkop",
|
||||
"submit": "Indienen",
|
||||
"summary": "Samenvatting",
|
||||
"survey": "Vragenlijst",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "bijv. Formbricks",
|
||||
"workspaces": "Werkruimtes",
|
||||
"years": "jaren",
|
||||
"you": "Jij",
|
||||
"you_are_downgraded_to_the_community_edition": "Je bent gedowngraded naar de Community-editie.",
|
||||
"you_are_not_authorized_to_perform_this_action": "U bent niet geautoriseerd om deze actie uit te voeren.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Je hebt je limiet van {projectLimit} werkruimtes bereikt.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Verzend gegevens naar uw Notion-database",
|
||||
"please_select_a_survey_error": "Selecteer een enquête",
|
||||
"reconnect_button": "Opnieuw verbinden",
|
||||
"reconnect_button_description": "Je integratieverbinding is verlopen. Maak opnieuw verbinding om door te gaan met het synchroniseren van reacties. Je bestaande links en gegevens blijven behouden.",
|
||||
"reconnect_button_tooltip": "Verbind de integratie opnieuw om je toegang te vernieuwen. Je bestaande links en gegevens blijven behouden.",
|
||||
"select_at_least_one_question_error": "Selecteer minimaal één vraag",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "U heeft al een andere enquête aan dit kanaal gekoppeld.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Je bent helemaal klaar! Tijd om uw eerste enquête te maken",
|
||||
"alphabetical": "Alfabetisch",
|
||||
"copy_survey": "Kopieer enquête",
|
||||
"copy_survey_description": "Kopieer deze enquête naar een andere omgeving",
|
||||
"copy_survey_error": "Het kopiëren van de enquête is mislukt",
|
||||
"copy_survey_link_to_clipboard": "Kopieer de enquêtelink naar het klembord",
|
||||
"copy_survey_partially_success": "{success} enquêtes zijn succesvol gekopieerd, {error} is mislukt.",
|
||||
"copy_survey_success": "Enquête succesvol gekopieerd!",
|
||||
"delete_survey_and_responses_warning": "Weet u zeker dat u deze enquête en alle antwoorden erop wilt verwijderen?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Kies de standaardtaal voor deze enquête:",
|
||||
"2_activate_translation_for_specific_languages": "2. Activeer vertaling voor specifieke talen:",
|
||||
"activate_translations": "Vertalingen activeren",
|
||||
"add": "Voeg + toe",
|
||||
"add_a_delay_or_auto_close_the_survey": "Voeg een vertraging toe of sluit de enquête automatisch",
|
||||
"add_a_four_digit_pin": "Voeg een viercijferige pincode toe",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Publiek",
|
||||
"auto_close_on_inactivity": "Automatisch sluiten bij inactiviteit",
|
||||
"auto_progress_rating_and_nps": "Automatisch doorgaan bij beoordelings- en NPS-vragen",
|
||||
"auto_progress_rating_and_nps_description": "Ga automatisch verder wanneer respondenten een antwoord selecteren bij beoordelings- of NPS-vragen. Dit geldt alleen voor blokken met één vraag. Bij verplichte vragen wordt de Volgende-knop verborgen; bij optionele vragen blijft deze zichtbaar om de vraag over te slaan.",
|
||||
"auto_progress_rating_and_nps_description": "Automatisch doorgaan bij blokken met één vraag. Verplichte vragen verbergen Volgende, behalve wanneer \"Anders\" is geselecteerd.",
|
||||
"auto_save_disabled": "Automatisch opslaan uitgeschakeld",
|
||||
"auto_save_disabled_tooltip": "Uw enquête wordt alleen automatisch opgeslagen wanneer deze een concept is. Dit zorgt ervoor dat openbare enquêtes niet onbedoeld worden bijgewerkt.",
|
||||
"auto_save_on": "Automatisch opslaan aan",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Veranderingen zullen tot inconsistenties leiden",
|
||||
"change_anyway": "Hoe dan ook veranderen",
|
||||
"change_background": "Achtergrond wijzigen",
|
||||
"change_default": "Standaard wijzigen",
|
||||
"change_question_type": "Vraagtype wijzigen",
|
||||
"change_survey_type": "Als u van enquêtetype verandert, heeft dit invloed op de bestaande toegang",
|
||||
"change_the_background_to_a_color_image_or_animation": "Verander de achtergrond in een kleur, afbeelding of animatie.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Kies waar u de enquête wilt uitvoeren.",
|
||||
"city": "Stad",
|
||||
"close_survey_on_response_limit": "Sluit enquête over responslimiet",
|
||||
"code": "Code",
|
||||
"color": "Kleur",
|
||||
"column_used_in_logic_error": "Deze kolom wordt gebruikt in de logica van vraag {questionIndex}. Verwijder het eerst uit de logica.",
|
||||
"columns": "Kolommen",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Pas het enquêtelogo aan",
|
||||
"darken_or_lighten_background_of_your_choice": "Maak de achtergrond naar keuze donkerder of lichter.",
|
||||
"days_before_showing_this_survey_again": "of meer dagen moeten verstrijken tussen de laatst getoonde enquête en het tonen van deze enquête.",
|
||||
"default_language": "Standaardtaal",
|
||||
"delete_anyways": "Toch verwijderen",
|
||||
"delete_block": "Blok verwijderen",
|
||||
"delete_choice": "Keuze verwijderen",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Vraag dupliceren",
|
||||
"edit_link": "Link bewerken",
|
||||
"edit_recall": "Bewerken Terugroepen",
|
||||
"edit_translations": "Bewerk {lang} vertalingen",
|
||||
"element_not_found": "Vraag niet gevonden",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Sta respondenten toe om op elk moment van taal te wisselen. Vereist min. 2 actieve talen.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "Spambeveiliging maakt gebruik van reCAPTCHA v3 om de spamreacties eruit te filteren.",
|
||||
@@ -1597,11 +1602,13 @@
|
||||
"long_answer": "Lang antwoord",
|
||||
"long_answer_toggle_description": "Sta respondenten toe om langere antwoorden met meerdere regels te schrijven.",
|
||||
"lower_label": "Lager etiket",
|
||||
"manage_languages": "Beheer talen",
|
||||
"manage_languages": "Talen beheren",
|
||||
"manage_translations": "Vertalingen beheren",
|
||||
"matrix_all_fields": "Alle velden",
|
||||
"matrix_rows": "Rijen",
|
||||
"max_file_size": "Maximale bestandsgrootte",
|
||||
"max_file_size_limit_is": "Maximale bestandsgroottelimiet is",
|
||||
"missing_first": "Ontbrekende eerst",
|
||||
"move_question_to_block": "Vraag naar blok verplaatsen",
|
||||
"multiply": "Vermenigvuldig *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Nodig voor een zelf-gehoste Cal.com-instantie",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Knoplabel 'Volgende'",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Nog geen verborgen velden. Voeg de eerste hieronder toe.",
|
||||
"no_images_found_for": "Geen afbeeldingen gevonden voor ''{query}'",
|
||||
"no_languages_found_add_first_one_to_get_started": "Geen talen gevonden. Voeg de eerste toe om aan de slag te gaan.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Geen enquêtetalen gevonden in deze werkruimte. Voeg er een toe om te beginnen.",
|
||||
"no_option_found": "Geen optie gevonden",
|
||||
"no_recall_items_found": "Geen recall-items gevonden",
|
||||
"no_variables_yet_add_first_one_below": "Nog geen variabelen. Voeg de eerste hieronder toe.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Voer een geldige URL in (bijvoorbeeld https://example.com)",
|
||||
"please_set_a_survey_trigger": "Stel een enquêtetrigger in",
|
||||
"please_specify": "Gelieve te specificeren",
|
||||
"present_your_survey_in_multiple_languages": "Toon je enquête in meerdere talen",
|
||||
"prevent_double_submission": "Voorkom dubbele indiening",
|
||||
"prevent_double_submission_description": "Er is slechts 1 reactie per e-mailadres toegestaan",
|
||||
"progress_saved": "Voortgang opgeslagen",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 punten",
|
||||
"show_block_settings": "Blokinstellingen tonen",
|
||||
"show_button": "Toon knop",
|
||||
"show_in_order": "Toon op volgorde",
|
||||
"show_language_switch": "Toon taalwissel",
|
||||
"show_multiple_times": "Toon een beperkt aantal keren",
|
||||
"show_only_once": "Slechts één keer weergeven",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Enquêtevoorbeeld 👀",
|
||||
"survey_styling": "Vorm styling",
|
||||
"survey_trigger": "Enquêtetrigger",
|
||||
"switch_multi_language_on_to_get_started": "Schakel meertaligheid in om te beginnen 👉",
|
||||
"target_block_not_found": "Doelblok niet gevonden",
|
||||
"targeted": "Gericht",
|
||||
"ten_points": "10 punten",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Toon één keer, zelfs als ze niet reageren.",
|
||||
"then": "Dan",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Met deze actie worden alle vertalingen uit deze enquête verwijderd.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Dit verwijdert deze taal en alle vertalingen uit deze enquête. Deze actie kan niet ongedaan worden gemaakt.",
|
||||
"three_points": "3 punten",
|
||||
"times": "keer",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Om de plaatsing over alle enquêtes consistent te houden, kunt u dat doen",
|
||||
"translated": "Vertaald",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Enquête activeren wanneer een van de acties wordt afgevuurd...",
|
||||
"try_lollipop_or_mountain": "Probeer 'lollipop' of 'berg'...",
|
||||
"type_field_id": "Typ veld-ID",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Laat alleen mensen met een echte e-mail reageren.",
|
||||
"visibility_and_recontact": "Zichtbaarheid & opnieuw contact",
|
||||
"visibility_and_recontact_description": "Bepaal wanneer deze enquête kan verschijnen en hoe vaak deze opnieuw kan verschijnen.",
|
||||
"visible": "Zichtbaar",
|
||||
"wait": "Wachten",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Wacht een paar seconden na de trigger voordat u de enquête weergeeft",
|
||||
"waiting_time_across_surveys": "Afkoelperiode (voor alle enquêtes)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "QR-code downloaden",
|
||||
"drop_offs": "Drop-offs",
|
||||
"drop_offs_tooltip": "Aantal keren dat de enquête is gestart maar niet is voltooid.",
|
||||
"failed_to_copy_link": "Kan de link niet kopiëren",
|
||||
"filter_added_successfully": "Filter succesvol toegevoegd",
|
||||
"filter_updated_successfully": "Filter succesvol bijgewerkt",
|
||||
"filtered_responses_csv": "Gefilterde reacties (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Enquête succesvol verwijderd!",
|
||||
"survey_duplicated_successfully": "Enquête is succesvol gedupliceerd.",
|
||||
"survey_duplication_error": "Het is niet gelukt de enquête te dupliceren.",
|
||||
"templates": {
|
||||
"all_channels": "Alle kanalen",
|
||||
"all_industries": "Alle industrieën",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Dubbele taal of taal-ID",
|
||||
"edit_languages": "Talen bewerken",
|
||||
"identifier": "Identifier (ISO)",
|
||||
"incomplete_translations": "Onvolledige vertalingen",
|
||||
"language": "Taal",
|
||||
"language_deleted_successfully": "Taal succesvol verwijderd",
|
||||
"languages_updated_successfully": "Talen succesvol bijgewerkt",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Selecteer een taal",
|
||||
"remove_language": "Taal verwijderen",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Verwijder de taal uit deze enquêtes om deze uit de werkruimte te verwijderen.",
|
||||
"search_items": "Items zoeken",
|
||||
"translate": "Vertalen"
|
||||
"search_items": "Items zoeken"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Achtergrondkleur toevoegen",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Kleurt het ongevulde gedeelte van de balk.",
|
||||
"advanced_styling_field_track_height": "Spoorhoogte",
|
||||
"advanced_styling_field_track_height_description": "Regelt de dikte van de voortgangsbalk.",
|
||||
"advanced_styling_field_upper_label_color": "Koplabelkleur",
|
||||
"advanced_styling_field_upper_label_color_description": "Kleurt het kleine label boven invoervelden.",
|
||||
"advanced_styling_field_upper_label_size": "Lettergrootte koplabel",
|
||||
"advanced_styling_field_upper_label_size_description": "Schaalt het kleine label boven invoervelden.",
|
||||
"advanced_styling_field_upper_label_weight": "Letterdikte koplabel",
|
||||
"advanced_styling_field_upper_label_weight_description": "Maakt het label lichter of vetter.",
|
||||
"advanced_styling_field_upper_label_color": "Labelkleur",
|
||||
"advanced_styling_field_upper_label_color_description": "Kleurt de kleine labels boven invoervelden en schaallabels.",
|
||||
"advanced_styling_field_upper_label_size": "Lettergrootte label",
|
||||
"advanced_styling_field_upper_label_size_description": "Past de grootte aan van de kleine labels boven invoervelden en schaallabels.",
|
||||
"advanced_styling_field_upper_label_weight": "Letterdikte label",
|
||||
"advanced_styling_field_upper_label_weight_description": "Maakt de labels lichter of dikgedrukt.",
|
||||
"advanced_styling_section_buttons": "Knoppen",
|
||||
"advanced_styling_section_headlines": "Koppen & beschrijvingen",
|
||||
"advanced_styling_section_inputs": "Invoervelden",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verifieer uw e-mailadres om te reageren",
|
||||
"verify_email_before_submission_button": "Verifiëren",
|
||||
"verify_email_before_submission_description": "Om op deze enquête te reageren, dient u uw e-mailadres te verifiëren",
|
||||
"want_to_respond": "Wilt u reageren?"
|
||||
"want_to_respond": "Wilt u reageren?",
|
||||
"paused_heading": "Gepauzeerd",
|
||||
"completed_heading": "Voltooid"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Wat kunnen we beter doen?",
|
||||
"identify_customer_goals_description": "Begrijp beter of uw boodschap de juiste verwachtingen wekt van de waarde die uw product biedt.",
|
||||
"identify_customer_goals_name": "Identificeer klantdoelen",
|
||||
"identify_customer_goals_question_1_choice_1": "Mijn gebruikersgroep grondig begrijpen",
|
||||
"identify_customer_goals_question_1_choice_2": "Upselling-mogelijkheden identificeren",
|
||||
"identify_customer_goals_question_1_choice_3": "Het best mogelijke product bouwen",
|
||||
"identify_customer_goals_question_1_choice_4": "De wereld regeren om iedereen spruitjes als ontbijt te geven",
|
||||
"identify_customer_goals_question_1_headline": "Wat is je primaire doel voor het gebruik van $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Bied een korting aan om inzicht te krijgen in de aanmeldingsbarrières.",
|
||||
"identify_sign_up_barriers_name": "Identificeer aanmeldingsbarrières",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Krijg 10% korting",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Help ons u beter te begrijpen:",
|
||||
"improve_trial_conversion_question_2_button_label": "Volgende",
|
||||
"improve_trial_conversion_question_2_headline": "Sorry om te horen. Wat was het grootste probleem bij het gebruik van $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Volgende",
|
||||
"improve_trial_conversion_question_3_headline": "Wat had je verwacht dat $[projectName] zou doen?",
|
||||
"improve_trial_conversion_question_4_button_label": "Krijg 20% korting",
|
||||
"improve_trial_conversion_question_4_headline": "Sorry om te horen! Krijg het eerste jaar 20% korting.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>We bieden u graag 20% korting op een jaarabonnement.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Volgende",
|
||||
"improve_trial_conversion_question_5_headline": "Wat zou je graag willen bereiken?",
|
||||
"improve_trial_conversion_question_5_subheader": "Selecteer een van de volgende opties:",
|
||||
"improve_trial_conversion_question_5_subheader": "Beschrijf hieronder:",
|
||||
"improve_trial_conversion_question_6_headline": "Hoe los jij je probleem nu op?",
|
||||
"improve_trial_conversion_question_6_subheader": "Noem alternatieve oplossingen:",
|
||||
"integration_setup_survey_description": "Evalueer hoe gemakkelijk gebruikers integraties aan uw product kunnen toevoegen. Zoek blinde vlekken.",
|
||||
|
||||
+46
-30
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Seu link está expirado.",
|
||||
"link_expired_description": "O link que você usou não é mais válido."
|
||||
"link_expired_description": "O link que você usou não é mais válido.",
|
||||
"link_expired_heading": "Seu link está expirado."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Aceito",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Modal Centralizado",
|
||||
"change_organization": "Alterar organização",
|
||||
"change_workspace": "Alterar espaço de trabalho",
|
||||
"choice_n": "Escolha {{n}}",
|
||||
"choices": "Escolhas",
|
||||
"choose_environment": "Escolher ambiente",
|
||||
"choose_organization": "Escolher organização",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Fechar",
|
||||
"code": "Código",
|
||||
"collapse_rows": "Recolher linhas",
|
||||
"column_n": "Coluna {{n}}",
|
||||
"completed": "Concluído",
|
||||
"configuration": "Configuração",
|
||||
"confirm": "Confirmar",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Falha ao copiar para a área de transferência",
|
||||
"failed_to_load_organizations": "Falha ao carregar organizações",
|
||||
"failed_to_load_workspaces": "Falha ao carregar projetos",
|
||||
"field_placeholder": "Espaço reservado de {{field}}",
|
||||
"filter": "Filtro",
|
||||
"finish": "Terminar",
|
||||
"first_name": "Primeiro nome",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Gerar",
|
||||
"go_back": "Voltar",
|
||||
"go_to_dashboard": "Ir para o Painel",
|
||||
"headline": "Título",
|
||||
"hidden": "Escondido",
|
||||
"hidden_field": "Campo oculto",
|
||||
"hidden_fields": "Campos ocultos",
|
||||
"hide_column": "Ocultar coluna",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "imagem",
|
||||
"images": "Imagens",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "meses",
|
||||
"move_down": "Descer",
|
||||
"move_up": "Subir",
|
||||
"multiple_languages": "Vários idiomas",
|
||||
"my_product": "meu produto",
|
||||
"name": "Nome",
|
||||
"new": "Novo",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Nenhum resultado encontrado",
|
||||
"no_results": "Nenhum resultado",
|
||||
"no_surveys_found": "Não foram encontradas pesquisas.",
|
||||
"no_text_found": "Nenhum texto encontrado",
|
||||
"none_of_the_above": "Nenhuma das opções acima",
|
||||
"not_authenticated": "Você não está autenticado para realizar essa ação.",
|
||||
"not_authorized": "Não autorizado",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Configurações da Organização",
|
||||
"other": "outro",
|
||||
"other_filters": "Outros Filtros",
|
||||
"others": "Outros",
|
||||
"other_placeholder": "Outro espaço reservado",
|
||||
"overlay_color": "Cor da sobreposição",
|
||||
"overview": "Visão Geral",
|
||||
"password": "Senha",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Por favor, atualize seu plano",
|
||||
"powered_by_formbricks": "Desenvolvido por Formbricks",
|
||||
"preview": "Prévia",
|
||||
"preview_survey": "Prévia da Pesquisa",
|
||||
"privacy": "Política de Privacidade",
|
||||
"product_manager": "Gerente de Produto",
|
||||
"production": "Produção",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Respostas",
|
||||
"restart": "Reiniciar",
|
||||
"role": "Rolê",
|
||||
"row_n": "Linha {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "vendas",
|
||||
"save": "Salvar",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Armazenamento de arquivos não configurado, uploads provavelmente falharão",
|
||||
"string": "Texto",
|
||||
"styling": "Estilização",
|
||||
"subheader": "Subtítulo",
|
||||
"submit": "Enviar",
|
||||
"summary": "Resumo",
|
||||
"survey": "Pesquisa",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "ex: Formbricks",
|
||||
"workspaces": "Projetos",
|
||||
"years": "anos",
|
||||
"you": "Você",
|
||||
"you_are_downgraded_to_the_community_edition": "Você foi rebaixado para a Edição Comunitária.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Você não tem autorização para realizar essa ação.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Você atingiu seu limite de {projectLimit} espaços de trabalho.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Enviar dados para seu banco de dados do Notion",
|
||||
"please_select_a_survey_error": "Por favor, escolha uma pesquisa",
|
||||
"reconnect_button": "Reconectar",
|
||||
"reconnect_button_description": "Sua conexão de integração expirou. Por favor, reconecte para continuar sincronizando respostas. Seus links e dados existentes serão preservados.",
|
||||
"reconnect_button_tooltip": "Reconecte a integração para atualizar seu acesso. Seus links e dados existentes serão preservados.",
|
||||
"select_at_least_one_question_error": "Por favor, selecione pelo menos uma pergunta",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Você já conectou outra pesquisa a este canal.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Tá tudo pronto! Hora de criar sua primeira pesquisa",
|
||||
"alphabetical": "alfabético",
|
||||
"copy_survey": "Copiar pesquisa",
|
||||
"copy_survey_description": "Copiar essa pesquisa para outro ambiente",
|
||||
"copy_survey_error": "Falha ao copiar pesquisa",
|
||||
"copy_survey_link_to_clipboard": "Copiar link da pesquisa para a área de transferência",
|
||||
"copy_survey_partially_success": "{success} pesquisas copiadas com sucesso, {error} falharam.",
|
||||
"copy_survey_success": "Pesquisa copiada com sucesso!",
|
||||
"delete_survey_and_responses_warning": "Você tem certeza de que quer deletar essa pesquisa e todas as suas respostas?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Escolha o idioma padrão para essa pesquisa:",
|
||||
"2_activate_translation_for_specific_languages": "2. Ativar tradução para idiomas específicos:",
|
||||
"activate_translations": "Ativar traduções",
|
||||
"add": "Adicionar +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Adicione um atraso ou feche a pesquisa automaticamente",
|
||||
"add_a_four_digit_pin": "Adicione um PIN de quatro dígitos",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Público",
|
||||
"auto_close_on_inactivity": "Fechar automaticamente por inatividade",
|
||||
"auto_progress_rating_and_nps": "Avançar automaticamente em perguntas de avaliação e NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente quando os respondentes selecionam uma resposta em perguntas de avaliação ou NPS. Isso se aplica apenas a blocos com uma única pergunta. Perguntas obrigatórias ocultam o botão Próximo; perguntas opcionais ainda o exibem para permitir pular.",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente em blocos de pergunta única. Perguntas obrigatórias ocultam o botão Próximo, exceto quando \"Outro\" está selecionado.",
|
||||
"auto_save_disabled": "Salvamento automático desativado",
|
||||
"auto_save_disabled_tooltip": "Sua pesquisa só é salva automaticamente quando está em rascunho. Isso garante que pesquisas públicas não sejam atualizadas involuntariamente.",
|
||||
"auto_save_on": "Salvamento automático ativado",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Mudanças vão levar a inconsistências",
|
||||
"change_anyway": "Mudar mesmo assim",
|
||||
"change_background": "Mudar fundo",
|
||||
"change_default": "Alterar padrão",
|
||||
"change_question_type": "Mudar tipo de pergunta",
|
||||
"change_survey_type": "Alterar o tipo de pesquisa afeta o acesso existente",
|
||||
"change_the_background_to_a_color_image_or_animation": "Mude o fundo para uma cor, imagem ou animação.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Escolha onde realizar a pesquisa.",
|
||||
"city": "cidade",
|
||||
"close_survey_on_response_limit": "Fechar pesquisa ao atingir limite de respostas",
|
||||
"code": "Código",
|
||||
"color": "cor",
|
||||
"column_used_in_logic_error": "Esta coluna é usada na lógica da pergunta {questionIndex}. Por favor, remova-a da lógica primeiro.",
|
||||
"columns": "colunas",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Personalizar o logo da pesquisa",
|
||||
"darken_or_lighten_background_of_your_choice": "Escureça ou clareie o fundo da sua escolha.",
|
||||
"days_before_showing_this_survey_again": "ou mais dias devem passar entre a última pesquisa exibida e a exibição desta pesquisa.",
|
||||
"default_language": "Idioma padrão",
|
||||
"delete_anyways": "Excluir mesmo assim",
|
||||
"delete_block": "Excluir bloco",
|
||||
"delete_choice": "Deletar opção",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Duplicar pergunta",
|
||||
"edit_link": "Editar link",
|
||||
"edit_recall": "Editar Lembrete",
|
||||
"edit_translations": "Editar traduções de {lang}",
|
||||
"element_not_found": "Pergunta não encontrada",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permitir que os respondentes alterem o idioma a qualquer momento. Necessita de no mínimo 2 idiomas ativos.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "A proteção contra spam usa o reCAPTCHA v3 para filtrar as respostas de spam.",
|
||||
@@ -1597,11 +1602,13 @@
|
||||
"long_answer": "resposta longa",
|
||||
"long_answer_toggle_description": "Permitir que os respondentes escrevam respostas mais longas e com várias linhas.",
|
||||
"lower_label": "Etiqueta Inferior",
|
||||
"manage_languages": "Gerenciar Idiomas",
|
||||
"manage_languages": "Gerenciar idiomas",
|
||||
"manage_translations": "Gerenciar traduções",
|
||||
"matrix_all_fields": "Todos os campos",
|
||||
"matrix_rows": "Linhas",
|
||||
"max_file_size": "Tamanho máximo do arquivo",
|
||||
"max_file_size_limit_is": "O limite de tamanho máximo do arquivo é",
|
||||
"missing_first": "Faltantes primeiro",
|
||||
"move_question_to_block": "Mover pergunta para o bloco",
|
||||
"multiply": "Multiplicar *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Necessário para uma instância auto-hospedada do Cal.com",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Próximo",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Ainda não há campos ocultos. Adicione o primeiro abaixo.",
|
||||
"no_images_found_for": "Nenhuma imagem encontrada para ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nenhum idioma encontrado. Adicione o primeiro para começar.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nenhum idioma de pesquisa encontrado neste espaço de trabalho. Por favor, adicione um para começar.",
|
||||
"no_option_found": "Nenhuma opção encontrada",
|
||||
"no_recall_items_found": "Nenhum item de recuperação encontrado",
|
||||
"no_variables_yet_add_first_one_below": "Ainda não há variáveis. Adicione a primeira abaixo.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Por favor, insira uma URL válida (ex.: https://example.com)",
|
||||
"please_set_a_survey_trigger": "Por favor, configure um gatilho para a pesquisa",
|
||||
"please_specify": "Por favor, especifique",
|
||||
"present_your_survey_in_multiple_languages": "Apresente sua pesquisa em vários idiomas",
|
||||
"prevent_double_submission": "Evitar envio duplicado",
|
||||
"prevent_double_submission_description": "Permitir apenas 1 resposta por endereço de email",
|
||||
"progress_saved": "Progresso salvo",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 pontos",
|
||||
"show_block_settings": "Mostrar configurações do bloco",
|
||||
"show_button": "Mostrar Botão",
|
||||
"show_in_order": "Mostrar em ordem",
|
||||
"show_language_switch": "Mostrar troca de idioma",
|
||||
"show_multiple_times": "Mostrar um número limitado de vezes",
|
||||
"show_only_once": "Mostrar só uma vez",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Prévia da pesquisa 👀",
|
||||
"survey_styling": "Estilização de Formulários",
|
||||
"survey_trigger": "Gatilho de Pesquisa",
|
||||
"switch_multi_language_on_to_get_started": "Ative o modo multilíngue para começar 👉",
|
||||
"target_block_not_found": "Bloco de destino não encontrado",
|
||||
"targeted": "direcionado",
|
||||
"ten_points": "10 pontos",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Mostrar uma única vez, mesmo que não respondam.",
|
||||
"then": "Então",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Essa ação vai remover todas as traduções dessa pesquisa.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Isso removerá este idioma e todas as suas traduções desta pesquisa. Esta ação não pode ser desfeita.",
|
||||
"three_points": "3 pontos",
|
||||
"times": "times",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Para manter a colocação consistente em todas as pesquisas, você pode",
|
||||
"translated": "Traduzido",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Disparar pesquisa quando uma das ações for executada...",
|
||||
"try_lollipop_or_mountain": "Tenta 'pirulito' ou 'montanha'...",
|
||||
"type_field_id": "Digite o id do campo",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Deixe só quem tem um email real responder.",
|
||||
"visibility_and_recontact": "Visibilidade e recontato",
|
||||
"visibility_and_recontact_description": "Controle quando esta pesquisa pode aparecer e com que frequência pode reaparecer.",
|
||||
"visible": "Visível",
|
||||
"wait": "Espera",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Espera alguns segundos depois do gatilho antes de mostrar a pesquisa",
|
||||
"waiting_time_across_surveys": "Período de espera (entre pesquisas)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Baixando código QR",
|
||||
"drop_offs": "Pontos de Entrega",
|
||||
"drop_offs_tooltip": "Número de vezes que a pesquisa foi iniciada mas não concluída.",
|
||||
"failed_to_copy_link": "Falha ao copiar link",
|
||||
"filter_added_successfully": "Filtro adicionado com sucesso",
|
||||
"filter_updated_successfully": "Filtro atualizado com sucesso",
|
||||
"filtered_responses_csv": "Respostas filtradas (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Pesquisa deletada com sucesso!",
|
||||
"survey_duplicated_successfully": "Pesquisa duplicada com sucesso.",
|
||||
"survey_duplication_error": "Falha ao duplicar a pesquisa.",
|
||||
"templates": {
|
||||
"all_channels": "Todos os canais",
|
||||
"all_industries": "Todas as indústrias",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Idioma ou ID de idioma duplicado",
|
||||
"edit_languages": "Editar idiomas",
|
||||
"identifier": "Identificador (ISO)",
|
||||
"incomplete_translations": "Traduções incompletas",
|
||||
"language": "Idioma",
|
||||
"language_deleted_successfully": "Idioma excluído com sucesso",
|
||||
"languages_updated_successfully": "Idiomas atualizados com sucesso",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Por favor, selecione um idioma",
|
||||
"remove_language": "Remover idioma",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Por favor, remova o idioma dessas pesquisas para removê-lo do workspace.",
|
||||
"search_items": "Buscar itens",
|
||||
"translate": "Traduzir"
|
||||
"search_items": "Buscar itens"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Adicionar cor de fundo",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colore a porção não preenchida da barra.",
|
||||
"advanced_styling_field_track_height": "Altura da trilha",
|
||||
"advanced_styling_field_track_height_description": "Controla a espessura da barra de progresso.",
|
||||
"advanced_styling_field_upper_label_color": "Cor do rótulo do título",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore o pequeno rótulo acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da fonte do rótulo do título",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho do pequeno rótulo acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da fonte do rótulo do título",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna o rótulo mais leve ou mais negrito.",
|
||||
"advanced_styling_field_upper_label_color": "Cor do Rótulo",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore os pequenos rótulos acima dos campos de entrada e rótulos de escala.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da Fonte do Rótulo",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho dos pequenos rótulos acima dos campos de entrada e rótulos de escala.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da Fonte do Rótulo",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna os rótulos mais leves ou mais pesados.",
|
||||
"advanced_styling_section_buttons": "Botões",
|
||||
"advanced_styling_section_headlines": "Títulos e descrições",
|
||||
"advanced_styling_section_inputs": "Campos de entrada",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verifique seu e-mail para responder",
|
||||
"verify_email_before_submission_button": "Verificar",
|
||||
"verify_email_before_submission_description": "Para responder a esta pesquisa, confirme seu e-mail",
|
||||
"want_to_respond": "Quer responder?"
|
||||
"want_to_respond": "Quer responder?",
|
||||
"paused_heading": "Pausado",
|
||||
"completed_heading": "Concluído"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "O que a gente poderia melhorar?",
|
||||
"identify_customer_goals_description": "Entenda melhor se sua mensagem cria as expectativas certas sobre o valor que seu produto oferece.",
|
||||
"identify_customer_goals_name": "Identificar Objetivos do Cliente",
|
||||
"identify_customer_goals_question_1_choice_1": "Entender profundamente minha base de usuários",
|
||||
"identify_customer_goals_question_1_choice_2": "Identificar oportunidades de upsell",
|
||||
"identify_customer_goals_question_1_choice_3": "Construir o melhor produto possível",
|
||||
"identify_customer_goals_question_1_choice_4": "Dominar o mundo para fazer todo mundo tomar couve de bruxelas no café da manhã",
|
||||
"identify_customer_goals_question_1_headline": "Qual é o seu objetivo principal ao usar $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Ofereça um desconto pra entender melhor as barreiras de cadastro.",
|
||||
"identify_sign_up_barriers_name": "Identificar Barreiras de Cadastro",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Ganhe 10% de desconto",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Ajuda a gente a te entender melhor:",
|
||||
"improve_trial_conversion_question_2_button_label": "Próximo",
|
||||
"improve_trial_conversion_question_2_headline": "Que chato ouvir isso. Qual foi o maior problema ao usar $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Próximo",
|
||||
"improve_trial_conversion_question_3_headline": "O que você esperava que $[projectName] fizesse?",
|
||||
"improve_trial_conversion_question_4_button_label": "Ganhe 20% de desconto",
|
||||
"improve_trial_conversion_question_4_headline": "Que pena ouvir isso! Ganhe 20% de desconto no primeiro ano.",
|
||||
"improve_trial_conversion_question_4_html": "Estamos felizes em te oferecer um desconto de 20% no plano anual.",
|
||||
"improve_trial_conversion_question_5_button_label": "Próximo",
|
||||
"improve_trial_conversion_question_5_headline": "O que você gostaria de alcançar?",
|
||||
"improve_trial_conversion_question_5_subheader": "Por favor, escolha uma das opções a seguir:",
|
||||
"improve_trial_conversion_question_5_subheader": "Por favor, descreva abaixo:",
|
||||
"improve_trial_conversion_question_6_headline": "Como você tá resolvendo seu problema agora?",
|
||||
"improve_trial_conversion_question_6_subheader": "Por favor, nomeie soluções alternativas:",
|
||||
"integration_setup_survey_description": "Avalie quão fácil é para os usuários adicionarem integrações ao seu produto. Encontre pontos cegos.",
|
||||
|
||||
+46
-30
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "O seu link expirou.",
|
||||
"link_expired_description": "O link que utilizou já não é válido."
|
||||
"link_expired_description": "O link que utilizou já não é válido.",
|
||||
"link_expired_heading": "O seu link expirou."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Aceite",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Modal Centralizado",
|
||||
"change_organization": "Alterar organização",
|
||||
"change_workspace": "Alterar espaço de trabalho",
|
||||
"choice_n": "Escolha {{n}}",
|
||||
"choices": "Escolhas",
|
||||
"choose_environment": "Escolha o ambiente",
|
||||
"choose_organization": "Escolher organização",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Fechar",
|
||||
"code": "Código",
|
||||
"collapse_rows": "Recolher linhas",
|
||||
"column_n": "Coluna {{n}}",
|
||||
"completed": "Concluído",
|
||||
"configuration": "Configuração",
|
||||
"confirm": "Confirmar",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Falha ao copiar para a área de transferência",
|
||||
"failed_to_load_organizations": "Falha ao carregar organizações",
|
||||
"failed_to_load_workspaces": "Falha ao carregar projetos",
|
||||
"field_placeholder": "Espaço reservado de {{field}}",
|
||||
"filter": "Filtro",
|
||||
"finish": "Concluir",
|
||||
"first_name": "Primeiro nome",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Gerar",
|
||||
"go_back": "Voltar",
|
||||
"go_to_dashboard": "Ir para o Painel",
|
||||
"headline": "Título",
|
||||
"hidden": "Oculto",
|
||||
"hidden_field": "Campo oculto",
|
||||
"hidden_fields": "Campos ocultos",
|
||||
"hide_column": "Ocultar coluna",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Imagem",
|
||||
"images": "Imagens",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "meses",
|
||||
"move_down": "Mover para baixo",
|
||||
"move_up": "Mover para cima",
|
||||
"multiple_languages": "Várias línguas",
|
||||
"my_product": "o meu produto",
|
||||
"name": "Nome",
|
||||
"new": "Novo",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Nenhum resultado encontrado",
|
||||
"no_results": "Nenhum resultado",
|
||||
"no_surveys_found": "Nenhum inquérito encontrado.",
|
||||
"no_text_found": "Nenhum texto encontrado",
|
||||
"none_of_the_above": "Nenhuma das opções acima",
|
||||
"not_authenticated": "Não está autenticado para realizar esta ação.",
|
||||
"not_authorized": "Não autorizado",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Configurações da Organização",
|
||||
"other": "Outro",
|
||||
"other_filters": "Outros Filtros",
|
||||
"others": "Outros",
|
||||
"other_placeholder": "Outro espaço reservado",
|
||||
"overlay_color": "Cor da sobreposição",
|
||||
"overview": "Visão geral",
|
||||
"password": "Palavra-passe",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Por favor, atualize o seu plano",
|
||||
"powered_by_formbricks": "Desenvolvido por Formbricks",
|
||||
"preview": "Pré-visualização",
|
||||
"preview_survey": "Pré-visualização do inquérito",
|
||||
"privacy": "Política de Privacidade",
|
||||
"product_manager": "Gestor de Produto",
|
||||
"production": "Produção",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Respostas",
|
||||
"restart": "Reiniciar",
|
||||
"role": "Função",
|
||||
"row_n": "Linha {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Vendas",
|
||||
"save": "Guardar",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Armazenamento de ficheiros não configurado, uploads provavelmente falharão",
|
||||
"string": "Texto",
|
||||
"styling": "Estilo",
|
||||
"subheader": "Subtítulo",
|
||||
"submit": "Submeter",
|
||||
"summary": "Resumo",
|
||||
"survey": "Inquérito",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "ex. Formbricks",
|
||||
"workspaces": "Projetos",
|
||||
"years": "anos",
|
||||
"you": "Você",
|
||||
"you_are_downgraded_to_the_community_edition": "Foi rebaixado para a Edição Comunitária.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Não está autorizado a realizar esta ação.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Atingiu o seu limite de {projectLimit} áreas de trabalho.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Enviar dados para a sua base de dados do Notion",
|
||||
"please_select_a_survey_error": "Por favor, selecione um inquérito",
|
||||
"reconnect_button": "Voltar a ligar",
|
||||
"reconnect_button_description": "A ligação da tua integração expirou. Por favor, volta a ligar para continuar a sincronizar as respostas. As tuas ligações e dados existentes serão preservados.",
|
||||
"reconnect_button_tooltip": "Volta a ligar a integração para atualizar o teu acesso. As tuas ligações e dados existentes serão preservados.",
|
||||
"select_at_least_one_question_error": "Por favor, selecione pelo menos uma pergunta",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Já ligou outro inquérito a este canal.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Está tudo pronto! Hora de criar o seu primeiro inquérito",
|
||||
"alphabetical": "Alfabética",
|
||||
"copy_survey": "Copiar inquérito",
|
||||
"copy_survey_description": "Copiar este questionário para outro ambiente",
|
||||
"copy_survey_error": "Falha ao copiar inquérito",
|
||||
"copy_survey_link_to_clipboard": "Copiar link do inquérito para a área de transferência",
|
||||
"copy_survey_partially_success": "{success} inquéritos copiados com sucesso, {error} falharam.",
|
||||
"copy_survey_success": "Inquérito copiado com sucesso!",
|
||||
"delete_survey_and_responses_warning": "Tem a certeza de que deseja eliminar este inquérito e todas as suas respostas?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Escolha o idioma padrão para este inquérito:",
|
||||
"2_activate_translation_for_specific_languages": "2. Ativar tradução para idiomas específicos:",
|
||||
"activate_translations": "Ativar traduções",
|
||||
"add": "Adicionar +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Adicionar um atraso ou fechar automaticamente o inquérito",
|
||||
"add_a_four_digit_pin": "Adicione um PIN de quatro dígitos",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Público",
|
||||
"auto_close_on_inactivity": "Fechar automaticamente por inatividade",
|
||||
"auto_progress_rating_and_nps": "Avançar automaticamente em perguntas de classificação e NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente quando os inquiridos selecionam uma resposta em perguntas de classificação ou NPS. Isto aplica-se apenas a blocos com uma única pergunta. Perguntas obrigatórias ocultam o botão Seguinte; perguntas opcionais continuam a mostrá-lo para permitir saltar.",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente em blocos de pergunta única. Perguntas obrigatórias ocultam o botão Seguinte, exceto quando \"Outro\" está selecionado.",
|
||||
"auto_save_disabled": "Guardar automático desativado",
|
||||
"auto_save_disabled_tooltip": "O seu inquérito só é guardado automaticamente quando está em rascunho. Isto garante que os inquéritos públicos não sejam atualizados involuntariamente.",
|
||||
"auto_save_on": "Guardar automático ativado",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "As alterações levarão a inconsistências",
|
||||
"change_anyway": "Alterar mesmo assim",
|
||||
"change_background": "Alterar fundo",
|
||||
"change_default": "Alterar predefinição",
|
||||
"change_question_type": "Alterar tipo de pergunta",
|
||||
"change_survey_type": "Alterar o tipo de inquérito afeta o acesso existente",
|
||||
"change_the_background_to_a_color_image_or_animation": "Altere o fundo para uma cor, imagem ou animação",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Escolha onde realizar o inquérito.",
|
||||
"city": "Cidade",
|
||||
"close_survey_on_response_limit": "Fechar inquérito no limite de respostas",
|
||||
"code": "Código",
|
||||
"color": "Cor",
|
||||
"column_used_in_logic_error": "Esta coluna é usada na lógica da pergunta {questionIndex}. Por favor, remova-a da lógica primeiro.",
|
||||
"columns": "Colunas",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Personalizar o logótipo do inquérito",
|
||||
"darken_or_lighten_background_of_your_choice": "Escurecer ou clarear o fundo da sua escolha.",
|
||||
"days_before_showing_this_survey_again": "ou mais dias a decorrer entre o último inquérito apresentado e a apresentação deste inquérito.",
|
||||
"default_language": "Idioma predefinido",
|
||||
"delete_anyways": "Eliminar mesmo assim",
|
||||
"delete_block": "Eliminar bloco",
|
||||
"delete_choice": "Eliminar escolha",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Duplicar pergunta",
|
||||
"edit_link": "Editar link",
|
||||
"edit_recall": "Editar Lembrete",
|
||||
"edit_translations": "Editar traduções {lang}",
|
||||
"element_not_found": "Pergunta não encontrada",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permitir que os inquiridos mudem de idioma a qualquer momento. Necessita de pelo menos 2 idiomas ativos.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "A proteção contra spam usa o reCAPTCHA v3 para filtrar as respostas de spam.",
|
||||
@@ -1597,11 +1602,13 @@
|
||||
"long_answer": "Resposta longa",
|
||||
"long_answer_toggle_description": "Permitir que os inquiridos escrevam respostas mais longas e com várias linhas.",
|
||||
"lower_label": "Etiqueta Inferior",
|
||||
"manage_languages": "Gerir Idiomas",
|
||||
"manage_languages": "Gerir idiomas",
|
||||
"manage_translations": "Gerir traduções",
|
||||
"matrix_all_fields": "Todos os campos",
|
||||
"matrix_rows": "Linhas",
|
||||
"max_file_size": "Tamanho máximo de ficheiro",
|
||||
"max_file_size_limit_is": "O limite de tamanho máximo de ficheiro é",
|
||||
"missing_first": "Em falta primeiro",
|
||||
"move_question_to_block": "Mover pergunta para o bloco",
|
||||
"multiply": "Multiplicar *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Necessário para uma instância auto-hospedada do Cal.com",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Rótulo do botão \"Seguinte\"",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Ainda não há campos ocultos. Adicione o primeiro abaixo.",
|
||||
"no_images_found_for": "Não foram encontradas imagens para ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nenhuma língua encontrada. Adicione a primeira para começar.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Não foram encontrados idiomas de inquérito neste espaço de trabalho. Por favor, adiciona um para começar.",
|
||||
"no_option_found": "Nenhuma opção encontrada",
|
||||
"no_recall_items_found": "Nenhum item de recuperação encontrado",
|
||||
"no_variables_yet_add_first_one_below": "Ainda não há variáveis. Adicione a primeira abaixo.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Por favor, insira um URL válido (por exemplo, https://example.com)",
|
||||
"please_set_a_survey_trigger": "Por favor, defina um desencadeador de inquérito",
|
||||
"please_specify": "Por favor, especifique",
|
||||
"present_your_survey_in_multiple_languages": "Apresenta o teu inquérito em vários idiomas",
|
||||
"prevent_double_submission": "Impedir submissão dupla",
|
||||
"prevent_double_submission_description": "Permitir apenas 1 resposta por endereço de email",
|
||||
"progress_saved": "Progresso guardado",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 pontos",
|
||||
"show_block_settings": "Mostrar definições do bloco",
|
||||
"show_button": "Mostrar Botão",
|
||||
"show_in_order": "Mostrar por ordem",
|
||||
"show_language_switch": "Mostrar alternador de idioma",
|
||||
"show_multiple_times": "Mostrar um número limitado de vezes",
|
||||
"show_only_once": "Mostrar apenas uma vez",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Pré-visualização do questionário 👀",
|
||||
"survey_styling": "Estilo do formulário",
|
||||
"survey_trigger": "Desencadeador de Inquérito",
|
||||
"switch_multi_language_on_to_get_started": "Ative o modo multilingue para começar 👉",
|
||||
"target_block_not_found": "Bloco de destino não encontrado",
|
||||
"targeted": "Alvo",
|
||||
"ten_points": "10 pontos",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Mostrar uma única vez, mesmo que não respondam.",
|
||||
"then": "Então",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Esta ação irá remover todas as traduções deste inquérito.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Isto irá remover este idioma e todas as suas traduções deste inquérito. Esta ação não pode ser revertida.",
|
||||
"three_points": "3 pontos",
|
||||
"times": "tempos",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Para manter a colocação consistente em todos os questionários, pode",
|
||||
"translated": "Traduzido",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Desencadear inquérito quando uma das ações for disparada...",
|
||||
"try_lollipop_or_mountain": "Experimente 'cão' ou 'planta'...",
|
||||
"type_field_id": "Escreva o id do campo",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Permitir apenas que pessoas com um email real respondam.",
|
||||
"visibility_and_recontact": "Visibilidade e Recontacto",
|
||||
"visibility_and_recontact_description": "Controlar quando este inquérito pode aparecer e com que frequência pode reaparecer.",
|
||||
"visible": "Visível",
|
||||
"wait": "Aguardar",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Aguarde alguns segundos após o gatilho antes de mostrar o inquérito",
|
||||
"waiting_time_across_surveys": "Período de espera (entre inquéritos)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "A transferir código QR",
|
||||
"drop_offs": "Desistências",
|
||||
"drop_offs_tooltip": "Número de vezes que o inquérito foi iniciado mas não concluído.",
|
||||
"failed_to_copy_link": "Falha ao copiar link",
|
||||
"filter_added_successfully": "Filtro adicionado com sucesso",
|
||||
"filter_updated_successfully": "Filtro atualizado com sucesso",
|
||||
"filtered_responses_csv": "Respostas filtradas (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Inquérito eliminado com sucesso!",
|
||||
"survey_duplicated_successfully": "Inquérito duplicado com sucesso.",
|
||||
"survey_duplication_error": "Falha ao duplicar o inquérito.",
|
||||
"templates": {
|
||||
"all_channels": "Todos os canais",
|
||||
"all_industries": "Todas as indústrias",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Idioma ou ID de idioma duplicado",
|
||||
"edit_languages": "Editar idiomas",
|
||||
"identifier": "Identificador (ISO)",
|
||||
"incomplete_translations": "Traduções incompletas",
|
||||
"language": "Idioma",
|
||||
"language_deleted_successfully": "Idioma eliminado com sucesso",
|
||||
"languages_updated_successfully": "Idiomas atualizados com sucesso",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Por favor, selecione um idioma",
|
||||
"remove_language": "Remover idioma",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Por favor, remova o idioma destes inquéritos para o poder remover do espaço de trabalho.",
|
||||
"search_items": "Pesquisar itens",
|
||||
"translate": "Traduzir"
|
||||
"search_items": "Pesquisar itens"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Adicionar cor de fundo",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colore a porção não preenchida da barra.",
|
||||
"advanced_styling_field_track_height": "Altura da faixa",
|
||||
"advanced_styling_field_track_height_description": "Controla a espessura da barra de progresso.",
|
||||
"advanced_styling_field_upper_label_color": "Cor da etiqueta do título",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore a pequena etiqueta acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da fonte da etiqueta do título",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho da pequena etiqueta acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da fonte da etiqueta do título",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna a etiqueta mais leve ou mais negrito.",
|
||||
"advanced_styling_field_upper_label_color": "Cor da Etiqueta",
|
||||
"advanced_styling_field_upper_label_color_description": "Define a cor das pequenas etiquetas acima dos campos de entrada e das etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da Fonte da Etiqueta",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho das pequenas etiquetas acima dos campos de entrada e das etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_weight": "Espessura da Fonte da Etiqueta",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna as etiquetas mais finas ou mais grossas.",
|
||||
"advanced_styling_section_buttons": "Botões",
|
||||
"advanced_styling_section_headlines": "Títulos e descrições",
|
||||
"advanced_styling_section_inputs": "Campos de entrada",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verifique o seu email para responder",
|
||||
"verify_email_before_submission_button": "Verificar",
|
||||
"verify_email_before_submission_description": "Para responder a este questionário, por favor verifique o seu email",
|
||||
"want_to_respond": "Quer responder?"
|
||||
"want_to_respond": "Quer responder?",
|
||||
"paused_heading": "Em pausa",
|
||||
"completed_heading": "Concluído"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "O que é uma coisa que poderíamos fazer melhor?",
|
||||
"identify_customer_goals_description": "Compreenda melhor se a sua mensagem cria as expectativas certas sobre o valor que o seu produto oferece.",
|
||||
"identify_customer_goals_name": "Identificar Objetivos do Cliente",
|
||||
"identify_customer_goals_question_1_choice_1": "Compreender profundamente a minha base de utilizadores",
|
||||
"identify_customer_goals_question_1_choice_2": "Identificar oportunidades de upselling",
|
||||
"identify_customer_goals_question_1_choice_3": "Construir o melhor produto possível",
|
||||
"identify_customer_goals_question_1_choice_4": "Dominar o mundo para fazer couves de Bruxelas ao pequeno-almoço para todos",
|
||||
"identify_customer_goals_question_1_headline": "Qual é o seu objetivo principal ao usar $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Ofereça um desconto para obter informações sobre as barreiras de inscrição.",
|
||||
"identify_sign_up_barriers_name": "Identificar Barreiras de Inscrição",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Obtenha 10% de desconto",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Ajude-nos a compreendê-lo melhor:",
|
||||
"improve_trial_conversion_question_2_button_label": "Seguinte",
|
||||
"improve_trial_conversion_question_2_headline": "Lamentamos saber. Qual foi o maior problema ao usar $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Seguinte",
|
||||
"improve_trial_conversion_question_3_headline": "O que esperava que $[projectName] fizesse?",
|
||||
"improve_trial_conversion_question_4_button_label": "Obtenha 20% de desconto",
|
||||
"improve_trial_conversion_question_4_headline": "Lamentamos saber! Obtenha 20% de desconto no primeiro ano.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Estamos felizes por lhe oferecer um desconto de 20% num plano anual.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Seguinte",
|
||||
"improve_trial_conversion_question_5_headline": "O que gostaria de alcançar?",
|
||||
"improve_trial_conversion_question_5_subheader": "Por favor, selecione uma das seguintes opções:",
|
||||
"improve_trial_conversion_question_5_subheader": "Por favor, descreve abaixo:",
|
||||
"improve_trial_conversion_question_6_headline": "Como está a resolver o seu problema agora?",
|
||||
"improve_trial_conversion_question_6_subheader": "Por favor, nomeie soluções alternativas:",
|
||||
"integration_setup_survey_description": "Avalie a facilidade com que os utilizadores podem adicionar integrações ao seu produto. Encontre pontos cegos.",
|
||||
|
||||
+46
-30
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Link-ul dumneavoastră a expirat.",
|
||||
"link_expired_description": "Link-ul pe care l-ați utilizat nu mai este valabil."
|
||||
"link_expired_description": "Link-ul pe care l-ați utilizat nu mai este valabil.",
|
||||
"link_expired_heading": "Link-ul dumneavoastră a expirat."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Acceptat",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Modală centralizată",
|
||||
"change_organization": "Schimbă organizația",
|
||||
"change_workspace": "Schimbă spațiul de lucru",
|
||||
"choice_n": "Opțiunea {{n}}",
|
||||
"choices": "Alegeri",
|
||||
"choose_environment": "Alege mediul",
|
||||
"choose_organization": "Alege organizația",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Închide",
|
||||
"code": "Cod",
|
||||
"collapse_rows": "Restrânge rânduri",
|
||||
"column_n": "Coloana {{n}}",
|
||||
"completed": "Completat",
|
||||
"configuration": "Configurare",
|
||||
"confirm": "Confirmare",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Nu s-a reușit copierea în clipboard",
|
||||
"failed_to_load_organizations": "Nu s-a reușit încărcarea organizațiilor",
|
||||
"failed_to_load_workspaces": "Nu s-au putut încărca workspaces",
|
||||
"field_placeholder": "Substituent {{field}}",
|
||||
"filter": "Filtru",
|
||||
"finish": "Finalizează",
|
||||
"first_name": "Prenume",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Generează",
|
||||
"go_back": "Înapoi",
|
||||
"go_to_dashboard": "Mergi la Tablou de Bord",
|
||||
"headline": "Titlu",
|
||||
"hidden": "Ascuns",
|
||||
"hidden_field": "Câmp ascuns",
|
||||
"hidden_fields": "Câmpuri ascunse",
|
||||
"hide_column": "Ascunde coloana",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Imagine",
|
||||
"images": "Imagini",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "luni",
|
||||
"move_down": "Mută în jos",
|
||||
"move_up": "Mută sus",
|
||||
"multiple_languages": "Mai multe limbi",
|
||||
"my_product": "produsul meu",
|
||||
"name": "Nume",
|
||||
"new": "Nou",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Niciun rezultat găsit",
|
||||
"no_results": "Nicio rezultat",
|
||||
"no_surveys_found": "Nu au fost găsite sondaje.",
|
||||
"no_text_found": "Niciun text găsit",
|
||||
"none_of_the_above": "Niciuna dintre cele de mai sus",
|
||||
"not_authenticated": "Nu sunteți autentificat pentru a efectua această acțiune.",
|
||||
"not_authorized": "Neautorizat",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Setări Organizație",
|
||||
"other": "Altele",
|
||||
"other_filters": "Alte Filtre",
|
||||
"others": "Altele",
|
||||
"other_placeholder": "Alt substituent",
|
||||
"overlay_color": "Culoare overlay",
|
||||
"overview": "Prezentare generală",
|
||||
"password": "Parolă",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Vă rugăm să faceți upgrade la planul dumneavoastră",
|
||||
"powered_by_formbricks": "Oferit de Formbricks",
|
||||
"preview": "Previzualizare",
|
||||
"preview_survey": "Previzualizare Chestionar",
|
||||
"privacy": "Politica de Confidențialitate",
|
||||
"product_manager": "Manager de Produs",
|
||||
"production": "Producție",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Răspunsuri",
|
||||
"restart": "Repornește",
|
||||
"role": "Rolul",
|
||||
"row_n": "Rândul {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Vânzări",
|
||||
"save": "Salvează",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Stocarea fișierelor neconfigurată, upload-urile vor eșua probabil",
|
||||
"string": "Text",
|
||||
"styling": "Stilizare",
|
||||
"subheader": "Subtitlu",
|
||||
"submit": "Trimite",
|
||||
"summary": "Sumar",
|
||||
"survey": "Chestionar",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "ex: Formbricks",
|
||||
"workspaces": "Workspaces",
|
||||
"years": "ani",
|
||||
"you": "Tu",
|
||||
"you_are_downgraded_to_the_community_edition": "Ai fost retrogradat la ediția Community.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Nu sunteți autorizat să efectuați această acțiune.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Ați atins limita de {projectLimit} spații de lucru.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Trimiteți datele în baza de date Notion",
|
||||
"please_select_a_survey_error": "Vă rugăm să selectați un sondaj",
|
||||
"reconnect_button": "Reconectează",
|
||||
"reconnect_button_description": "Conexiunea integrării tale a expirat. Te rugăm să te reconectezi pentru a continua sincronizarea răspunsurilor. Linkurile și datele tale existente vor fi păstrate.",
|
||||
"reconnect_button_tooltip": "Reconectează integrarea pentru a reîmprospăta accesul. Linkurile și datele tale existente vor fi păstrate.",
|
||||
"select_at_least_one_question_error": "Vă rugăm să selectați cel puțin o întrebare",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Ați conectat deja un alt chestionar la acest canal.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Ești gata! Este timpul să creezi primul tău chestionar",
|
||||
"alphabetical": "Alfabetic",
|
||||
"copy_survey": "Copiază sondajul",
|
||||
"copy_survey_description": "Copiază acest sondaj într-un alt mediu",
|
||||
"copy_survey_error": "Nu s-a putut copia sondajul",
|
||||
"copy_survey_link_to_clipboard": "Copiază linkul chestionarului în clipboard",
|
||||
"copy_survey_partially_success": "\"{success} sondaje copiate cu succes, {error} eșuate.\"",
|
||||
"copy_survey_success": "\"Sondaj copiat cu succes!\"",
|
||||
"delete_survey_and_responses_warning": "Sigur doriți să ștergeți acest sondaj și toate răspunsurile sale?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Alege limba implicită pentru acest sondaj:",
|
||||
"2_activate_translation_for_specific_languages": "2. Activați traducerea pentru anumite limbi:",
|
||||
"activate_translations": "Activează traducerile",
|
||||
"add": "Adaugă +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Adăugați o întârziere sau închideți automat sondajul",
|
||||
"add_a_four_digit_pin": "Adăugați un cod PIN din patru cifre",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Public",
|
||||
"auto_close_on_inactivity": "Închidere automată la inactivitate",
|
||||
"auto_progress_rating_and_nps": "Avansare automată pentru întrebări de rating și NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avansează automat când respondenții selectează un răspuns la întrebările de rating sau NPS. Aceasta se aplică doar blocurilor cu o singură întrebare. Întrebările obligatorii ascund butonul Următorul; întrebările opționale îl afișează în continuare pentru a permite omiterea.",
|
||||
"auto_progress_rating_and_nps_description": "Avansare automată în blocurile cu o singură întrebare. Întrebările obligatorii ascund butonul Următorul, cu excepția cazului în care este selectată opțiunea „Altele“.",
|
||||
"auto_save_disabled": "Salvare automată dezactivată",
|
||||
"auto_save_disabled_tooltip": "Chestionarul dvs. este salvat automat doar când este în ciornă. Acest lucru asigură că sondajele publice nu sunt actualizate neintenționat.",
|
||||
"auto_save_on": "Salvare automată activată",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Schimbările vor duce la inconsecvențe",
|
||||
"change_anyway": "Schimbă oricum",
|
||||
"change_background": "Schimbați fundalul",
|
||||
"change_default": "Schimbă implicit",
|
||||
"change_question_type": "Schimbă tipul întrebării",
|
||||
"change_survey_type": "Schimbarea tipului chestionarului afectează accesul existent",
|
||||
"change_the_background_to_a_color_image_or_animation": "Schimbați fundalul cu o culoare, imagine sau animație.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Alegeți unde să rulați chestionarul.",
|
||||
"city": "Oraș",
|
||||
"close_survey_on_response_limit": "Închideți sondajul la limită de răspunsuri",
|
||||
"code": "Cod",
|
||||
"color": "Culoare",
|
||||
"column_used_in_logic_error": "Această coloană este folosită în logica întrebării {questionIndex}. Vă rugăm să o eliminați din logică mai întâi.",
|
||||
"columns": "Coloane",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Personalizează logo-ul chestionarului",
|
||||
"darken_or_lighten_background_of_your_choice": "Întunecați sau luminați fundalul după preferințe.",
|
||||
"days_before_showing_this_survey_again": "sau mai multe zile să treacă între ultima afișare a sondajului și afișarea acestui sondaj.",
|
||||
"default_language": "Limba implicită",
|
||||
"delete_anyways": "Șterge oricum",
|
||||
"delete_block": "Șterge blocul",
|
||||
"delete_choice": "Șterge alegerea",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Duplică întrebarea",
|
||||
"edit_link": "Editare legătură",
|
||||
"edit_recall": "Editează Referințele",
|
||||
"edit_translations": "Editează traducerile {lang}",
|
||||
"element_not_found": "Întrebarea nu a fost găsită",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permite respondenților să schimbe limba în orice moment. Necesită minimum 2 limbi active.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "Protecția împotriva spamului folosește reCAPTCHA v3 pentru a filtra răspunsurile de spam.",
|
||||
@@ -1597,11 +1602,13 @@
|
||||
"long_answer": "Răspuns lung",
|
||||
"long_answer_toggle_description": "Permite respondenților să scrie răspunsuri mai lungi, pe mai multe rânduri.",
|
||||
"lower_label": "Etichetă inferioară",
|
||||
"manage_languages": "Gestionați limbile",
|
||||
"manage_languages": "Gestionează limbile",
|
||||
"manage_translations": "Gestionează traducerile",
|
||||
"matrix_all_fields": "Toate câmpurile",
|
||||
"matrix_rows": "Rânduri",
|
||||
"max_file_size": "Dimensiune maximă fișier",
|
||||
"max_file_size_limit_is": "Limita maximă pentru dimensiunea fișierului este",
|
||||
"missing_first": "Lipsă întâi",
|
||||
"move_question_to_block": "Mută întrebarea în bloc",
|
||||
"multiply": "Multiplicare",
|
||||
"needed_for_self_hosted_cal_com_instance": "Necesar pentru un exemplu autogăzduit Cal.com",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Etichetă buton \"Următorul\"",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Nu există încă câmpuri ascunse. Adăugați primul mai jos.",
|
||||
"no_images_found_for": "Nicio imagine găsită pentru ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nu s-au găsit limbi. Adaugă prima pentru a începe.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Nu s-au găsit limbi de chestionar în acest spațiu de lucru. Te rugăm să adaugi una pentru a începe.",
|
||||
"no_option_found": "Nicio opțiune găsită",
|
||||
"no_recall_items_found": "Nu au fost găsite elemente de reamintire",
|
||||
"no_variables_yet_add_first_one_below": "Nu există variabile încă. Adăugați prima mai jos.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Vă rugăm să introduceți un URL valid (de exemplu, https://example.com)",
|
||||
"please_set_a_survey_trigger": "Vă rugăm să setați un declanșator sondaj",
|
||||
"please_specify": "Vă rugăm să specificați",
|
||||
"present_your_survey_in_multiple_languages": "Prezintă chestionarul tău în mai multe limbi",
|
||||
"prevent_double_submission": "Prevenire trimitere dublă",
|
||||
"prevent_double_submission_description": "Permite doar 1 răspuns per adresă de email.",
|
||||
"progress_saved": "Progres salvat",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 puncte",
|
||||
"show_block_settings": "Afișează setările blocului",
|
||||
"show_button": "Afișează butonul",
|
||||
"show_in_order": "Afișează în ordine",
|
||||
"show_language_switch": "Afișează comutatorul de limbă",
|
||||
"show_multiple_times": "Afișează de mai multe ori",
|
||||
"show_only_once": "Afișează doar o dată",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Previzualizare chestionar 👀",
|
||||
"survey_styling": "Stilizare formular",
|
||||
"survey_trigger": "Declanșator sondaj",
|
||||
"switch_multi_language_on_to_get_started": "Activați opțiunea multi-limbă pentru a începe 👉",
|
||||
"target_block_not_found": "Blocul țintă nu a fost găsit",
|
||||
"targeted": "Ţintite",
|
||||
"ten_points": "10 puncte",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Afișează o singură dată, chiar dacă persoana nu răspunde.",
|
||||
"then": "Apoi",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Această acțiune va elimina toate traducerile din acest sondaj.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Aceasta va elimina această limbă și toate traducerile ei din acest chestionar. Această acțiune nu poate fi anulată.",
|
||||
"three_points": "3 puncte",
|
||||
"times": "ori",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Pentru a menține amplasarea consecventă pentru toate sondajele, puteți",
|
||||
"translated": "Tradus",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Declanșați sondajul atunci când una dintre acțiuni este realizată...",
|
||||
"try_lollipop_or_mountain": "Încercați „lollipop” sau „mountain”...",
|
||||
"type_field_id": "ID câmp tip",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Permite doar persoanelor cu un email real să răspundă.",
|
||||
"visibility_and_recontact": "Vizibilitate și recontactare",
|
||||
"visibility_and_recontact_description": "Controlează când poate apărea acest sondaj și cât de des poate reapărea.",
|
||||
"visible": "Vizibil",
|
||||
"wait": "Așteptați",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Așteptați câteva secunde după declanșare înainte de a afișa sondajul",
|
||||
"waiting_time_across_surveys": "Perioadă de răcire (între sondaje)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Se descarcă codul QR",
|
||||
"drop_offs": "Renunțări",
|
||||
"drop_offs_tooltip": "Număr de ori când sondajul a fost început dar nu a fost finalizat.",
|
||||
"failed_to_copy_link": "Nu s-a putut copia legătura",
|
||||
"filter_added_successfully": "Filtru adăugat cu succes",
|
||||
"filter_updated_successfully": "Filtru actualizat cu succes",
|
||||
"filtered_responses_csv": "Răspunsuri filtrate (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "\"Sondaj șters cu succes!\"",
|
||||
"survey_duplicated_successfully": "\"Sondaj duplicat cu succes!\"",
|
||||
"survey_duplication_error": "Eșec la duplicarea sondajului.",
|
||||
"templates": {
|
||||
"all_channels": "Toate canalele",
|
||||
"all_industries": "Toate industriile",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Limbă sau ID de limbă duplicat",
|
||||
"edit_languages": "Editați limbile",
|
||||
"identifier": "Identificator (ISO)",
|
||||
"incomplete_translations": "Traduceri incomplete",
|
||||
"language": "Limba",
|
||||
"language_deleted_successfully": "Limba a fost ștearsă cu succes",
|
||||
"languages_updated_successfully": "Limbile au fost actualizate cu succes",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Vă rugăm să selectați o limbă",
|
||||
"remove_language": "Eliminați limba",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Vă rugăm să eliminați limba din aceste sondaje pentru a o elimina din spațiul de lucru.",
|
||||
"search_items": "Căutați elemente",
|
||||
"translate": "Traduceți"
|
||||
"search_items": "Căutați elemente"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Adăugați culoare de fundal",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colorează partea necompletată a barei.",
|
||||
"advanced_styling_field_track_height": "Înălțime track",
|
||||
"advanced_styling_field_track_height_description": "Controlează grosimea barei de progres.",
|
||||
"advanced_styling_field_upper_label_color": "Culoare etichetă titlu",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorează eticheta mică de deasupra câmpurilor.",
|
||||
"advanced_styling_field_upper_label_size": "Mărime font etichetă titlu",
|
||||
"advanced_styling_field_upper_label_size_description": "Redimensionează eticheta mică de deasupra câmpurilor.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosime font etichetă titlu",
|
||||
"advanced_styling_field_upper_label_weight_description": "Face eticheta mai subțire sau mai îngroșată.",
|
||||
"advanced_styling_field_upper_label_color": "Culoare etichetă",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorează etichetele mici de deasupra câmpurilor de introducere și etichetele de scală.",
|
||||
"advanced_styling_field_upper_label_size": "Dimensiune font etichetă",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajustează dimensiunea etichetelor mici de deasupra câmpurilor de introducere și a etichetelor de scală.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosime font etichetă",
|
||||
"advanced_styling_field_upper_label_weight_description": "Face etichetele mai subțiri sau mai îngroșate.",
|
||||
"advanced_styling_section_buttons": "Butoane",
|
||||
"advanced_styling_section_headlines": "Titluri și descrieri",
|
||||
"advanced_styling_section_inputs": "Inputuri",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verificați-vă emailul pentru a răspunde",
|
||||
"verify_email_before_submission_button": "Verifică",
|
||||
"verify_email_before_submission_description": "Pentru a răspunde la acest sondaj, vă rugăm să vă verificați emailul",
|
||||
"want_to_respond": "Dorești să răspunzi?"
|
||||
"want_to_respond": "Dorești să răspunzi?",
|
||||
"paused_heading": "Pauză",
|
||||
"completed_heading": "Completat"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Care este acel lucru pe care l-am putea îmbunătăți?",
|
||||
"identify_customer_goals_description": "Înțelegeți mai bine dacă mesajele voastre creează așteptările corecte privind valoarea pe care o oferă produsul vostru.",
|
||||
"identify_customer_goals_name": "Identifică Obiectivele Clienților",
|
||||
"identify_customer_goals_question_1_choice_1": "Să îmi înțeleg în profunzime baza de utilizatori",
|
||||
"identify_customer_goals_question_1_choice_2": "Să identific oportunități de upselling",
|
||||
"identify_customer_goals_question_1_choice_3": "Să construiesc cel mai bun produs posibil",
|
||||
"identify_customer_goals_question_1_choice_4": "Să cuceresc lumea pentru a-i face tuturor la micul dejun varză de Bruxelles",
|
||||
"identify_customer_goals_question_1_headline": "Care este obiectivul tău principal pentru utilizarea $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Oferiți o reducere pentru a obține informații despre barierele de înscriere.",
|
||||
"identify_sign_up_barriers_name": "Identificați barierele de înscriere",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Obține reducere de 10%",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Ajută-ne să te înțelegem mai bine:",
|
||||
"improve_trial_conversion_question_2_button_label": "Următorul",
|
||||
"improve_trial_conversion_question_2_headline": "Ne pare rău să auzim asta. Care a fost cea mai mare problemă folosind $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Următorul",
|
||||
"improve_trial_conversion_question_3_headline": "Ce ați fi așteptat de la $[projectName]?",
|
||||
"improve_trial_conversion_question_4_button_label": "Obțineți 20% reducere",
|
||||
"improve_trial_conversion_question_4_headline": "Ne pare rău să auzim asta! Obțineți 20% reducere în primul an.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Suntem bucuroși să vă oferim o reducere de 20% la un plan anual.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Următorul",
|
||||
"improve_trial_conversion_question_5_headline": "Ce ați dori să obțineți?",
|
||||
"improve_trial_conversion_question_5_subheader": "Vă rugăm să selectați una dintre următoarele opțiuni:",
|
||||
"improve_trial_conversion_question_5_subheader": "Te rugăm să descrii mai jos:",
|
||||
"improve_trial_conversion_question_6_headline": "Cum rezolvați acum problema dumneavoastră?",
|
||||
"improve_trial_conversion_question_6_subheader": "Vă rugăm să numiți soluțiile alternative:",
|
||||
"integration_setup_survey_description": "Evaluați cât de ușor pot utilizatorii să adauge integrări la produsul dvs. Identificați punctele oarbe.",
|
||||
|
||||
+45
-29
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Ваша ссылка истекла.",
|
||||
"link_expired_description": "Ссылка, которой вы воспользовались, больше не действительна."
|
||||
"link_expired_description": "Ссылка, которой вы воспользовались, больше не действительна.",
|
||||
"link_expired_heading": "Ваша ссылка истекла."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Принято",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Центрированное модальное окно",
|
||||
"change_organization": "Сменить организацию",
|
||||
"change_workspace": "Сменить рабочее пространство",
|
||||
"choice_n": "Вариант {{n}}",
|
||||
"choices": "Варианты",
|
||||
"choose_environment": "Выберите среду",
|
||||
"choose_organization": "Выберите организацию",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Закрыть",
|
||||
"code": "Код",
|
||||
"collapse_rows": "Свернуть строки",
|
||||
"column_n": "Колонка {{n}}",
|
||||
"completed": "Завершено",
|
||||
"configuration": "Конфигурация",
|
||||
"confirm": "Подтвердить",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Не удалось скопировать в буфер обмена",
|
||||
"failed_to_load_organizations": "Не удалось загрузить организации",
|
||||
"failed_to_load_workspaces": "Не удалось загрузить рабочие пространства",
|
||||
"field_placeholder": "Заполнитель {{field}}",
|
||||
"filter": "Фильтр",
|
||||
"finish": "Завершить",
|
||||
"first_name": "Имя",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Сгенерировать",
|
||||
"go_back": "Назад",
|
||||
"go_to_dashboard": "Перейти к панели управления",
|
||||
"headline": "Заголовок",
|
||||
"hidden": "Скрыто",
|
||||
"hidden_field": "Скрытое поле",
|
||||
"hidden_fields": "Скрытые поля",
|
||||
"hide_column": "Скрыть столбец",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Изображение",
|
||||
"images": "Изображения",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "месяцы",
|
||||
"move_down": "Переместить вниз",
|
||||
"move_up": "Переместить вверх",
|
||||
"multiple_languages": "Несколько языков",
|
||||
"my_product": "мой продукт",
|
||||
"name": "Имя",
|
||||
"new": "Новый",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Результат не найден",
|
||||
"no_results": "Нет результатов",
|
||||
"no_surveys_found": "Опросы не найдены.",
|
||||
"no_text_found": "Текст не найден",
|
||||
"none_of_the_above": "Ничего из вышеперечисленного",
|
||||
"not_authenticated": "У вас нет прав для выполнения этого действия.",
|
||||
"not_authorized": "Нет доступа",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Настройки организации",
|
||||
"other": "Другое",
|
||||
"other_filters": "Другие фильтры",
|
||||
"others": "Другие",
|
||||
"other_placeholder": "Другой заполнитель",
|
||||
"overlay_color": "Цвет наложения",
|
||||
"overview": "Обзор",
|
||||
"password": "Пароль",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Пожалуйста, обновите ваш тарифный план",
|
||||
"powered_by_formbricks": "Работает на Formbricks",
|
||||
"preview": "Предпросмотр",
|
||||
"preview_survey": "Предпросмотр опроса",
|
||||
"privacy": "Политика конфиденциальности",
|
||||
"product_manager": "Менеджер продукта",
|
||||
"production": "Продакшн",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Ответы",
|
||||
"restart": "Перезапустить",
|
||||
"role": "Роль",
|
||||
"row_n": "Строка {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Продажи",
|
||||
"save": "Сохранить",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Хранилище файлов не настроено, загрузка, скорее всего, не удастся",
|
||||
"string": "Текст",
|
||||
"styling": "Стилизация",
|
||||
"subheader": "Подзаголовок",
|
||||
"submit": "Отправить",
|
||||
"summary": "Сводка",
|
||||
"survey": "Опрос",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "например, Formbricks",
|
||||
"workspaces": "Рабочие пространства",
|
||||
"years": "годы",
|
||||
"you": "Вы",
|
||||
"you_are_downgraded_to_the_community_edition": "Ваша версия понижена до Community Edition.",
|
||||
"you_are_not_authorized_to_perform_this_action": "У вас нет прав для выполнения этого действия.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Вы достигли лимита в {projectLimit} рабочих пространств.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Отправляйте данные в вашу базу данных Notion",
|
||||
"please_select_a_survey_error": "Пожалуйста, выберите опрос",
|
||||
"reconnect_button": "Переподключить",
|
||||
"reconnect_button_description": "Срок действия подключения интеграции истёк. Пожалуйста, переподключитесь, чтобы продолжить синхронизацию ответов. Ваши существующие ссылки и данные будут сохранены.",
|
||||
"reconnect_button_tooltip": "Переподключите интеграцию, чтобы обновить доступ. Ваши существующие ссылки и данные будут сохранены.",
|
||||
"select_at_least_one_question_error": "Пожалуйста, выберите хотя бы один вопрос",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Вы уже подключили другой опрос к этому каналу.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Всё готово! Пора создать первый опрос",
|
||||
"alphabetical": "По алфавиту",
|
||||
"copy_survey": "Копировать опрос",
|
||||
"copy_survey_description": "Скопируйте этот опрос в другую среду",
|
||||
"copy_survey_error": "Не удалось скопировать опрос",
|
||||
"copy_survey_link_to_clipboard": "Скопировать ссылку на опрос в буфер обмена",
|
||||
"copy_survey_partially_success": "Успешно скопировано опросов: {success}, не удалось: {error}.",
|
||||
"copy_survey_success": "Опрос успешно скопирован!",
|
||||
"delete_survey_and_responses_warning": "Вы уверены, что хотите удалить этот опрос и все его ответы?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Выберите язык по умолчанию для этого опроса:",
|
||||
"2_activate_translation_for_specific_languages": "2. Активируйте перевод для выбранных языков:",
|
||||
"activate_translations": "Активировать переводы",
|
||||
"add": "Добавить +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Добавить задержку или автоматически закрыть опрос",
|
||||
"add_a_four_digit_pin": "Добавить четырёхзначный PIN-код",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Аудитория",
|
||||
"auto_close_on_inactivity": "Автоматически закрывать при бездействии",
|
||||
"auto_progress_rating_and_nps": "Автоматический переход для вопросов с оценкой и NPS",
|
||||
"auto_progress_rating_and_nps_description": "Автоматически переходить к следующему шагу, когда респонденты выбирают ответ в вопросах с оценкой или NPS. Это применяется только к блокам с одним вопросом. В обязательных вопросах кнопка «Далее» скрыта; в необязательных вопросах она остается видимой для пропуска.",
|
||||
"auto_progress_rating_and_nps_description": "Автоматический переход в блоках с одним вопросом. Обязательные вопросы скрывают кнопку «Далее», за исключением случаев, когда выбран вариант «Другое».",
|
||||
"auto_save_disabled": "Автосохранение отключено",
|
||||
"auto_save_disabled_tooltip": "Ваш опрос автоматически сохраняется только в режиме черновика. Это гарантирует, что публичные опросы не будут случайно обновлены.",
|
||||
"auto_save_on": "Автосохранение включено",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Изменения приведут к несоответствиям",
|
||||
"change_anyway": "Всё равно изменить",
|
||||
"change_background": "Изменить фон",
|
||||
"change_default": "Изменить по умолчанию",
|
||||
"change_question_type": "Изменить тип вопроса",
|
||||
"change_survey_type": "Смена типа опроса влияет на существующий доступ",
|
||||
"change_the_background_to_a_color_image_or_animation": "Изменить фон на цвет, изображение или анимацию.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Выберите, где запускать опрос.",
|
||||
"city": "Город",
|
||||
"close_survey_on_response_limit": "Закрыть опрос при достижении лимита ответов",
|
||||
"code": "Код",
|
||||
"color": "Цвет",
|
||||
"column_used_in_logic_error": "Этот столбец используется в логике вопроса {questionIndex}. Пожалуйста, сначала удалите его из логики.",
|
||||
"columns": "Столбцы",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Настроить логотип опроса",
|
||||
"darken_or_lighten_background_of_your_choice": "Затемните или осветлите выбранный фон.",
|
||||
"days_before_showing_this_survey_again": "или больше дней должно пройти между последним показом опроса и показом этого опроса.",
|
||||
"default_language": "Язык по умолчанию",
|
||||
"delete_anyways": "Удалить в любом случае",
|
||||
"delete_block": "Удалить блок",
|
||||
"delete_choice": "Удалить вариант",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Дублировать вопрос",
|
||||
"edit_link": "Редактировать ссылку",
|
||||
"edit_recall": "Редактировать напоминание",
|
||||
"edit_translations": "Редактировать переводы на {lang}",
|
||||
"element_not_found": "Вопрос не найден",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Разрешить респондентам менять язык опроса в любое время. Требуется минимум 2 активных языка.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "Для защиты от спама используется reCAPTCHA v3, чтобы отфильтровывать спам-ответы.",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "Позволить респондентам писать более длинные, многострочные ответы.",
|
||||
"lower_label": "Нижняя метка",
|
||||
"manage_languages": "Управление языками",
|
||||
"manage_translations": "Управление переводами",
|
||||
"matrix_all_fields": "Все поля",
|
||||
"matrix_rows": "Строки",
|
||||
"max_file_size": "Максимальный размер файла",
|
||||
"max_file_size_limit_is": "Ограничение максимального размера файла",
|
||||
"missing_first": "Сначала отсутствующие",
|
||||
"move_question_to_block": "Переместить вопрос в блок",
|
||||
"multiply": "Умножить *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Требуется для самостоятельного размещения Cal.com",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "Метка кнопки «Далее»",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Скрытых полей пока нет. Добавьте первое ниже.",
|
||||
"no_images_found_for": "Изображения не найдены для «{query}»",
|
||||
"no_languages_found_add_first_one_to_get_started": "Языки не найдены. Добавьте первый, чтобы начать.",
|
||||
"no_languages_found_add_first_one_to_get_started": "В этом рабочем пространстве не найдено языков опроса. Пожалуйста, добавьте язык, чтобы начать работу.",
|
||||
"no_option_found": "Вариант не найден",
|
||||
"no_recall_items_found": "Не найдено ни одного элемента для напоминания",
|
||||
"no_variables_yet_add_first_one_below": "Пока нет переменных. Добавьте первую ниже.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Пожалуйста, введите корректный URL (например, https://example.com)",
|
||||
"please_set_a_survey_trigger": "Пожалуйста, установите триггер опроса",
|
||||
"please_specify": "Пожалуйста, уточните",
|
||||
"present_your_survey_in_multiple_languages": "Представьте свой опрос на нескольких языках",
|
||||
"prevent_double_submission": "Предотвратить повторную отправку",
|
||||
"prevent_double_submission_description": "Разрешить только 1 ответ на один адрес электронной почты",
|
||||
"progress_saved": "Прогресс сохранён",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 баллов",
|
||||
"show_block_settings": "Показать настройки блока",
|
||||
"show_button": "Показать кнопку",
|
||||
"show_in_order": "Показать по порядку",
|
||||
"show_language_switch": "Показать переключатель языка",
|
||||
"show_multiple_times": "Показать ограниченное количество раз",
|
||||
"show_only_once": "Показать только один раз",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Предпросмотр опроса 👀",
|
||||
"survey_styling": "Оформление формы",
|
||||
"survey_trigger": "Триггер опроса",
|
||||
"switch_multi_language_on_to_get_started": "Включите многоязычный режим, чтобы начать 👉",
|
||||
"target_block_not_found": "Целевой блок не найден",
|
||||
"targeted": "Нацелен",
|
||||
"ten_points": "10 баллов",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Показать один раз, даже если не будет ответа.",
|
||||
"then": "Затем",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Это действие удалит все переводы из этого опроса.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Это удалит данный язык и все его переводы из этого опроса. Это действие нельзя отменить.",
|
||||
"three_points": "3 балла",
|
||||
"times": "раз",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "Чтобы сохранить единое расположение во всех опросах, вы можете",
|
||||
"translated": "Переведено",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Запустить опрос при выполнении одного из действий...",
|
||||
"try_lollipop_or_mountain": "Попробуйте «lollipop» или «mountain»...",
|
||||
"type_field_id": "Введите id поля",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Разрешить отвечать только пользователям с реальным email.",
|
||||
"visibility_and_recontact": "Видимость и повторный контакт",
|
||||
"visibility_and_recontact_description": "Управляйте, когда этот опрос может появляться и как часто он может повторяться.",
|
||||
"visible": "Видимый",
|
||||
"wait": "Ожидание",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Подождите несколько секунд после срабатывания триггера перед показом опроса",
|
||||
"waiting_time_across_surveys": "Период ожидания (между опросами)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Скачивание QR-кода",
|
||||
"drop_offs": "Прерывания",
|
||||
"drop_offs_tooltip": "Количество раз, когда опрос был начат, но не завершён.",
|
||||
"failed_to_copy_link": "Не удалось скопировать ссылку",
|
||||
"filter_added_successfully": "Фильтр успешно добавлен",
|
||||
"filter_updated_successfully": "Фильтр успешно обновлён",
|
||||
"filtered_responses_csv": "Отфильтрованные ответы (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Опрос успешно удалён!",
|
||||
"survey_duplicated_successfully": "Опрос успешно продублирован.",
|
||||
"survey_duplication_error": "Не удалось продублировать опрос.",
|
||||
"templates": {
|
||||
"all_channels": "Все каналы",
|
||||
"all_industries": "Все отрасли",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Дублирующийся язык или идентификатор языка",
|
||||
"edit_languages": "Редактировать языки",
|
||||
"identifier": "Идентификатор (ISO)",
|
||||
"incomplete_translations": "Неполные переводы",
|
||||
"language": "Язык",
|
||||
"language_deleted_successfully": "Язык успешно удалён",
|
||||
"languages_updated_successfully": "Языки успешно обновлены",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Пожалуйста, выберите язык",
|
||||
"remove_language": "Удалить язык",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Пожалуйста, удалите язык из этих опросов, чтобы удалить его из рабочей области.",
|
||||
"search_items": "Поиск элементов",
|
||||
"translate": "Перевести"
|
||||
"search_items": "Поиск элементов"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Добавить цвет фона",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Задаёт цвет незаполненной части полосы.",
|
||||
"advanced_styling_field_track_height": "Высота трека",
|
||||
"advanced_styling_field_track_height_description": "Управляет толщиной индикатора прогресса.",
|
||||
"advanced_styling_field_upper_label_color": "Цвет метки заголовка",
|
||||
"advanced_styling_field_upper_label_color_description": "Задаёт цвет маленькой метки над полями ввода.",
|
||||
"advanced_styling_field_upper_label_size": "Размер шрифта метки заголовка",
|
||||
"advanced_styling_field_upper_label_size_description": "Изменяет размер маленькой метки над полями ввода.",
|
||||
"advanced_styling_field_upper_label_weight": "Толщина шрифта метки заголовка",
|
||||
"advanced_styling_field_upper_label_weight_description": "Делает метку тоньше или жирнее.",
|
||||
"advanced_styling_field_upper_label_color": "Цвет подписи",
|
||||
"advanced_styling_field_upper_label_color_description": "Задаёт цвет маленьких подписей над полями ввода и подписей шкалы.",
|
||||
"advanced_styling_field_upper_label_size": "Размер шрифта подписи",
|
||||
"advanced_styling_field_upper_label_size_description": "Изменяет размер маленьких подписей над полями ввода и подписей шкалы.",
|
||||
"advanced_styling_field_upper_label_weight": "Насыщенность шрифта подписи",
|
||||
"advanced_styling_field_upper_label_weight_description": "Делает подписи светлее или жирнее.",
|
||||
"advanced_styling_section_buttons": "Кнопки",
|
||||
"advanced_styling_section_headlines": "Заголовки и описания",
|
||||
"advanced_styling_section_inputs": "Поля ввода",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Подтвердите свой email, чтобы ответить",
|
||||
"verify_email_before_submission_button": "Подтвердить",
|
||||
"verify_email_before_submission_description": "Чтобы ответить на этот опрос, пожалуйста, подтвердите свой email",
|
||||
"want_to_respond": "Хотите ответить?"
|
||||
"want_to_respond": "Хотите ответить?",
|
||||
"paused_heading": "Приостановлено",
|
||||
"completed_heading": "Завершено"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Что мы могли бы сделать лучше?",
|
||||
"identify_customer_goals_description": "Лучше понять, создают ли ваши сообщения правильные ожидания относительно ценности вашего продукта.",
|
||||
"identify_customer_goals_name": "Определение целей клиента",
|
||||
"identify_customer_goals_question_1_choice_1": "Глубоко понять свою пользовательскую базу",
|
||||
"identify_customer_goals_question_1_choice_2": "Выявить возможности для допродаж",
|
||||
"identify_customer_goals_question_1_choice_3": "Создать наилучший продукт",
|
||||
"identify_customer_goals_question_1_choice_4": "Править миром, чтобы накормить всех брюссельской капустой на завтрак",
|
||||
"identify_customer_goals_question_1_headline": "Какова ваша основная цель использования $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Предложите скидку, чтобы узнать, что мешает регистрации.",
|
||||
"identify_sign_up_barriers_name": "Определение барьеров регистрации",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Получить скидку 10%",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Помогите нам лучше вас понять:",
|
||||
"improve_trial_conversion_question_2_button_label": "Далее",
|
||||
"improve_trial_conversion_question_2_headline": "Жаль это слышать. Какая была самая большая проблема при использовании $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Далее",
|
||||
"improve_trial_conversion_question_3_headline": "Что вы ожидали от $[projectName]?",
|
||||
"improve_trial_conversion_question_4_button_label": "Получить скидку 20%",
|
||||
"improve_trial_conversion_question_4_headline": "Жаль это слышать! Получите 20% скидку на первый год.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Мы рады предложить вам скидку 20% на годовой тариф.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Далее",
|
||||
"improve_trial_conversion_question_5_headline": "Чего бы вы хотели достичь?",
|
||||
"improve_trial_conversion_question_5_subheader": "Пожалуйста, выберите один из следующих вариантов:",
|
||||
"improve_trial_conversion_question_5_subheader": "Пожалуйста, опишите ниже:",
|
||||
"improve_trial_conversion_question_6_headline": "Как вы сейчас решаете свою проблему?",
|
||||
"improve_trial_conversion_question_6_subheader": "Пожалуйста, укажите альтернативные решения:",
|
||||
"integration_setup_survey_description": "Оцените, насколько легко пользователи могут добавлять интеграции в ваш продукт. Найдите слабые места.",
|
||||
|
||||
+45
-29
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "Din länk har gått ut.",
|
||||
"link_expired_description": "Länken du använde är inte längre giltig."
|
||||
"link_expired_description": "Länken du använde är inte längre giltig.",
|
||||
"link_expired_heading": "Din länk har gått ut."
|
||||
},
|
||||
"common": {
|
||||
"accepted": "Accepterad",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "Centrerad modal",
|
||||
"change_organization": "Byt organisation",
|
||||
"change_workspace": "Byt arbetsyta",
|
||||
"choice_n": "Val {{n}}",
|
||||
"choices": "Val",
|
||||
"choose_environment": "Välj miljö",
|
||||
"choose_organization": "Välj organisation",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "Stäng",
|
||||
"code": "Kod",
|
||||
"collapse_rows": "Dölj rader",
|
||||
"column_n": "Kolumn {{n}}",
|
||||
"completed": "Slutförd",
|
||||
"configuration": "Konfiguration",
|
||||
"confirm": "Bekräfta",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "Misslyckades att kopiera till urklipp",
|
||||
"failed_to_load_organizations": "Misslyckades att ladda organisationer",
|
||||
"failed_to_load_workspaces": "Det gick inte att ladda arbetsytor",
|
||||
"field_placeholder": "Platshållare för {{field}}",
|
||||
"filter": "Filter",
|
||||
"finish": "Slutför",
|
||||
"first_name": "Förnamn",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "Generera",
|
||||
"go_back": "Gå tillbaka",
|
||||
"go_to_dashboard": "Gå till instrumentpanelen",
|
||||
"headline": "Rubrik",
|
||||
"hidden": "Dold",
|
||||
"hidden_field": "Dolt fält",
|
||||
"hidden_fields": "Dolda fält",
|
||||
"hide_column": "Dölj kolumn",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "Bild",
|
||||
"images": "Bilder",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "månader",
|
||||
"move_down": "Flytta ner",
|
||||
"move_up": "Flytta upp",
|
||||
"multiple_languages": "Flera språk",
|
||||
"my_product": "min produkt",
|
||||
"name": "Namn",
|
||||
"new": "Ny",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "Inget resultat hittades",
|
||||
"no_results": "Inga resultat",
|
||||
"no_surveys_found": "Inga enkäter hittades.",
|
||||
"no_text_found": "Ingen text hittades",
|
||||
"none_of_the_above": "Inget av ovanstående",
|
||||
"not_authenticated": "Du är inte autentiserad för att utföra denna åtgärd.",
|
||||
"not_authorized": "Ej behörig",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "Organisationsinställningar",
|
||||
"other": "Annat",
|
||||
"other_filters": "Andra filter",
|
||||
"others": "Andra",
|
||||
"other_placeholder": "Annan platshållare",
|
||||
"overlay_color": "Overlay-färg",
|
||||
"overview": "Översikt",
|
||||
"password": "Lösenord",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "Vänligen uppgradera din plan",
|
||||
"powered_by_formbricks": "Drivs av Formbricks",
|
||||
"preview": "Förhandsgranska",
|
||||
"preview_survey": "Förhandsgranska enkät",
|
||||
"privacy": "Integritetspolicy",
|
||||
"product_manager": "Produktchef",
|
||||
"production": "Produktion",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "Svar",
|
||||
"restart": "Starta om",
|
||||
"role": "Roll",
|
||||
"row_n": "Rad {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "Försäljning",
|
||||
"save": "Spara",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "Fillagring är inte konfigurerad, uppladdningar kommer sannolikt att misslyckas",
|
||||
"string": "Text",
|
||||
"styling": "Styling",
|
||||
"subheader": "Underrubrik",
|
||||
"submit": "Skicka",
|
||||
"summary": "Sammanfattning",
|
||||
"survey": "Enkät",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "t.ex. Formbricks",
|
||||
"workspaces": "Arbetsytor",
|
||||
"years": "år",
|
||||
"you": "Du",
|
||||
"you_are_downgraded_to_the_community_edition": "Du har nedgraderats till Community Edition.",
|
||||
"you_are_not_authorized_to_perform_this_action": "Du har inte behörighet att utföra denna åtgärd.",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "Du har nått din gräns på {projectLimit} arbetsytor.",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "Skicka data till din Notion-databas",
|
||||
"please_select_a_survey_error": "Vänligen välj en enkät",
|
||||
"reconnect_button": "Återanslut",
|
||||
"reconnect_button_description": "Din integrationsanslutning har gått ut. Vänligen återanslut för att fortsätta synkronisera svar. Dina befintliga länkar och data kommer att bevaras.",
|
||||
"reconnect_button_tooltip": "Återanslut integrationen för att uppdatera din åtkomst. Dina befintliga länkar och data kommer att bevaras.",
|
||||
"select_at_least_one_question_error": "Vänligen välj minst en fråga",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "Du har redan anslutit en annan enkät till denna kanal.",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "Allt klart! Dags att skapa din första enkät",
|
||||
"alphabetical": "Alfabetisk",
|
||||
"copy_survey": "Kopiera enkät",
|
||||
"copy_survey_description": "Kopiera denna enkät till en annan miljö",
|
||||
"copy_survey_error": "Misslyckades med att kopiera enkät",
|
||||
"copy_survey_link_to_clipboard": "Kopiera enkätlänk till urklipp",
|
||||
"copy_survey_partially_success": "{success} enkäter kopierade, {error} misslyckades.",
|
||||
"copy_survey_success": "Enkät kopierad!",
|
||||
"delete_survey_and_responses_warning": "Är du säker på att du vill ta bort denna enkät och alla dess svar?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. Välj standardspråk för denna enkät:",
|
||||
"2_activate_translation_for_specific_languages": "2. Aktivera översättning för specifika språk:",
|
||||
"activate_translations": "Aktivera översättningar",
|
||||
"add": "Lägg till +",
|
||||
"add_a_delay_or_auto_close_the_survey": "Lägg till fördröjning eller stäng enkäten automatiskt",
|
||||
"add_a_four_digit_pin": "Lägg till en fyrsiffrig PIN",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "Målgrupp",
|
||||
"auto_close_on_inactivity": "Stäng automatiskt vid inaktivitet",
|
||||
"auto_progress_rating_and_nps": "Gå vidare automatiskt vid betygs- och NPS-frågor",
|
||||
"auto_progress_rating_and_nps_description": "Gå automatiskt vidare när respondenter väljer ett svar på betygs- eller NPS-frågor. Detta gäller endast block med en enda fråga. Obligatoriska frågor döljer Nästa-knappen; valfria frågor visar den fortfarande för att kunna hoppas över.",
|
||||
"auto_progress_rating_and_nps_description": "Gå automatiskt vidare i block med en enda fråga. Obligatoriska frågor döljer Nästa, utom när \"Annat\" är valt.",
|
||||
"auto_save_disabled": "Automatisk sparning inaktiverad",
|
||||
"auto_save_disabled_tooltip": "Din enkät sparas endast automatiskt när den är ett utkast. Detta säkerställer att publika enkäter inte uppdateras oavsiktligt.",
|
||||
"auto_save_on": "Automatisk sparning på",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "Ändringar kommer att leda till inkonsekvenser",
|
||||
"change_anyway": "Ändra ändå",
|
||||
"change_background": "Ändra bakgrund",
|
||||
"change_default": "Ändra standard",
|
||||
"change_question_type": "Ändra frågetyp",
|
||||
"change_survey_type": "Byte av enkättyp påverkar befintlig åtkomst",
|
||||
"change_the_background_to_a_color_image_or_animation": "Ändra bakgrunden till en färg, bild eller animering.",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "Välj var enkäten ska köras.",
|
||||
"city": "Stad",
|
||||
"close_survey_on_response_limit": "Stäng enkät vid svarsgräns",
|
||||
"code": "Kod",
|
||||
"color": "Färg",
|
||||
"column_used_in_logic_error": "Denna kolumn används i logiken för fråga {questionIndex}. Vänligen ta bort den från logiken först.",
|
||||
"columns": "Kolumner",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "Anpassa undersökningens logotyp",
|
||||
"darken_or_lighten_background_of_your_choice": "Gör bakgrunden mörkare eller ljusare efter eget val.",
|
||||
"days_before_showing_this_survey_again": "eller fler dagar måste gå mellan den senaste visade enkäten och att visa denna enkät.",
|
||||
"default_language": "Standardspråk",
|
||||
"delete_anyways": "Ta bort ändå",
|
||||
"delete_block": "Ta bort block",
|
||||
"delete_choice": "Ta bort val",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "Duplicera fråga",
|
||||
"edit_link": "Redigera länk",
|
||||
"edit_recall": "Redigera återkallning",
|
||||
"edit_translations": "Redigera {lang} översättningar",
|
||||
"element_not_found": "Fråga hittades inte",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Tillåt respondenter att byta språk när som helst. Kräver minst 2 aktiva språk.",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "Spamskydd använder reCAPTCHA v3 för att filtrera bort spam-svar.",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "Tillåt respondenter att skriva längre svar på flera rader.",
|
||||
"lower_label": "Lägre etikett",
|
||||
"manage_languages": "Hantera språk",
|
||||
"manage_translations": "Hantera översättningar",
|
||||
"matrix_all_fields": "Alla fält",
|
||||
"matrix_rows": "Rader",
|
||||
"max_file_size": "Max filstorlek",
|
||||
"max_file_size_limit_is": "Maximal filstorleksgräns är",
|
||||
"missing_first": "Saknade först",
|
||||
"move_question_to_block": "Flytta fråga till block",
|
||||
"multiply": "Multiplicera *",
|
||||
"needed_for_self_hosted_cal_com_instance": "Behövs för en självhostad Cal.com-instans",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "\"Nästa\"-knappetikett",
|
||||
"no_hidden_fields_yet_add_first_one_below": "Inga dolda fält ännu. Lägg till det första nedan.",
|
||||
"no_images_found_for": "Inga bilder hittades för ''{query}\"",
|
||||
"no_languages_found_add_first_one_to_get_started": "Inga språk hittades. Lägg till det första för att komma igång.",
|
||||
"no_languages_found_add_first_one_to_get_started": "Inga undersökningsspråk hittades i denna arbetsyta. Lägg till ett för att komma igång.",
|
||||
"no_option_found": "Inget alternativ hittat",
|
||||
"no_recall_items_found": "Inga återkallningsobjekt hittades",
|
||||
"no_variables_yet_add_first_one_below": "Inga variabler ännu. Lägg till den första nedan.",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "Vänligen ange en giltig URL (t.ex. https://example.com)",
|
||||
"please_set_a_survey_trigger": "Vänligen ställ in en enkätutlösare",
|
||||
"please_specify": "Vänligen specificera",
|
||||
"present_your_survey_in_multiple_languages": "Presentera din enkät på flera språk",
|
||||
"prevent_double_submission": "Förhindra dubbelinskickning",
|
||||
"prevent_double_submission_description": "Tillåt endast 1 svar per e-postadress",
|
||||
"progress_saved": "Framsteg sparade",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 poäng",
|
||||
"show_block_settings": "Visa blockinställningar",
|
||||
"show_button": "Visa knapp",
|
||||
"show_in_order": "Visa i ordning",
|
||||
"show_language_switch": "Visa språkväxlare",
|
||||
"show_multiple_times": "Visa ett begränsat antal gånger",
|
||||
"show_only_once": "Visa endast en gång",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "Enkätförhandsgranskning 👀",
|
||||
"survey_styling": "Formulärstil",
|
||||
"survey_trigger": "Enkätutlösare",
|
||||
"switch_multi_language_on_to_get_started": "Slå på flerspråkighet för att komma igång 👉",
|
||||
"target_block_not_found": "Målblock hittades inte",
|
||||
"targeted": "Riktad",
|
||||
"ten_points": "10 poäng",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "Visa en enda gång, även om de inte svarar.",
|
||||
"then": "Sedan",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "Denna åtgärd kommer att ta bort alla översättningar från denna enkät.",
|
||||
"this_will_remove_the_language_and_all_its_translations": "Detta tar bort språket och alla dess översättningar från denna enkät. Denna åtgärd kan inte ångras.",
|
||||
"three_points": "3 poäng",
|
||||
"times": "gånger",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "För att hålla placeringen konsekvent över alla enkäter kan du",
|
||||
"translated": "Översatt",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "Utlös enkät när en av åtgärderna aktiveras...",
|
||||
"try_lollipop_or_mountain": "Prova 'lollipop' eller 'mountain'...",
|
||||
"type_field_id": "Skriv fält-ID",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "Låt endast personer med en riktig e-post svara.",
|
||||
"visibility_and_recontact": "Synlighet och återkontakt",
|
||||
"visibility_and_recontact_description": "Kontrollera när denna enkät kan visas och hur ofta den kan visas igen.",
|
||||
"visible": "Synlig",
|
||||
"wait": "Vänta",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "Vänta några sekunder efter utlösningen innan enkäten visas",
|
||||
"waiting_time_across_surveys": "Väntetid (mellan enkäter)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "Laddar ner QR-kod",
|
||||
"drop_offs": "Avhopp",
|
||||
"drop_offs_tooltip": "Antal gånger enkäten har startats men inte slutförts.",
|
||||
"failed_to_copy_link": "Misslyckades med att kopiera länk",
|
||||
"filter_added_successfully": "Filter tillagt",
|
||||
"filter_updated_successfully": "Filter uppdaterat",
|
||||
"filtered_responses_csv": "Filtrerade svar (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "Enkät borttagen!",
|
||||
"survey_duplicated_successfully": "Enkät duplicerad.",
|
||||
"survey_duplication_error": "Misslyckades med att duplicera enkäten.",
|
||||
"templates": {
|
||||
"all_channels": "Alla kanaler",
|
||||
"all_industries": "Alla branscher",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "Duplicerat språk eller språk-ID",
|
||||
"edit_languages": "Redigera språk",
|
||||
"identifier": "Identifierare (ISO)",
|
||||
"incomplete_translations": "Ofullständiga översättningar",
|
||||
"language": "Språk",
|
||||
"language_deleted_successfully": "Språket har tagits bort",
|
||||
"languages_updated_successfully": "Språken har uppdaterats",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "Vänligen välj ett språk",
|
||||
"remove_language": "Ta bort språk",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "Ta bort språket från dessa enkäter för att kunna ta bort det från arbetsytan.",
|
||||
"search_items": "Sök objekt",
|
||||
"translate": "Översätt"
|
||||
"search_items": "Sök objekt"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "Lägg till bakgrundsfärg",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Färgar den ofyllda delen av stapeln.",
|
||||
"advanced_styling_field_track_height": "Spårets höjd",
|
||||
"advanced_styling_field_track_height_description": "Styr tjockleken på förloppsstapeln.",
|
||||
"advanced_styling_field_upper_label_color": "Rubriketikettens färg",
|
||||
"advanced_styling_field_upper_label_color_description": "Färgar den lilla etiketten ovanför fälten.",
|
||||
"advanced_styling_field_upper_label_size": "Rubriketikettens teckenstorlek",
|
||||
"advanced_styling_field_upper_label_size_description": "Skalar storleken på den lilla etiketten ovanför fälten.",
|
||||
"advanced_styling_field_upper_label_weight": "Rubriketikettens teckentjocklek",
|
||||
"advanced_styling_field_upper_label_weight_description": "Gör etiketten tunnare eller fetare.",
|
||||
"advanced_styling_field_upper_label_color": "Etiketfärg",
|
||||
"advanced_styling_field_upper_label_color_description": "Färglägger de små etiketterna ovanför inmatningsfält och skalans etiketter.",
|
||||
"advanced_styling_field_upper_label_size": "Etiketttextstorlek",
|
||||
"advanced_styling_field_upper_label_size_description": "Skalar storleken på de små etiketterna ovanför inmatningsfält och skalans etiketter.",
|
||||
"advanced_styling_field_upper_label_weight": "Etiketttextvikt",
|
||||
"advanced_styling_field_upper_label_weight_description": "Gör etiketterna ljusare eller fetare.",
|
||||
"advanced_styling_section_buttons": "Knappar",
|
||||
"advanced_styling_section_headlines": "Rubriker & beskrivningar",
|
||||
"advanced_styling_section_inputs": "Inmatningar",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "Verifiera din e-post för att svara",
|
||||
"verify_email_before_submission_button": "Verifiera",
|
||||
"verify_email_before_submission_description": "För att svara på denna enkät, vänligen verifiera din e-post",
|
||||
"want_to_respond": "Vill du svara?"
|
||||
"want_to_respond": "Vill du svara?",
|
||||
"paused_heading": "Pausad",
|
||||
"completed_heading": "Slutförd"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "Vad är en sak vi kunde göra bättre?",
|
||||
"identify_customer_goals_description": "Förstå bättre om din kommunikation skapar rätt förväntningar på värdet din produkt ger.",
|
||||
"identify_customer_goals_name": "Identifiera kundmål",
|
||||
"identify_customer_goals_question_1_choice_1": "Förstå min användarbas på djupet",
|
||||
"identify_customer_goals_question_1_choice_2": "Identifiera merförsäljningsmöjligheter",
|
||||
"identify_customer_goals_question_1_choice_3": "Bygga bästa möjliga produkt",
|
||||
"identify_customer_goals_question_1_choice_4": "Härska över världen för att få alla att äta brysselkål till frukost",
|
||||
"identify_customer_goals_question_1_headline": "Vad är ditt primära mål med att använda $[projectName]?",
|
||||
"identify_sign_up_barriers_description": "Erbjud en rabatt för att samla insikter om registreringshinder.",
|
||||
"identify_sign_up_barriers_name": "Identifiera registreringshinder",
|
||||
"identify_sign_up_barriers_question_1_button_label": "Få 10% rabatt",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "Hjälp oss förstå dig bättre:",
|
||||
"improve_trial_conversion_question_2_button_label": "Nästa",
|
||||
"improve_trial_conversion_question_2_headline": "Tråkigt att höra. Vad var det största problemet med att använda $[projectName]?",
|
||||
"improve_trial_conversion_question_3_button_label": "Nästa",
|
||||
"improve_trial_conversion_question_3_headline": "Vad förväntade du dig att $[projectName] skulle göra?",
|
||||
"improve_trial_conversion_question_4_button_label": "Få 20% rabatt",
|
||||
"improve_trial_conversion_question_4_headline": "Tråkigt att höra! Få 20% rabatt första året.",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>Vi erbjuder dig gärna 20% rabatt på en årsplan.</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "Nästa",
|
||||
"improve_trial_conversion_question_5_headline": "Vad vill du uppnå?",
|
||||
"improve_trial_conversion_question_5_subheader": "Vänligen välj ett av följande alternativ:",
|
||||
"improve_trial_conversion_question_5_subheader": "Beskriv gärna nedan:",
|
||||
"improve_trial_conversion_question_6_headline": "Hur löser du ditt problem nu?",
|
||||
"improve_trial_conversion_question_6_subheader": "Vänligen nämn alternativa lösningar:",
|
||||
"integration_setup_survey_description": "Utvärdera hur enkelt användare kan lägga till integrationer i din produkt. Hitta blinda fläckar.",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "您的 链接 已过期。",
|
||||
"link_expired_description": "您 使用 的 链接 已失效。"
|
||||
"link_expired_description": "您 使用 的 链接 已失效。",
|
||||
"link_expired_heading": "您的 链接 已过期。"
|
||||
},
|
||||
"common": {
|
||||
"accepted": "已接受",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "居中 模态",
|
||||
"change_organization": "切换组织",
|
||||
"change_workspace": "切换工作区",
|
||||
"choice_n": "选项 {{n}}",
|
||||
"choices": "选项",
|
||||
"choose_environment": "选择 环境",
|
||||
"choose_organization": "选择 组织",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "关闭",
|
||||
"code": "代码",
|
||||
"collapse_rows": "折叠 行",
|
||||
"column_n": "列 {{n}}",
|
||||
"completed": "完成",
|
||||
"configuration": "配置",
|
||||
"confirm": "确认",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "复制到剪贴板失败",
|
||||
"failed_to_load_organizations": "加载组织失败",
|
||||
"failed_to_load_workspaces": "加载工作区失败",
|
||||
"field_placeholder": "{{field}} 占位符",
|
||||
"filter": "筛选",
|
||||
"finish": "完成",
|
||||
"first_name": "名字",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "生成",
|
||||
"go_back": "返回 ",
|
||||
"go_to_dashboard": "转到 Dashboard",
|
||||
"headline": "标题",
|
||||
"hidden": "隐藏",
|
||||
"hidden_field": "隐藏 字段",
|
||||
"hidden_fields": "隐藏 字段",
|
||||
"hide_column": "隐藏 列",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "图片",
|
||||
"images": "图片",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "月",
|
||||
"move_down": "下移",
|
||||
"move_up": "上移",
|
||||
"multiple_languages": "多种 语言",
|
||||
"my_product": "我的产品",
|
||||
"name": "名称",
|
||||
"new": "新建",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "没有 结果",
|
||||
"no_results": "没有 结果",
|
||||
"no_surveys_found": "未找到 调查",
|
||||
"no_text_found": "未找到文本",
|
||||
"none_of_the_above": "以上 都 不 是",
|
||||
"not_authenticated": "您 未 认证 以 执行 该 操作。",
|
||||
"not_authorized": "未授权",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "组织 设置",
|
||||
"other": "其他",
|
||||
"other_filters": "其他筛选条件",
|
||||
"others": "其他",
|
||||
"other_placeholder": "其他占位符",
|
||||
"overlay_color": "覆盖层颜色",
|
||||
"overview": "概览",
|
||||
"password": "密码",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "请升级您的计划",
|
||||
"powered_by_formbricks": "由 Formbricks 提供支持",
|
||||
"preview": "预览",
|
||||
"preview_survey": "预览 Survey",
|
||||
"privacy": "隐私政策",
|
||||
"product_manager": "产品经理",
|
||||
"production": "生产环境",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "反馈",
|
||||
"restart": "重新启动",
|
||||
"role": "角色",
|
||||
"row_n": "行 {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "销售",
|
||||
"save": "保存",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "文件存储 未设置,上传 可能 失败",
|
||||
"string": "文本",
|
||||
"styling": "样式",
|
||||
"subheader": "副标题",
|
||||
"submit": "提交",
|
||||
"summary": "概要",
|
||||
"survey": "调查",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "例如:Formbricks",
|
||||
"workspaces": "工作区",
|
||||
"years": "年",
|
||||
"you": "你 ",
|
||||
"you_are_downgraded_to_the_community_edition": "您已降级到社区版。",
|
||||
"you_are_not_authorized_to_perform_this_action": "您无权执行此操作。",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "您已达到 {projectLimit} 个工作区的上限。",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "将 数据 发送到 您的 Notion 数据库",
|
||||
"please_select_a_survey_error": "请选择 一个 调查",
|
||||
"reconnect_button": "重新连接",
|
||||
"reconnect_button_description": "你的集成连接已过期。请重新连接以继续同步响应。你现有的链接和数据将被保留。",
|
||||
"reconnect_button_tooltip": "重新连接集成以刷新你的访问权限。你现有的链接和数据将被保留。",
|
||||
"select_at_least_one_question_error": "请选择至少 一个问题",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "您 已 经 将 另 一 个 调 查 连 接 到 此 频 道 。",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "一切准备就绪!是时候创建您的第一个调查了",
|
||||
"alphabetical": "字母顺序",
|
||||
"copy_survey": "复制 调查",
|
||||
"copy_survey_description": "复制 此 调查 到 另 一个 环境",
|
||||
"copy_survey_error": "复制 调查 失败",
|
||||
"copy_survey_link_to_clipboard": "复制 survey 链接 到 剪贴板",
|
||||
"copy_survey_partially_success": "{success} 个调查成功复制,{error} 个失败。",
|
||||
"copy_survey_success": "调查成功复制!",
|
||||
"delete_survey_and_responses_warning": "您 确定 要 删除 此 调查 及 所有 回复 吗?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. 选择 此 调查 的 默认 语言:",
|
||||
"2_activate_translation_for_specific_languages": "2. 激活 特定 语言 的 翻译:",
|
||||
"activate_translations": "激活翻译",
|
||||
"add": "添加 +",
|
||||
"add_a_delay_or_auto_close_the_survey": "添加 延迟 或 自动 关闭 调查",
|
||||
"add_a_four_digit_pin": "添加 一个 四 位 数 PIN",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "受众",
|
||||
"auto_close_on_inactivity": "自动关闭 在 无活动时",
|
||||
"auto_progress_rating_and_nps": "自动推进评分和 NPS 问题",
|
||||
"auto_progress_rating_and_nps_description": "当受访者在评分或 NPS 问题上选择答案时自动前进。这仅适用于单问题区块。必填问题会隐藏\"下一步\"按钮;可选问题仍会显示该按钮以便跳过。",
|
||||
"auto_progress_rating_and_nps_description": "在单问题块中自动前进。必填问题会隐藏\"下一步\"按钮,除非选择了\"其他\"选项。",
|
||||
"auto_save_disabled": "自动保存已禁用",
|
||||
"auto_save_disabled_tooltip": "您的调查仅在草稿状态时自动保存。这确保公开的调查不会被意外更新。",
|
||||
"auto_save_on": "自动保存已启用",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "更改 会导致 不一致",
|
||||
"change_anyway": "还是更改",
|
||||
"change_background": "更改 背景",
|
||||
"change_default": "更改默认语言",
|
||||
"change_question_type": "更改 问题类型",
|
||||
"change_survey_type": "更改 调查 类型 会影 响 现有 访问",
|
||||
"change_the_background_to_a_color_image_or_animation": "将 背景 更改为 颜色 、 图像 或 动画。",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "选择 调查 运行 的 位置 。",
|
||||
"city": "城市",
|
||||
"close_survey_on_response_limit": "在响应限制时关闭 调查",
|
||||
"code": "代码",
|
||||
"color": "颜色",
|
||||
"column_used_in_logic_error": "\"这个 列 在 问题 {questionIndex} 的 逻辑 中 使用。请 先 从 逻辑 中 删除 它。\"",
|
||||
"columns": "列",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "自定义调查 logo",
|
||||
"darken_or_lighten_background_of_your_choice": "根据 您 的 选择 暗化 或 亮化 背景。",
|
||||
"days_before_showing_this_survey_again": "距离上次显示问卷后需间隔不少于指定天数,才能再次显示此问卷。",
|
||||
"default_language": "默认语言",
|
||||
"delete_anyways": "仍然删除",
|
||||
"delete_block": "删除区块",
|
||||
"delete_choice": "删除 选择",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "复制问题",
|
||||
"edit_link": "编辑 链接",
|
||||
"edit_recall": "编辑 调用",
|
||||
"edit_translations": "编辑 {lang} 翻译",
|
||||
"element_not_found": "未找到问题",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "允许受访者在调查过程中随时切换语言。需要至少启用两种语言。",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "垃圾 邮件 保护 使用 reCAPTCHA v3 来 过滤 掉 垃圾 响应 。",
|
||||
@@ -1597,11 +1602,13 @@
|
||||
"long_answer": "长答案",
|
||||
"long_answer_toggle_description": "允许受访者填写较长的多行答案。",
|
||||
"lower_label": "下限标签",
|
||||
"manage_languages": "管理 语言",
|
||||
"manage_languages": "管理语言",
|
||||
"manage_translations": "管理翻译",
|
||||
"matrix_all_fields": "所有字段",
|
||||
"matrix_rows": "行",
|
||||
"max_file_size": "最大文件大小",
|
||||
"max_file_size_limit_is": "最大文件大小限制为",
|
||||
"missing_first": "缺失优先",
|
||||
"move_question_to_block": "将问题移动到区块",
|
||||
"multiply": "乘 *",
|
||||
"needed_for_self_hosted_cal_com_instance": "需要用于 自建 Cal.com 实例",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "\"下一步\" 按钮标签",
|
||||
"no_hidden_fields_yet_add_first_one_below": "还没有隐藏字段。 在下面添加第一个。",
|
||||
"no_images_found_for": "未找到与 \"{query}\" 相关的图片",
|
||||
"no_languages_found_add_first_one_to_get_started": "没有找到语言。添加第一个以开始。",
|
||||
"no_languages_found_add_first_one_to_get_started": "此工作区中未找到调查问卷语言。请添加一个以开始使用。",
|
||||
"no_option_found": "找不到选择",
|
||||
"no_recall_items_found": "未找到召回项",
|
||||
"no_variables_yet_add_first_one_below": "还没有变量。 在下面添加第一个。",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "请输入有效的 URL(例如, https://example.com )",
|
||||
"please_set_a_survey_trigger": "请 设置 一个 调查 触发",
|
||||
"please_specify": "请 指定",
|
||||
"present_your_survey_in_multiple_languages": "以多种语言展示您的调查问卷",
|
||||
"prevent_double_submission": "防止 重复 提交",
|
||||
"prevent_double_submission_description": "只允许每个 email 地址提供 1 个回复",
|
||||
"progress_saved": "进度已保存",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 分",
|
||||
"show_block_settings": "显示区块设置",
|
||||
"show_button": "显示 按钮",
|
||||
"show_in_order": "按顺序显示",
|
||||
"show_language_switch": "显示 语言 切换",
|
||||
"show_multiple_times": "显示有限次数",
|
||||
"show_only_once": "仅 显示 一次",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "问卷预览 👀",
|
||||
"survey_styling": "表单 样式",
|
||||
"survey_trigger": "调查 触发",
|
||||
"switch_multi_language_on_to_get_started": "开启多语言以开始使用 👉",
|
||||
"target_block_not_found": "未找到目标区块",
|
||||
"targeted": "定位",
|
||||
"ten_points": "10 分",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "仅显示一次,即使他们未回应。",
|
||||
"then": "然后",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "此操作将删除该调查中的所有翻译。",
|
||||
"this_will_remove_the_language_and_all_its_translations": "这将从此调查问卷中删除该语言及其所有翻译。此操作无法撤销。",
|
||||
"three_points": "3 分",
|
||||
"times": "次数",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "为了 保持 所有 调查 的 放置 一致,您 可以",
|
||||
"translated": "已翻译",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "当 其中 一个 动作 被 触发 时 启动 调查…",
|
||||
"try_lollipop_or_mountain": "尝试 'lollipop' 或 'mountain' ...",
|
||||
"type_field_id": "类型 字段 ID",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "仅允许 拥有 有效 电子邮件 的 人 回应。",
|
||||
"visibility_and_recontact": "可见性与重新联系",
|
||||
"visibility_and_recontact_description": "控制此调查何时可以显示以及可以重新显示的频率。",
|
||||
"visible": "可见",
|
||||
"wait": "等待",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "触发后等待几秒再显示问卷",
|
||||
"waiting_time_across_surveys": "冷却期(跨问卷)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "正在下载二维码",
|
||||
"drop_offs": "流失",
|
||||
"drop_offs_tooltip": "调查 被 开始 但 未 完成 的 次数",
|
||||
"failed_to_copy_link": "复制链接失败",
|
||||
"filter_added_successfully": "筛选器 添加成功",
|
||||
"filter_updated_successfully": "筛选器 更新 成功",
|
||||
"filtered_responses_csv": "过滤 反馈 (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "调查 删除 成功",
|
||||
"survey_duplicated_successfully": "调查成功复制。",
|
||||
"survey_duplication_error": "无法复制 调查。",
|
||||
"templates": {
|
||||
"all_channels": "所有 渠道",
|
||||
"all_industries": "所有 行业",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "语言或语言 ID 重复",
|
||||
"edit_languages": "编辑语言",
|
||||
"identifier": "标识符(ISO)",
|
||||
"incomplete_translations": "翻译不完整",
|
||||
"language": "语言",
|
||||
"language_deleted_successfully": "语言删除成功",
|
||||
"languages_updated_successfully": "语言更新成功",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "请选择一种语言",
|
||||
"remove_language": "移除语言",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "请先从这些调查中移除该语言,然后才能从工作区中删除。",
|
||||
"search_items": "搜索项目",
|
||||
"translate": "翻译"
|
||||
"search_items": "搜索项目"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "添加背景色",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "设置进度条未填充部分的颜色。",
|
||||
"advanced_styling_field_track_height": "轨道高度",
|
||||
"advanced_styling_field_track_height_description": "控制进度条的粗细。",
|
||||
"advanced_styling_field_upper_label_color": "标题标签颜色",
|
||||
"advanced_styling_field_upper_label_color_description": "设置输入框上方小标签的颜色。",
|
||||
"advanced_styling_field_upper_label_size": "标题标签字体大小",
|
||||
"advanced_styling_field_upper_label_size_description": "调整输入框上方小标签的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "标题标签字体粗细",
|
||||
"advanced_styling_field_upper_label_weight_description": "设置标签文字的粗细。",
|
||||
"advanced_styling_field_upper_label_color": "标签颜色",
|
||||
"advanced_styling_field_upper_label_color_description": "为输入框上方的小标签和刻度标签着色。",
|
||||
"advanced_styling_field_upper_label_size": "标签字体大小",
|
||||
"advanced_styling_field_upper_label_size_description": "调整输入框上方的小标签和刻度标签的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "标签字体粗细",
|
||||
"advanced_styling_field_upper_label_weight_description": "使标签更细或更粗。",
|
||||
"advanced_styling_section_buttons": "按钮",
|
||||
"advanced_styling_section_headlines": "标题和描述",
|
||||
"advanced_styling_section_inputs": "输入项",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "验证 您的 邮件 以 响应",
|
||||
"verify_email_before_submission_button": "验证",
|
||||
"verify_email_before_submission_description": "要 响应 此 调查,请 验证 您的 邮件",
|
||||
"want_to_respond": "想要 参与 吗?"
|
||||
"want_to_respond": "想要 参与 吗?",
|
||||
"paused_heading": "暂停",
|
||||
"completed_heading": "完成"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "我们 可以 改进 的 一 件事 是 什么?",
|
||||
"identify_customer_goals_description": "更好 地 了解 您 的 信息 是否 创造了 您 的 产品 所 提供 价值 的 正确 期望。",
|
||||
"identify_customer_goals_name": "识别 客户 目标",
|
||||
"identify_customer_goals_question_1_choice_1": "深入了解我的用户群体",
|
||||
"identify_customer_goals_question_1_choice_2": "识别追加销售机会",
|
||||
"identify_customer_goals_question_1_choice_3": "打造最优质的产品",
|
||||
"identify_customer_goals_question_1_choice_4": "统治世界,让每个人早餐都吃抱子甘蓝",
|
||||
"identify_customer_goals_question_1_headline": "您使用 $[projectName] 的主要目标是什么?",
|
||||
"identify_sign_up_barriers_description": "提供折扣以收集有关 注册障碍 的见解。",
|
||||
"identify_sign_up_barriers_name": "识别 注册 障碍",
|
||||
"identify_sign_up_barriers_question_1_button_label": "获取 10% 折扣",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "帮助 我们 更好 地 了解 你 :",
|
||||
"improve_trial_conversion_question_2_button_label": "下一步",
|
||||
"improve_trial_conversion_question_2_headline": "很抱歉 听到。使用 $[projectName] 时 最大的 问题 是 什么?",
|
||||
"improve_trial_conversion_question_3_button_label": "下一步",
|
||||
"improve_trial_conversion_question_3_headline": "您期望 $[projectName] 做什么?",
|
||||
"improve_trial_conversion_question_4_button_label": "获取 20% 折扣",
|
||||
"improve_trial_conversion_question_4_headline": "很抱歉 听到!首年 可 获 20% 优惠。",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>我们 很 乐意 为 您 提供 年 度 计划 20% 的 折扣。</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "下一步",
|
||||
"improve_trial_conversion_question_5_headline": "你 想 实现 什么?",
|
||||
"improve_trial_conversion_question_5_subheader": "请选择以下选项之一:",
|
||||
"improve_trial_conversion_question_5_subheader": "请在下方描述:",
|
||||
"improve_trial_conversion_question_6_headline": "你 现在 如何 解决 你的 问题?",
|
||||
"improve_trial_conversion_question_6_subheader": "请 列举 替代 方案:",
|
||||
"integration_setup_survey_description": "评估用户 添加 集成 到 产品 的 便捷程度 。 找到 盲点 。",
|
||||
|
||||
@@ -111,7 +111,8 @@
|
||||
},
|
||||
"c": {
|
||||
"link_expired": "您 的 連結 已過期。",
|
||||
"link_expired_description": "您 使用 的 連結 已無效。"
|
||||
"link_expired_description": "您 使用 的 連結 已無效。",
|
||||
"link_expired_heading": "您 的 連結 已過期。"
|
||||
},
|
||||
"common": {
|
||||
"accepted": "已接受",
|
||||
@@ -152,6 +153,7 @@
|
||||
"centered_modal": "置中彈窗",
|
||||
"change_organization": "變更組織",
|
||||
"change_workspace": "變更工作區",
|
||||
"choice_n": "選項 {{n}}",
|
||||
"choices": "選項",
|
||||
"choose_environment": "選擇環境",
|
||||
"choose_organization": "選擇 組織",
|
||||
@@ -165,6 +167,7 @@
|
||||
"close": "關閉",
|
||||
"code": "程式碼",
|
||||
"collapse_rows": "摺疊列",
|
||||
"column_n": "欄 {{n}}",
|
||||
"completed": "已完成",
|
||||
"configuration": "組態",
|
||||
"confirm": "確認",
|
||||
@@ -236,6 +239,7 @@
|
||||
"failed_to_copy_to_clipboard": "無法複製到剪貼簿",
|
||||
"failed_to_load_organizations": "無法載入組織",
|
||||
"failed_to_load_workspaces": "載入工作區失敗",
|
||||
"field_placeholder": "{{field}} 預設文字",
|
||||
"filter": "篩選",
|
||||
"finish": "完成",
|
||||
"first_name": "名字",
|
||||
@@ -247,10 +251,12 @@
|
||||
"generate": "產生",
|
||||
"go_back": "返回",
|
||||
"go_to_dashboard": "前往儀表板",
|
||||
"headline": "標題",
|
||||
"hidden": "隱藏",
|
||||
"hidden_field": "隱藏欄位",
|
||||
"hidden_fields": "隱藏欄位",
|
||||
"hide_column": "隱藏欄位",
|
||||
"html": "HTML",
|
||||
"id": "ID",
|
||||
"image": "圖片",
|
||||
"images": "圖片",
|
||||
@@ -298,7 +304,6 @@
|
||||
"months": "月",
|
||||
"move_down": "下移",
|
||||
"move_up": "上移",
|
||||
"multiple_languages": "多種語言",
|
||||
"my_product": "我的產品",
|
||||
"name": "名稱",
|
||||
"new": "新增",
|
||||
@@ -313,6 +318,7 @@
|
||||
"no_result_found": "找不到結果",
|
||||
"no_results": "沒有結果",
|
||||
"no_surveys_found": "找不到問卷。",
|
||||
"no_text_found": "找不到文字",
|
||||
"none_of_the_above": "以上皆非",
|
||||
"not_authenticated": "您未經授權執行此操作。",
|
||||
"not_authorized": "未授權",
|
||||
@@ -336,7 +342,7 @@
|
||||
"organization_settings": "組織設定",
|
||||
"other": "其他",
|
||||
"other_filters": "其他篩選條件",
|
||||
"others": "其他",
|
||||
"other_placeholder": "其他預設文字",
|
||||
"overlay_color": "覆蓋層顏色",
|
||||
"overview": "概覽",
|
||||
"password": "密碼",
|
||||
@@ -354,7 +360,6 @@
|
||||
"please_upgrade_your_plan": "請升級您的方案",
|
||||
"powered_by_formbricks": "由 Formbricks 提供技術支援",
|
||||
"preview": "預覽",
|
||||
"preview_survey": "預覽問卷",
|
||||
"privacy": "隱私權政策",
|
||||
"product_manager": "產品經理",
|
||||
"production": "正式環境",
|
||||
@@ -381,6 +386,7 @@
|
||||
"responses": "回應",
|
||||
"restart": "重新開始",
|
||||
"role": "角色",
|
||||
"row_n": "列 {{n}}",
|
||||
"saas": "SaaS",
|
||||
"sales": "銷售",
|
||||
"save": "儲存",
|
||||
@@ -419,6 +425,7 @@
|
||||
"storage_not_configured": "檔案儲存未設定,上傳可能會失敗",
|
||||
"string": "文字",
|
||||
"styling": "樣式設定",
|
||||
"subheader": "副標題",
|
||||
"submit": "提交",
|
||||
"summary": "摘要",
|
||||
"survey": "問卷",
|
||||
@@ -487,7 +494,6 @@
|
||||
"workspace_name_placeholder": "例如:Formbricks",
|
||||
"workspaces": "工作區",
|
||||
"years": "年",
|
||||
"you": "您",
|
||||
"you_are_downgraded_to_the_community_edition": "您已降級至社群版。",
|
||||
"you_are_not_authorized_to_perform_this_action": "您沒有執行此操作的權限。",
|
||||
"you_have_reached_your_limit_of_workspace_limit": "您已達到 {projectLimit} 個工作區的上限。",
|
||||
@@ -828,6 +834,9 @@
|
||||
},
|
||||
"notion_integration_description": "將資料傳送至您的 Notion 資料庫",
|
||||
"please_select_a_survey_error": "請選取問卷",
|
||||
"reconnect_button": "重新連接",
|
||||
"reconnect_button_description": "您的整合連線已過期。請重新連接以繼續同步回應。您現有的連結和資料將會保留。",
|
||||
"reconnect_button_tooltip": "重新連接整合以更新您的存取權限。您現有的連結和資料將會保留。",
|
||||
"select_at_least_one_question_error": "請選取至少一個問題",
|
||||
"slack": {
|
||||
"already_connected_another_survey": "您已將另一個問卷連線到此頻道。",
|
||||
@@ -1301,16 +1310,10 @@
|
||||
"surveys": {
|
||||
"all_set_time_to_create_first_survey": "您已準備就緒!是時候建立您的第一個問卷",
|
||||
"alphabetical": "依字母順序",
|
||||
"copy_survey": "複製問卷",
|
||||
"copy_survey_description": "將此問卷複製到另一個環境",
|
||||
"copy_survey_error": "無法複製問卷",
|
||||
"copy_survey_link_to_clipboard": "將問卷連結複製到剪貼簿",
|
||||
"copy_survey_partially_success": "{success} 個問卷已成功複製,{error} 個失敗。",
|
||||
"copy_survey_success": "問卷已成功複製!",
|
||||
"delete_survey_and_responses_warning": "您確定要刪除此問卷及其所有回應嗎?",
|
||||
"edit": {
|
||||
"1_choose_the_default_language_for_this_survey": "1. 選擇此問卷的預設語言:",
|
||||
"2_activate_translation_for_specific_languages": "2. 啟用特定語言的翻譯:",
|
||||
"activate_translations": "啟用翻譯",
|
||||
"add": "新增 +",
|
||||
"add_a_delay_or_auto_close_the_survey": "新增延遲或自動關閉問卷",
|
||||
"add_a_four_digit_pin": "新增四位數 PIN 碼",
|
||||
@@ -1360,7 +1363,7 @@
|
||||
"audience": "受眾",
|
||||
"auto_close_on_inactivity": "非活動時自動關閉",
|
||||
"auto_progress_rating_and_nps": "自動前進評分與 NPS 問題",
|
||||
"auto_progress_rating_and_nps_description": "當受訪者在評分或 NPS 問題中選擇答案時自動前進。此設定僅適用於單一問題區塊。必填問題會隱藏「下一步」按鈕;選填問題仍會顯示該按鈕以便跳過。",
|
||||
"auto_progress_rating_and_nps_description": "在單一問題區塊中自動前進。必填問題會隱藏「下一步」按鈕,除非選擇了「其他」選項。",
|
||||
"auto_save_disabled": "自動儲存已停用",
|
||||
"auto_save_disabled_tooltip": "您的問卷僅在草稿狀態時自動儲存。這確保公開的問卷不會被意外更新。",
|
||||
"auto_save_on": "自動儲存已啟用",
|
||||
@@ -1406,6 +1409,7 @@
|
||||
"caution_text": "變更會導致不一致",
|
||||
"change_anyway": "仍然變更",
|
||||
"change_background": "變更背景",
|
||||
"change_default": "變更預設",
|
||||
"change_question_type": "變更問題類型",
|
||||
"change_survey_type": "切換問卷類型會影響現有訪問",
|
||||
"change_the_background_to_a_color_image_or_animation": "將背景變更為顏色、圖片或動畫。",
|
||||
@@ -1418,6 +1422,7 @@
|
||||
"choose_where_to_run_the_survey": "選擇在哪裡執行問卷。",
|
||||
"city": "城市",
|
||||
"close_survey_on_response_limit": "在回應次數上限關閉問卷",
|
||||
"code": "代碼",
|
||||
"color": "顏色",
|
||||
"column_used_in_logic_error": "此 column 用於問題 '{'questionIndex'}' 的邏輯中。請先從邏輯中移除。",
|
||||
"columns": "欄位",
|
||||
@@ -1442,6 +1447,7 @@
|
||||
"customize_survey_logo": "自訂問卷標誌",
|
||||
"darken_or_lighten_background_of_your_choice": "變暗或變亮您選擇的背景。",
|
||||
"days_before_showing_this_survey_again": "距離上次顯示問卷後,需間隔指定天數才能再次顯示此問卷。",
|
||||
"default_language": "預設語言",
|
||||
"delete_anyways": "仍要刪除",
|
||||
"delete_block": "刪除區塊",
|
||||
"delete_choice": "刪除選項",
|
||||
@@ -1461,7 +1467,6 @@
|
||||
"duplicate_question": "複製問題",
|
||||
"edit_link": "編輯 連結",
|
||||
"edit_recall": "編輯回憶",
|
||||
"edit_translations": "編輯 '{'language'}' 翻譯",
|
||||
"element_not_found": "找不到問題",
|
||||
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "允許受訪者隨時切換語言。需要至少啟用兩種語言。",
|
||||
"enable_recaptcha_to_protect_your_survey_from_spam": "垃圾郵件保護使用 reCAPTCHA v3 過濾垃圾回應。",
|
||||
@@ -1598,10 +1603,12 @@
|
||||
"long_answer_toggle_description": "允許受訪者撰寫較長的多行回答。",
|
||||
"lower_label": "下標籤",
|
||||
"manage_languages": "管理語言",
|
||||
"manage_translations": "管理翻譯",
|
||||
"matrix_all_fields": "所有欄位",
|
||||
"matrix_rows": "列",
|
||||
"max_file_size": "最大檔案大小",
|
||||
"max_file_size_limit_is": "最大檔案大小限制為",
|
||||
"missing_first": "缺少的優先",
|
||||
"move_question_to_block": "將問題移至區塊",
|
||||
"multiply": "乘 *",
|
||||
"needed_for_self_hosted_cal_com_instance": "自行託管 Cal.com 執行個體時需要",
|
||||
@@ -1609,7 +1616,7 @@
|
||||
"next_button_label": "「下一步」按鈕標籤",
|
||||
"no_hidden_fields_yet_add_first_one_below": "尚無隱藏欄位。在下方新增第一個隱藏欄位。",
|
||||
"no_images_found_for": "找不到「'{'query'}'」的圖片",
|
||||
"no_languages_found_add_first_one_to_get_started": "找不到語言。新增第一個語言以開始使用。",
|
||||
"no_languages_found_add_first_one_to_get_started": "此工作區中找不到問卷語言。請新增一個語言以開始使用。",
|
||||
"no_option_found": "找不到選項",
|
||||
"no_recall_items_found": "未找到回溯項目",
|
||||
"no_variables_yet_add_first_one_below": "尚無變數。在下方新增第一個變數。",
|
||||
@@ -1636,6 +1643,7 @@
|
||||
"please_enter_a_valid_url": "請輸入有效的 URL(例如:https://example.com)",
|
||||
"please_set_a_survey_trigger": "請設定問卷觸發器",
|
||||
"please_specify": "請指定",
|
||||
"present_your_survey_in_multiple_languages": "以多種語言呈現你的問卷",
|
||||
"prevent_double_submission": "防止重複提交",
|
||||
"prevent_double_submission_description": "每個電子郵件地址僅允許 1 個回應",
|
||||
"progress_saved": "進度已儲存",
|
||||
@@ -1727,6 +1735,7 @@
|
||||
"seven_points": "7 分",
|
||||
"show_block_settings": "顯示區塊設定",
|
||||
"show_button": "顯示按鈕",
|
||||
"show_in_order": "依序顯示",
|
||||
"show_language_switch": "顯示語言切換",
|
||||
"show_multiple_times": "顯示有限次數",
|
||||
"show_only_once": "僅顯示一次",
|
||||
@@ -1758,7 +1767,6 @@
|
||||
"survey_preview": "問卷預覽 👀",
|
||||
"survey_styling": "表單樣式設定",
|
||||
"survey_trigger": "問卷觸發器",
|
||||
"switch_multi_language_on_to_get_started": "請開啟多語言功能以開始使用 👉",
|
||||
"target_block_not_found": "找不到目標區塊",
|
||||
"targeted": "目標",
|
||||
"ten_points": "10 分",
|
||||
@@ -1766,9 +1774,11 @@
|
||||
"the_survey_will_be_shown_once_even_if_person_doesnt_respond": "僅顯示一次,即使他們未回應。",
|
||||
"then": "然後",
|
||||
"this_action_will_remove_all_the_translations_from_this_survey": "此操作將從此問卷中移除所有翻譯。",
|
||||
"this_will_remove_the_language_and_all_its_translations": "這將會從此問卷中移除該語言及其所有翻譯。此操作無法復原。",
|
||||
"three_points": "3 分",
|
||||
"times": "次",
|
||||
"to_keep_the_placement_over_all_surveys_consistent_you_can": "若要保持所有問卷的位置一致,您可以",
|
||||
"translated": "已翻譯",
|
||||
"trigger_survey_when_one_of_the_actions_is_fired": "當觸發其中一個操作時,觸發問卷...",
|
||||
"try_lollipop_or_mountain": "嘗試「棒棒糖」或「山峰」...",
|
||||
"type_field_id": "輸入欄位 ID",
|
||||
@@ -1843,6 +1853,7 @@
|
||||
"verify_email_before_submission_description": "僅允許擁有真實電子郵件的人員回應。",
|
||||
"visibility_and_recontact": "可見性與重新聯絡",
|
||||
"visibility_and_recontact_description": "控制此問卷何時可以顯示以及可以重新顯示的頻率。",
|
||||
"visible": "可見",
|
||||
"wait": "等待",
|
||||
"wait_a_few_seconds_after_the_trigger_before_showing_the_survey": "在觸發後等待幾秒鐘再顯示問卷",
|
||||
"waiting_time_across_surveys": "冷卻期(跨問卷)",
|
||||
@@ -2051,7 +2062,6 @@
|
||||
"downloading_qr_code": "正在下載 QR code",
|
||||
"drop_offs": "放棄",
|
||||
"drop_offs_tooltip": "問卷已開始但未完成的次數。",
|
||||
"failed_to_copy_link": "無法複製連結",
|
||||
"filter_added_successfully": "篩選器已成功新增",
|
||||
"filter_updated_successfully": "篩選器已成功更新",
|
||||
"filtered_responses_csv": "篩選回應 (CSV)",
|
||||
@@ -2139,7 +2149,6 @@
|
||||
},
|
||||
"survey_deleted_successfully": "問卷已成功刪除!",
|
||||
"survey_duplicated_successfully": "問卷已成功複製。",
|
||||
"survey_duplication_error": "無法複製問卷。",
|
||||
"templates": {
|
||||
"all_channels": "所有管道",
|
||||
"all_industries": "所有產業",
|
||||
@@ -2227,7 +2236,6 @@
|
||||
"duplicate_language_or_language_id": "語言或語言 ID 重複",
|
||||
"edit_languages": "編輯語言",
|
||||
"identifier": "識別碼(ISO)",
|
||||
"incomplete_translations": "翻譯不完整",
|
||||
"language": "語言",
|
||||
"language_deleted_successfully": "語言已成功刪除",
|
||||
"languages_updated_successfully": "語言已成功更新",
|
||||
@@ -2237,8 +2245,7 @@
|
||||
"please_select_a_language": "請選擇一種語言",
|
||||
"remove_language": "移除語言",
|
||||
"remove_language_from_surveys_to_remove_it_from_workspace": "請先從這些問卷中移除此語言,才能從工作區移除。",
|
||||
"search_items": "搜尋項目",
|
||||
"translate": "翻譯"
|
||||
"search_items": "搜尋項目"
|
||||
},
|
||||
"look": {
|
||||
"add_background_color": "新增背景顏色",
|
||||
@@ -2298,12 +2305,12 @@
|
||||
"advanced_styling_field_track_bg_description": "設定進度條未填滿部分的顏色。",
|
||||
"advanced_styling_field_track_height": "軌道高度",
|
||||
"advanced_styling_field_track_height_description": "調整進度條的厚度。",
|
||||
"advanced_styling_field_upper_label_color": "標題標籤顏色",
|
||||
"advanced_styling_field_upper_label_color_description": "設定輸入框上方小標籤的顏色。",
|
||||
"advanced_styling_field_upper_label_size": "標題標籤字體大小",
|
||||
"advanced_styling_field_upper_label_size_description": "調整輸入框上方小標籤的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "標題標籤字體粗細",
|
||||
"advanced_styling_field_upper_label_weight_description": "讓標籤字體變細或變粗。",
|
||||
"advanced_styling_field_upper_label_color": "標籤顏色",
|
||||
"advanced_styling_field_upper_label_color_description": "為輸入欄位上方的小標籤和刻度標籤設定顏色。",
|
||||
"advanced_styling_field_upper_label_size": "標籤字體大小",
|
||||
"advanced_styling_field_upper_label_size_description": "調整輸入欄位上方的小標籤和刻度標籤的字體大小。",
|
||||
"advanced_styling_field_upper_label_weight": "標籤字體粗細",
|
||||
"advanced_styling_field_upper_label_weight_description": "讓標籤變得更細或更粗。",
|
||||
"advanced_styling_section_buttons": "按鈕",
|
||||
"advanced_styling_section_headlines": "標題與說明",
|
||||
"advanced_styling_section_inputs": "輸入欄位",
|
||||
@@ -2439,7 +2446,9 @@
|
||||
"verify_email_before_submission": "驗證您的電子郵件以回應",
|
||||
"verify_email_before_submission_button": "驗證",
|
||||
"verify_email_before_submission_description": "若要回應此問卷,請驗證您的電子郵件",
|
||||
"want_to_respond": "想要回應嗎?"
|
||||
"want_to_respond": "想要回應嗎?",
|
||||
"paused_heading": "已暫停",
|
||||
"completed_heading": "已完成"
|
||||
},
|
||||
"setup": {
|
||||
"intro": {
|
||||
@@ -2874,6 +2883,11 @@
|
||||
"gauge_feature_satisfaction_question_2_headline": "我們可以做哪一件事來改進?",
|
||||
"identify_customer_goals_description": "更瞭解您的訊息傳遞是否符合您的產品所提供價值的正確期望。",
|
||||
"identify_customer_goals_name": "識別客戶目標",
|
||||
"identify_customer_goals_question_1_choice_1": "深入了解我的使用者群",
|
||||
"identify_customer_goals_question_1_choice_2": "找出向上銷售的機會",
|
||||
"identify_customer_goals_question_1_choice_3": "打造最優秀的產品",
|
||||
"identify_customer_goals_question_1_choice_4": "統治世界,讓每個人都吃早餐球芽甘藍",
|
||||
"identify_customer_goals_question_1_headline": "您使用 $[projectName] 的主要目標是什麼?",
|
||||
"identify_sign_up_barriers_description": "提供折扣以收集有關註冊障礙的洞察。",
|
||||
"identify_sign_up_barriers_name": "識別註冊障礙",
|
||||
"identify_sign_up_barriers_question_1_button_label": "獲得 10% 折扣",
|
||||
@@ -2948,12 +2962,14 @@
|
||||
"improve_trial_conversion_question_1_subheader": "協助我們更瞭解您:",
|
||||
"improve_trial_conversion_question_2_button_label": "下一步",
|
||||
"improve_trial_conversion_question_2_headline": "很抱歉聽到。使用 {projectName} 時,最大的問題是什麼?",
|
||||
"improve_trial_conversion_question_3_button_label": "下一步",
|
||||
"improve_trial_conversion_question_3_headline": "您期望 $[projectName] 做什麼?",
|
||||
"improve_trial_conversion_question_4_button_label": "獲得 20% 折扣",
|
||||
"improve_trial_conversion_question_4_headline": "很抱歉聽到!在第一年獲得 20% 的折扣。",
|
||||
"improve_trial_conversion_question_4_html": "<p class=\"fb-editor-paragraph\" dir=\"ltr\"><span>我們很樂意為您提供年度方案的 20% 折扣。</span></p>",
|
||||
"improve_trial_conversion_question_5_button_label": "下一步",
|
||||
"improve_trial_conversion_question_5_headline": "您想要達成什麼?",
|
||||
"improve_trial_conversion_question_5_subheader": "請選取以下其中一個選項:",
|
||||
"improve_trial_conversion_question_5_subheader": "請在下方說明:",
|
||||
"improve_trial_conversion_question_6_headline": "您現在如何解決您的問題?",
|
||||
"improve_trial_conversion_question_6_subheader": "請列出替代解決方案:",
|
||||
"integration_setup_survey_description": "評估使用者將整合新增至您的產品的容易程度。找出盲點。",
|
||||
|
||||
+4
-3
@@ -6,7 +6,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { getLanguageLabel } from "@formbricks/i18n-utils/src/utils";
|
||||
import { TResponse } from "@formbricks/types/responses";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/modules/ui/components/tooltip";
|
||||
|
||||
interface InfoIconButtonProps {
|
||||
@@ -26,9 +25,11 @@ const InfoIconButton = ({
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline" size="icon" aria-label={ariaLabel}>
|
||||
<button
|
||||
className="flex h-4 w-4 items-center justify-center rounded text-slate-500 hover:text-slate-700"
|
||||
aria-label={ariaLabel}>
|
||||
<Icon className="h-4 w-4" />
|
||||
</Button>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent avoidCollisions align="start" side="bottom" className={maxWidth}>
|
||||
{tooltipContent}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { V3ApiError, getV3ApiErrorMessage, parseV3ApiError } from "@/modules/api/lib/v3-client";
|
||||
|
||||
describe("parseV3ApiError", () => {
|
||||
test("parses RFC 9457 error responses into a typed V3ApiError", async () => {
|
||||
const response = new Response(
|
||||
JSON.stringify({
|
||||
title: "Forbidden",
|
||||
status: 403,
|
||||
detail: "You are not authorized to access this resource",
|
||||
code: "forbidden",
|
||||
requestId: "req_1",
|
||||
invalid_params: [{ name: "surveyId", reason: "Invalid id" }],
|
||||
}),
|
||||
{
|
||||
status: 403,
|
||||
headers: {
|
||||
"Content-Type": "application/problem+json",
|
||||
"X-Request-Id": "req_1",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const error = await parseV3ApiError(response);
|
||||
|
||||
expect(error).toBeInstanceOf(V3ApiError);
|
||||
expect(error.status).toBe(403);
|
||||
expect(error.detail).toBe("You are not authorized to access this resource");
|
||||
expect(error.code).toBe("forbidden");
|
||||
expect(error.requestId).toBe("req_1");
|
||||
expect(error.invalid_params).toEqual([{ name: "surveyId", reason: "Invalid id" }]);
|
||||
});
|
||||
|
||||
test("falls back to a provided fallback message", () => {
|
||||
expect(getV3ApiErrorMessage(new Error("boom"), "fallback")).toBe("boom");
|
||||
expect(getV3ApiErrorMessage("bad", "fallback")).toBe("fallback");
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user