Browse Source

feat: implement multilingual support infrastructure and introduce profile interaction components

front-test-2
ghorbani 2 weeks ago
parent
commit
2cbb6a3055
  1. 3892
      package-lock.json
  2. 10
      package.json
  3. 9
      proxy.ts
  4. 23
      src/app/globals.css
  5. 88
      src/app/request-accepted/page.tsx
  6. 90
      src/components/Componentes/female-outcome-sheet.test.tsx
  7. 6
      src/components/Componentes/female-outcome-sheet.tsx
  8. 186
      src/components/Componentes/swipe-button.tsx
  9. 2
      src/lib/get-submit-path.ts
  10. 28
      src/lib/view-paddings.ts
  11. 11
      src/test/setup.ts
  12. 40
      src/translations/dictionaries.ts
  13. 11
      src/translations/locales/ar.json
  14. 11
      src/translations/locales/az.json
  15. 11
      src/translations/locales/bn.json
  16. 11
      src/translations/locales/da.json
  17. 11
      src/translations/locales/de.json
  18. 5
      src/translations/locales/en.json
  19. 11
      src/translations/locales/es.json
  20. 7
      src/translations/locales/fa.json
  21. 11
      src/translations/locales/fr.json
  22. 11
      src/translations/locales/gu.json
  23. 11
      src/translations/locales/ha.json
  24. 12
      src/translations/locales/he.json
  25. 11
      src/translations/locales/hi.json
  26. 12
      src/translations/locales/id.json
  27. 12
      src/translations/locales/ks.json
  28. 12
      src/translations/locales/pt.json
  29. 18
      src/translations/locales/ru.json
  30. 12
      src/translations/locales/sw.json
  31. 12
      src/translations/locales/tg.json
  32. 12
      src/translations/locales/tr.json
  33. 12
      src/translations/locales/ul.json
  34. 12
      src/translations/locales/ur.json
  35. 12
      src/translations/locales/uz.json
  36. 11
      src/translations/locales/zh.json
  37. 14
      vitest.config.ts

3892
package-lock.json
File diff suppressed because it is too large
View File

10
package.json

@ -7,7 +7,8 @@
"build": "next build",
"start": "next start",
"lint": "biome check",
"format": "biome format --write"
"format": "biome format --write",
"test": "vitest run"
},
"dependencies": {
"@tanstack/react-query": "^5.100.5",
@ -24,12 +25,17 @@
"@babel/preset-typescript": "^8.0.1",
"@biomejs/biome": "2.2.0",
"@tailwindcss/postcss": "^4",
"@testing-library/jest-dom": "^7.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.3",
"@types/google-libphonenumber": "^7.4.30",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"jsdom": "^29.1.1",
"tailwindcss": "^4",
"typescript": "^5"
"typescript": "^5",
"vitest": "^4.1.10"
},
"overrides": {
"postcss": "^8.5.10"

9
proxy.ts

@ -2,10 +2,15 @@ import { type NextRequest, NextResponse } from "next/server";
import { defaultLocale, isLocale } from "@/translations/config";
function getPreferredLocale(request: NextRequest) {
const cookieLocale =
request.cookies.get("HABIB_LANGUAGE")?.value ??
request.cookies.get("habib_language")?.value;
const acceptLanguage = request.headers.get("accept-language") ?? "";
const acceptedLocale = acceptLanguage.split(",")[0]?.split("-")[0];
if (acceptLanguage.toLowerCase().includes("fa")) {
return "fa";
for (const locale of [cookieLocale, acceptedLocale]) {
const normalizedLocale = locale?.trim().toLowerCase();
if (isLocale(normalizedLocale)) return normalizedLocale;
}
return defaultLocale;

23
src/app/globals.css

@ -288,28 +288,31 @@ body[data-page-background="custom"] .app-shell {
/* ─── Premium Shimmer Animations ─── */
@keyframes shimmer {
0% {
background-position: -200% 0;
background-position: 200% 0;
}
100% {
background-position: 200% 0;
background-position: -200% 0;
}
}
.shimmer-bg {
background: linear-gradient(
background-color: rgba(0, 0, 0, 0.05);
background-image: linear-gradient(
90deg,
rgba(0, 0, 0, 0.05) 25%,
rgba(0, 0, 0, 0.1) 37%,
rgba(0, 0, 0, 0.05) 63%
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.4) 50%,
rgba(255, 255, 255, 0) 100%
);
background-size: 200% 100%;
background-repeat: no-repeat;
animation: shimmer 1.5s infinite linear;
}
.dark .shimmer-bg {
background: linear-gradient(
background-color: rgba(255, 255, 255, 0.04);
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0.04) 25%,
rgba(255, 255, 255, 0.09) 37%,
rgba(255, 255, 255, 0.04) 63%
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.06) 50%,
rgba(255, 255, 255, 0) 100%
);
background-size: 200% 100%;
}

88
src/app/request-accepted/page.tsx

@ -179,12 +179,13 @@ export default function RequestAcceptedPage() {
const [isContactInfoSheetOpen, setIsContactInfoSheetOpen] = useState(false);
const [isSubscriptionSheetOpen, setIsSubscriptionSheetOpen] = useState(false);
const [isOutcomeSheetOpen, setIsOutcomeSheetOpen] = useState(false);
const [isTimeElapsed, setIsTimeElapsed] = useState(false);
const [isNoContactConfirmOpen, setIsNoContactConfirmOpen] = useState(false);
const [isContactReceivedConfirmOpen, setIsContactReceivedConfirmOpen] =
useState(false);
const [noContactReportedSuccess, setNoContactReportedSuccess] =
useState(false);
const [hasConfirmedFemaleContact, setHasConfirmedFemaleContact] =
useState(false);
const profileHref = localizePath("/new-match/profile", locale);
const { data: profile, isLoading } = useMarriageProfileQuery({
refetchInterval: 3000,
@ -203,32 +204,7 @@ export default function RequestAcceptedPage() {
}
}, [profile, router, locale, noContactReportedSuccess]);
useEffect(() => {
if (!isFemaleProfile || !contactSharedAtStr) {
setIsTimeElapsed(true);
return;
}
const checkTime = () => {
const contactSharedTime = new Date(contactSharedAtStr).getTime();
const elapsed = Date.now() - contactSharedTime;
const isPast = elapsed >= 2 * 60 * 1000;
setIsTimeElapsed(isPast);
return isPast;
};
const isPast = checkTime();
if (isPast) return;
const timer = setInterval(() => {
const isPastNow = checkTime();
if (isPastNow) {
clearInterval(timer);
}
}, 1000);
return () => clearInterval(timer);
}, [isFemaleProfile, contactSharedAtStr]);
const isRedirecting = useMemo(() => {
if (!profile) return false;
@ -237,6 +213,9 @@ export default function RequestAcceptedPage() {
const caseId = profile?.active_case?.case_id;
const caseStatus = profile?.active_case?.status;
const isFemaleContactConfirmed =
isFemaleProfile &&
(caseStatus === "contacted" || hasConfirmedFemaleContact);
const recommendedPlanId = profile?.recommended_plan?.id;
const paymentMutation = useHabcoinPaymentMutation();
const outcomeMutation = useSubmitMarriageOutcomeMutation(caseId ?? "");
@ -371,15 +350,26 @@ export default function RequestAcceptedPage() {
buttons={
<SwipeButton
theme="green"
text={t["Swipe to confirm"]}
text={t["Confirm"]}
onCancel={() => setIsContactReceivedConfirmOpen(false)}
onSuccess={async () => {
setIsContactReceivedConfirmOpen(false);
if (caseId) {
setHasConfirmedFemaleContact(true);
if (!caseId) {
return;
}
try {
await contactStatusMutation.mutateAsync({
action: "contacted",
custom_note:
"Contact received confirmed by female candidate",
});
} catch (error) {
// The confirmation screen must advance immediately after a swipe.
// Keep the local state visible while the profile query retries.
console.error("Unable to persist received contact", error);
}
}}
/>
@ -507,7 +497,7 @@ export default function RequestAcceptedPage() {
<PageHeader className="-mx-[6px]" />
<div className="flex flex-1 flex-col justify-between gap-6 pt-4">
<section className="flex flex-col items-center">
<section className="flex flex-col items-center">
{isFinalized ? (
<div className="flex flex-col items-center max-w-[320px] text-center my-auto py-12">
<div className="relative flex items-center justify-center text-[70px] animate-bounce">
@ -542,6 +532,7 @@ export default function RequestAcceptedPage() {
</h1>
{caseStatus === "contacted" ||
isFemaleContactConfirmed ||
(isFemaleProfile && contactStatusMutation.isPending) ? (
<div className="w-full border border-[#ECECEC] bg-white rounded-[15px] mt-6 px-4 py-4 text-center shadow-sm max-w-[315px] flex flex-col items-center justify-center min-h-[100px]">
{isFemaleProfile && contactStatusMutation.isPending ? (
@ -560,29 +551,23 @@ export default function RequestAcceptedPage() {
</div>
) : (
<p className="mt-4 max-w-[315px] group-12 leading-[1.45] font-semibold text-[#777777]">
{isFemaleProfile
{noContactReportedSuccess
? t[
"The selected candidate will contact your family shortly."
"Thank you for your feedback. Our support team will investigate the matter and notify you of the result. Please wait patiently during the review; our support will contact you."
]
: t[
"You can now view their family's contact details and arrange further steps."
]}
: isFemaleProfile
? t[
"The selected candidate will contact your family shortly."
]
: t[
"You can now view their family's contact details and arrange further steps."
]}
</p>
)}
{noContactReportedSuccess ? (
<div className="w-full border border-[#ECECEC] bg-white rounded-[15px] mt-6 px-4 py-4 text-center shadow-sm max-w-[315px]">
<p className="text-[#555555] group-14 font-medium leading-relaxed">
{
t[
"Thank you for your feedback. Our support team will investigate the matter and notify you of the result. Please wait patiently during the review; our support will contact you."
]
}
</p>
</div>
) : (
<>
<>
{caseStatus === "contacted" ||
isFemaleContactConfirmed ||
(isFemaleProfile && contactStatusMutation.isPending) ? (
<div className="flex mt-8 w-full gap-3 justify-center">
{isFemaleProfile &&
@ -635,7 +620,7 @@ export default function RequestAcceptedPage() {
type="button"
onClick={() => setIsNoContactConfirmOpen(true)}
disabled={
contactStatusMutation.isPending || !isTimeElapsed
contactStatusMutation.isPending || noContactReportedSuccess
}
className="flex-1 h-[44px] rounded-[15px] border border-[#BFBFBF] bg-white text-[#36363C] font-semibold group-14 flex items-center justify-center transition-all cursor-pointer hover:bg-[#F5F5F5] disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-white"
>
@ -661,11 +646,7 @@ export default function RequestAcceptedPage() {
onClick={() => {
void handleSecondaryAction();
}}
disabled={
isFemaleProfile
? paymentMutation.isPending || !isTimeElapsed
: paymentMutation.isPending
}
disabled={paymentMutation.isPending}
className={
isFemaleProfile
? "flex-1 h-[44px] rounded-[15px] bg-gradient-to-r from-[#FE6F82] to-[#E03950] text-white font-semibold group-14 flex items-center justify-center shadow-md shadow-[#FE6F82]/30 transition-all cursor-pointer hover:opacity-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:shadow-none"
@ -692,6 +673,8 @@ export default function RequestAcceptedPage() {
)}
{caseStatus !== "contacted" &&
!isFemaleContactConfirmed &&
!noContactReportedSuccess &&
!(isFemaleProfile && contactStatusMutation.isPending) ? (
<div className="border border-[#F0445B] bg-[#F0445B]/10 rounded-xl mt-4">
<p className="text-[#F0445B] group-12 font-semibold py-2.5 px-3.5 whitespace-pre-line">
@ -704,7 +687,6 @@ export default function RequestAcceptedPage() {
</div>
) : null}
</>
)}
</>
)}
</section>

90
src/components/Componentes/female-outcome-sheet.test.tsx

@ -0,0 +1,90 @@
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { I18nProvider } from "@/translations/provider";
import FemaleOutcomeSheet from "./female-outcome-sheet";
vi.mock("./swipe-button", () => ({
default: ({
disabled,
onSuccess,
text,
}: {
disabled?: boolean;
onSuccess: () => void;
text: string;
}) => (
<button type="button" disabled={disabled} onClick={onSuccess}>
{text}
</button>
),
}));
function renderSheet(onSubmit = vi.fn()) {
render(
<I18nProvider locale="en">
<FemaleOutcomeSheet onSubmit={onSubmit} />
</I18nProvider>,
);
return onSubmit;
}
describe("FemaleOutcomeSheet", () => {
afterEach(cleanup);
beforeEach(() => {
vi.useRealTimers();
});
it("keeps the profile unchanged when the acquaintance process is still ongoing", async () => {
const onSubmit = renderSheet();
await userEvent.click(
screen.getByRole("button", { name: "Continue" }),
);
expect(onSubmit).toHaveBeenCalledWith("success");
});
it("requires a cancellation reason and submits it as a failure", async () => {
const onSubmit = renderSheet();
await userEvent.click(screen.getByLabelText("Canceled"));
const confirmation = screen.getByRole("button", {
name: "Confirm",
});
expect(confirmation).toHaveProperty("disabled", true);
await userEvent.click(
screen.getByRole("button", { name: "No mutual interest" }),
);
expect(confirmation).toHaveProperty("disabled", false);
fireEvent.click(confirmation);
expect(onSubmit).toHaveBeenCalledWith("failure", "No mutual interest");
});
it("requires a written note when the other cancellation reason is selected", async () => {
renderSheet();
await userEvent.click(screen.getByLabelText("Canceled"));
await userEvent.click(
screen.getByRole("button", { name: "Other reasons" }),
);
const confirmation = screen.getByRole("button", {
name: "Confirm",
});
expect(confirmation).toHaveProperty("disabled", true);
await userEvent.type(
screen.getByPlaceholderText(
"Feel free to briefly explain your decision...",
),
"The families could not agree on the next steps.",
);
expect(confirmation).toHaveProperty("disabled", false);
});
});

6
src/components/Componentes/female-outcome-sheet.tsx

@ -355,7 +355,8 @@ export function FemaleOutcomeSheet({
{outcome === "ongoing" ? (
<SwipeButton
theme="green"
text={t["Swipe to continue"]}
text={t["Continue"]}
onCancel={closeSheet}
onSuccess={() => {
onSubmit?.("success");
closeSheet();
@ -365,7 +366,8 @@ export function FemaleOutcomeSheet({
<SwipeButton
theme="default"
disabled={isCanceledSwipeDisabled}
text={t["Swipe to confirm cancellation"]}
text={t["Confirm"]}
onCancel={closeSheet}
onSuccess={() => {
const activeReasons = selectedReasons.map((r) => {
if (r === reasons[reasons.length - 1]) {

186
src/components/Componentes/swipe-button.tsx

@ -1,171 +1,71 @@
"use client";
import type React from "react";
import { useEffect, useRef, useState } from "react";
import { GoChevronLeft, GoChevronRight } from "react-icons/go";
import { useState } from "react";
import { useI18n } from "@/translations/provider";
import { LoadingThreeDot } from "./loading-three-dot";
type SwipeButtonProps = {
onSuccess: () => void;
onCancel?: () => void;
text: string;
cancelText?: string;
disabled?: boolean;
theme?: "default" | "green";
};
export function SwipeButton({
onSuccess,
onCancel,
text,
cancelText,
disabled = false,
theme = "default",
}: SwipeButtonProps) {
const { locale } = useI18n();
const isRtl =
locale === "fa" ||
locale === "ar" ||
locale === "ur" ||
locale === "he" ||
locale === "ks";
const { dictionary: t } = useI18n();
const [clicked, setClicked] = useState(false);
const [dragX, setDragX] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const [swiped, setSwiped] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const startX = useRef(0);
const getContainerWidth = () => {
return containerRef.current ? containerRef.current.clientWidth : 0;
};
const handleStart = (clientX: number) => {
if (disabled || swiped) return;
setIsDragging(true);
startX.current = clientX;
};
const handleMove = (clientX: number) => {
if (!isDragging || swiped) return;
const delta = isRtl ? startX.current - clientX : clientX - startX.current;
const containerWidth = getContainerWidth();
const handleWidth = 48; // width of the handle button (w-12 = 48px)
const padding = 8; // padding around the handle (p-1 = 4px on each side -> 8px total)
const maxDrag = containerWidth - handleWidth - padding;
const newDragX = Math.max(0, Math.min(delta, maxDrag));
setDragX(newDragX);
};
const handleEnd = () => {
if (!isDragging) return;
setIsDragging(false);
const containerWidth = getContainerWidth();
const handleWidth = 48;
const padding = 8;
const maxDrag = containerWidth - handleWidth - padding;
if (dragX >= maxDrag * 0.85) {
const finalX = maxDrag;
setDragX(finalX);
setSwiped(true);
onSuccess();
} else {
setDragX(0);
}
};
// Touch handlers
const onTouchStart = (e: React.TouchEvent) => {
handleStart(e.touches[0].clientX);
};
const onTouchMove = (e: React.TouchEvent) => {
handleMove(e.touches[0].clientX);
const handleClick = () => {
setClicked(true);
onSuccess();
};
// Mouse handlers
const onMouseDown = (e: React.MouseEvent) => {
handleStart(e.clientX);
};
useEffect(() => {
if (!isDragging) return;
const onGlobalMouseMove = (e: MouseEvent) => {
handleMove(e.clientX);
};
const onGlobalMouseUp = () => {
handleEnd();
};
window.addEventListener("mousemove", onGlobalMouseMove);
window.addEventListener("mouseup", onGlobalMouseUp);
return () => {
window.removeEventListener("mousemove", onGlobalMouseMove);
window.removeEventListener("mouseup", onGlobalMouseUp);
};
}, [isDragging, handleEnd, handleMove]);
const handleStyle = isRtl
? {
transform: `translateX(${-dragX}px)`,
transition: isDragging ? "none" : "transform 0.2s ease-out",
right: "4px",
}
: {
transform: `translateX(${dragX}px)`,
transition: isDragging ? "none" : "transform 0.2s ease-out",
left: "4px",
};
const cancelLabel = cancelText || t?.["Cancel"] || "Cancel";
const isGreen = theme === "green";
const containerBg = isGreen ? "bg-[#E8F8F3]" : "bg-[#FFECEF]";
const fillBg = isGreen ? "bg-[#00AC78]/15" : "bg-[#FFCCD4]/30";
const textColor = isGreen ? "text-[#00AC78]" : "text-[#F0445B]";
const handleBg = isGreen ? "bg-[#00AC78]" : "bg-[#F0445B]";
return (
<div
ref={containerRef}
className={`relative flex h-[56px] w-full items-center justify-center rounded-[15px] ${containerBg} p-1 select-none overflow-hidden ${
disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer"
}`}
onTouchStart={onTouchStart}
onTouchMove={onTouchMove}
onTouchEnd={handleEnd}
onMouseDown={onMouseDown}
const buttonBg = isGreen ? "bg-[#00AC78]" : "bg-[#F0445B]";
const actionButton = (
<button
type="button"
disabled={disabled || clicked}
onClick={handleClick}
className={`flex-1 h-[52px] rounded-[11px] ${buttonBg} text-white font-semibold group-16 flex items-center justify-center cursor-pointer transition-all active:scale-[0.98] hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed`}
>
{/* Background sliding fill */}
<div
className={`absolute inset-y-0 ${fillBg}`}
style={{
left: isRtl ? "auto" : 0,
right: isRtl ? 0 : "auto",
width: `${dragX + 48}px`,
transition: isDragging ? "none" : "width 0.2s ease-out",
}}
/>
{/* Slide text */}
<span
className={`pointer-events-none z-10 text-[14px] font-bold ${textColor} animate-pulse`}
>
{swiped ? <LoadingThreeDot /> : text}
</span>
{clicked ? <LoadingThreeDot /> : text}
</button>
);
{/* Slide handle */}
<div
style={handleStyle}
className={`absolute top-1 bottom-1 flex aspect-square items-center justify-center rounded-full ${handleBg} text-white shadow-lg z-20 cursor-grab active:cursor-grabbing`}
>
{isRtl ? (
<GoChevronLeft className="size-6 shrink-0" />
) : (
<GoChevronRight className="size-6 shrink-0" />
)}
if (onCancel) {
return (
<div className="flex w-full items-center gap-3">
{/* Cancel Button */}
<button
type="button"
onClick={onCancel}
className="flex-1 h-[52px] rounded-[11px] border border-[#8B8B8B] bg-transparent text-[#8B8B8B] font-semibold group-16 flex items-center justify-center cursor-pointer transition-all active:scale-[0.98] hover:opacity-90"
>
{cancelLabel}
</button>
{/* Action Button */}
{actionButton}
</div>
);
}
// Single Button full width
return (
<div className="w-full flex">
{actionButton}
</div>
);
}

2
src/lib/get-submit-path.ts

@ -4,7 +4,7 @@ import {
isWithinMatchStartGrace,
} from "./match-start-grace";
export function getSubmitPath(profile: MarriageProfileResponse | undefined) {
export function getSubmitPath(profile: MarriageProfileResponse | undefined): string {
clearLegacyMatchSubmittedFlag();
if (!profile) {

28
src/lib/view-paddings.ts

@ -56,6 +56,16 @@ function safeParse(value: string): unknown {
}
}
function getEventData(event: unknown): Record<string, unknown> | null {
if (!event || typeof event !== "object") return null;
const envelope = event as Record<string, unknown>;
const rawData = envelope.data ?? envelope.payload;
if (!rawData || typeof rawData !== "object") return null;
return rawData as Record<string, unknown>;
}
function readEdges(source: EdgeSource): ViewPaddings {
return {
top: num(source?.top),
@ -157,12 +167,19 @@ class ViewPaddingsBridge {
if (typeof win.addFlutterResponseListener !== "function") return false;
this.flutterUnsubscribe = win.addFlutterResponseListener((event) => {
if (!event || event.success === false || !event.data) return;
if (!event || event.success === false) return;
// Flutter clients use both `data` and `payload` for bridge responses.
// In particular, the uppercase INITIAL_CONFIG protocol uses `payload`.
// Keep the locale in that response so the route can be localized as soon
// as the WebView opens.
const data = getEventData(event);
if (!data) return;
switch (event.action) {
case "initial_config":
case "INITIAL_CONFIG":
this.applyInitialConfig(event.data ?? event.payload);
this.applyInitialConfig(data);
this.hasInitialConfig = true;
return;
@ -170,19 +187,18 @@ class ViewPaddingsBridge {
case "language_changed":
case "LOCALE_CHANGED":
case "LANGUAGE_CHANGED": {
const data = event.data ?? event.payload;
this.applyLocale(data?.locale ?? data);
return;
}
// به‌روزرسانی فضای امن هنگام چرخش/تغییر notch (px منطقی).
case "safe_area_changed":
this.applySafeArea(readEdges(event.data));
this.applySafeArea(readEdges(data));
return;
// ارتفاع کیبورد به‌صورت زنده (px منطقی).
case "keyboard_changed": {
const height = num(event.data.height);
const height = num(data.height);
this.config.keyboardHeight = height;
this.applyKeyboard(height);
return;
@ -192,7 +208,7 @@ class ViewPaddingsBridge {
// اگر initial_config رسیده باشد، آن مرجع است و این نادیده گرفته می‌شود.
case "get_view_paddings":
if (this.hasInitialConfig) return;
this.applyEdges(toLogical(readEdges(event.data)));
this.applyEdges(toLogical(readEdges(data)));
return;
default:

11
src/test/setup.ts

@ -0,0 +1,11 @@
import "@testing-library/jest-dom/vitest";
Object.defineProperty(window, "requestAnimationFrame", {
value: (callback: FrameRequestCallback) => window.setTimeout(callback, 0),
});
Object.defineProperty(window, "cancelAnimationFrame", {
value: (id: number) => window.clearTimeout(id),
});
HTMLTextAreaElement.prototype.scrollIntoView = () => {};

40
src/translations/dictionaries.ts

@ -54,9 +54,41 @@ export const dictionaries = {
export type Dictionary = typeof dictionaries.en;
function mergeWithEnglishFallback(
fallback: Record<string, unknown>,
localized: Record<string, unknown>,
): Record<string, unknown> {
const result = { ...fallback };
for (const [key, localizedValue] of Object.entries(localized)) {
const fallbackValue = fallback[key];
if (
localizedValue &&
typeof localizedValue === "object" &&
!Array.isArray(localizedValue) &&
fallbackValue &&
typeof fallbackValue === "object" &&
!Array.isArray(fallbackValue)
) {
result[key] = mergeWithEnglishFallback(
fallbackValue as Record<string, unknown>,
localizedValue as Record<string, unknown>,
);
} else {
result[key] = localizedValue;
}
}
return result;
}
export function getDictionary(locale: Locale): Dictionary {
return (
(dictionaries as unknown as Record<string, Dictionary>)[locale] ??
dictionaries.en
);
const localized = (dictionaries as unknown as Record<string, Dictionary>)[
locale
];
if (!localized || locale === "en") return dictionaries.en;
return mergeWithEnglishFallback(dictionaries.en, localized) as Dictionary;
}

11
src/translations/locales/ar.json

@ -746,5 +746,12 @@
"video": "فيديو",
"{completed} of {total} required steps completed": "{Completed} من {total} الخطوات المطلوبة المكتملة",
"{days} days remaining of your subscription.": "{days} يوم متبقي من اشتراكك.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ هذا القسم سري تمامًا ويستخدم فقط للمطابقة والمراجعة من قبل المستشارين."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ هذا القسم سري تمامًا ويستخدم فقط للمطابقة والمراجعة من قبل المستشارين.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/az.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{total} tələb olunan addımdan {tamamlandı} tamamlandı",
"{days} days remaining of your subscription.": "Abunəliyinizə {days} gün qalıb.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ Bu bölmə tamamilə məxfidir və yalnız məsləhətçilər tərəfindən uyğunlaşdırılması və nəzərdən keçirilməsi üçün istifadə olunur."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ Bu bölmə tamamilə məxfidir və yalnız məsləhətçilər tərəfindən uyğunlaşdırılması və nəzərdən keçirilməsi üçün istifadə olunur.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/bn.json

@ -746,5 +746,12 @@
"video": "ভিডিও",
"{completed} of {total} required steps completed": "{total} প্রয়োজনীয় ধাপগুলির মধ্যে {completed} সম্পন্ন হয়েছে৷",
"{days} days remaining of your subscription.": "আপনার সদস্যতার {দিন} দিন বাকি।",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ এই বিভাগটি সম্পূর্ণ গোপনীয় এবং শুধুমাত্র উপদেষ্টাদের দ্বারা মেলানো এবং পর্যালোচনা করার জন্য ব্যবহার করা হয়।"
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ এই বিভাগটি সম্পূর্ণ গোপনীয় এবং শুধুমাত্র উপদেষ্টাদের দ্বারা মেলানো এবং পর্যালোচনা করার জন্য ব্যবহার করা হয়।",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/da.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "{days} dage tilbage af dit abonnement.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/de.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "{days} Tage verbleibende Laufzeit Ihres Abonnements.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

5
src/translations/locales/en.json

@ -757,5 +757,6 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "{days} days remaining of your subscription.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Please select the reason for cancellation:": "Please select the reason for cancellation:"
}

11
src/translations/locales/es.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "{days} días restantes de tu suscripción.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

7
src/translations/locales/fa.json

@ -635,7 +635,7 @@
"Temporary conditions": "فعلاً شرایط موقت دارم.",
"Temporary with family okay": "زندگی موقت با خانواده در ابتدای ازدواج قابل قبول است.",
"Thank you for giving us feedback, we would be very happy if you also let us know the final result.": "ممنون از اینکه به ما فیدبک دادید، بسیار خوشحال میشویم نتیجه نهایی را نیز به ما اعلام کنید",
"Thank you for your feedback. Our support team will investigate the matter and notify you of the result. Please wait patiently during the review; our support will contact you.": "از فیدبکی که به ما دادید متشکریم. پشتیبانی ما موضوع را بررسی میکند و نتیجه را به شما اعلام خواهد کرد. لطفاً در مدت بررسی منتظر بمانید و صبوری کنید؛ پشتیبانی ما با شما تماس خواهد گرفت.",
"Thank you for your feedback. Our support team will investigate the matter and notify you of the result. Please wait patiently during the review; our support will contact you.": "ممنون از بازخورد شما و تیم پشتیبانی ما در اسرع وقت موضوع رو بررسی و به اطلاع شما میرسونن",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "از بازخورد شما ممنونیم. برای تکمیل پروسه لطفا فیدبک نهایی این ارتباط/معرفی رو بهمون بده تا وضعیت نهایی مشخص شه. اگر هنوز وضعیت نهایی نشده میتونید در همین حالت بمونید تا وضعیت نهایی شه.",
"The call may start 10-15 minutes earlier or later than scheduled.": "تماس ممکن است ۱۰ الی ۱۵ دقیقه زودتر یا دیرتر از زمان تعیین‌شده برقرار شود.",
"The selected candidate will contact your family shortly.": "گزینه انتخاب‌شده به‌زودی با خانواده شما تماس می‌گیرد.",
@ -757,5 +757,6 @@
"video": "ویدیو",
"{completed} of {total} required steps completed": "{completed} از {total} مرحله ضروری کامل شده است",
"{days} days remaining of your subscription.": "{days} روز از اعتبار اشتراک شما باقی مانده است.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ این بخش کاملاً محرمانه است و فقط برای مچینگ و بررسی کارشناسان استفاده میشود."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ این بخش کاملاً محرمانه است و فقط برای مچینگ و بررسی کارشناسان استفاده میشود.",
"Please select the reason for cancellation:": "Please select the reason for cancellation:"
}

11
src/translations/locales/fr.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "{days} jours restants de votre abonnement.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/gu.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "તમારા સબ્સ્ક્રિપ્શનના {days} દિવસ બાકી છે.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/ha.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "{days} days remaining of your subscription.",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/he.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/hi.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "आपकी सदस्यता के {days} दिन शेष हैं।",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/id.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/ks.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/pt.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

18
src/translations/locales/ru.json

@ -1,5 +1,11 @@
{
"Contact Received": "Контакт получен",
"Contact info released": "Контактная информация раскрыта",
"You can now view their family's contact details and arrange further steps.": "Теперь вы можете просмотреть контактные данные семьи и договориться о дальнейших шагах.",
"View profile": "Посмотреть профиль",
"View contact number": "Посмотреть номер телефона",
"If they don't contact you within 2 days, please inform us.": "Если с вами не свяжутся в течение 2 дней, пожалуйста, сообщите нам.",
"Profile is locked": "Профиль заблокирован",
"No Contact Received": "Контакт не получен",
"No contact has been made with you in any way or by any party.": "С вами не связывались никаким образом и ни с какой стороны.",
"Thank you for your feedback. Our support team will investigate the matter and notify you of the result. Please wait patiently during the review; our support will contact you.": "Спасибо за ваш отзыв. Наша служба поддержки расследует этот вопрос и сообщит вам о результате. Пожалуйста, наберитесь терпения во время проверки; наша служба поддержки свяжется с вами.",
@ -271,5 +277,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/sw.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/tg.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/tr.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/ul.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/ur.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

12
src/translations/locales/uz.json

@ -271,5 +271,13 @@
"dismissDescription": "Please provide the full reason for rejecting the submitted item",
"dismissPlaceholder": "Your explanatory text ..."
},
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"spouseCriteriaConfidentialNotice": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"What was the outcome of your contact?": "What was the outcome of your contact?",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

11
src/translations/locales/zh.json

@ -746,5 +746,12 @@
"video": "video",
"{completed} of {total} required steps completed": "{completed} of {total} required steps completed",
"{days} days remaining of your subscription.": "您的订阅还剩 {days} 天。",
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors."
}
"⚠️ This section is completely confidential and is only used for matching and review by advisors.": "⚠️ This section is completely confidential and is only used for matching and review by advisors.",
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.": "Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized.",
"Share Result": "Share Result",
"We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.": "We hope the acquaintance process is going well. Please let us know if you want to continue the acquaintance process or if the match has been canceled.",
"We are in the acquaintance/proposal process and nothing is finalized yet": "We are in the acquaintance/proposal process and nothing is finalized yet",
"Please select the reason for cancellation:": "Please select the reason for cancellation:",
"Swipe to continue": "Swipe to continue",
"Swipe to confirm cancellation": "Swipe to confirm cancellation"
}

14
vitest.config.ts

@ -0,0 +1,14 @@
import path from "node:path";
import { defineConfig } from "vitest/config";
export default defineConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
test: {
environment: "jsdom",
setupFiles: ["./src/test/setup.ts"],
},
});
Loading…
Cancel
Save