Browse Source

fix(i18n): pass locale headers in SSR fetch and ensure English fallback for match summary fields

master
Alireza 22 hours ago
parent
commit
4808877b71
  1. 1
      src/app/new-match/new-match-client.tsx
  2. 8
      src/lib/marriage-field-formatter.ts
  3. 52
      src/lib/ssr-fetch.ts

1
src/app/new-match/new-match-client.tsx

@ -119,6 +119,7 @@ const fieldCandidateMatchers = {
"career", "career",
], ],
hobbies: [ hobbies: [
"what_are_your_main_hobbies_and_interests",
"your_hobbies_and_main_interests", "your_hobbies_and_main_interests",
"hobbies_and_interests", "hobbies_and_interests",
"hobbies", "hobbies",

8
src/lib/marriage-field-formatter.ts

@ -122,7 +122,13 @@ export function formatFieldLabel(
return matchedCanonicalKey; return matchedCanonicalKey;
} }
// 5. Fallback
// 5. If rawLabel contains Persian/Arabic characters and active dictionary is English, use englishTitle
const hasPersian = /[؀-ۿ]/.test(rawLabel);
if (hasPersian && dictionary) {
return englishTitle || rawLabel;
}
// 6. Fallback
return rawLabel || englishTitle; return rawLabel || englishTitle;
} }

52
src/lib/ssr-fetch.ts

@ -1,4 +1,6 @@
// Server-only module: imported only by Server Components (page.tsx wrappers). // Server-only module: imported only by Server Components (page.tsx wrappers).
import { cookies, headers } from "next/headers";
import { defaultLocale, isLocale } from "@/translations/config";
/** /**
* Helper to get the API base URL for server-side fetches. * Helper to get the API base URL for server-side fetches.
@ -18,6 +20,41 @@ const DEFAULT_SSR_TIMEOUT_MS =
Number(process.env.SSR_FETCH_TIMEOUT_MS) || Number(process.env.SSR_FETCH_TIMEOUT_MS) ||
(process.env.NODE_ENV === "development" ? 15000 : 1500); (process.env.NODE_ENV === "development" ? 15000 : 1500);
async function resolveServerLocale(
localeOverride?: string | null,
): Promise<string> {
if (localeOverride && isLocale(localeOverride)) {
return localeOverride;
}
try {
const cookieStore = await cookies();
const cookieLang =
cookieStore.get("HABIB_LANGUAGE")?.value ??
cookieStore.get("habib_language")?.value;
if (isLocale(cookieLang)) {
return cookieLang;
}
} catch {
// Ignore if called outside request context
}
try {
const headersList = await headers();
const headerLang = headersList
.get("accept-language")
?.split(",")[0]
?.split("-")[0];
if (isLocale(headerLang)) {
return headerLang;
}
} catch {
// Ignore if called outside request context
}
return defaultLocale;
}
/** /**
* Fetches the marriage profile server-side. * Fetches the marriage profile server-side.
* Runs only on the server, typically inside a Next.js Server Component. * Runs only on the server, typically inside a Next.js Server Component.
@ -25,11 +62,13 @@ const DEFAULT_SSR_TIMEOUT_MS =
* *
* @param token - The user authentication token * @param token - The user authentication token
* @param timeoutMs - Timeout in milliseconds (defaults to 15s in dev, 1.5s in prod) * @param timeoutMs - Timeout in milliseconds (defaults to 15s in dev, 1.5s in prod)
* @param localeOverride - Optional locale override
* @returns Profile data or null on failure * @returns Profile data or null on failure
*/ */
export async function fetchProfileSSR( export async function fetchProfileSSR(
token?: string | null, token?: string | null,
timeoutMs = DEFAULT_SSR_TIMEOUT_MS, timeoutMs = DEFAULT_SSR_TIMEOUT_MS,
localeOverride?: string | null,
): Promise<any | null> { ): Promise<any | null> {
if (!token || token === "NO_TOKEN" || token.trim() === "") { if (!token || token === "NO_TOKEN" || token.trim() === "") {
console.log("🖥️ [SSR fetchProfileSSR] No valid token found in cookies."); console.log("🖥️ [SSR fetchProfileSSR] No valid token found in cookies.");
@ -40,10 +79,11 @@ export async function fetchProfileSSR(
const timeoutId = setTimeout(() => controller.abort(), timeoutMs); const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try { try {
const lang = await resolveServerLocale(localeOverride);
const baseUrl = getApiBaseUrl(); const baseUrl = getApiBaseUrl();
const url = `${baseUrl}/api/marriage/profile/main/`;
const url = `${baseUrl}/api/marriage/profile/main/?lang=${lang}`;
console.log( console.log(
`🖥️ [SSR fetchProfileSSR] Fetching profile from ${url} with token: ${token.slice(0, 8)}...`,
`🖥️ [SSR fetchProfileSSR] Fetching profile from ${url} with token: ${token.slice(0, 8)}... (lang: ${lang})`,
); );
const response = await fetch(url, { const response = await fetch(url, {
@ -53,6 +93,8 @@ export async function fetchProfileSSR(
headers: { headers: {
Accept: "application/json", Accept: "application/json",
Authorization: `Token ${token.trim()}`, Authorization: `Token ${token.trim()}`,
"Accept-Language": lang,
"X-User-Language": lang,
}, },
}); });
@ -88,13 +130,15 @@ export async function fetchProfileSSR(
*/ */
export async function fetchConfigSSR( export async function fetchConfigSSR(
timeoutMs = DEFAULT_SSR_TIMEOUT_MS, timeoutMs = DEFAULT_SSR_TIMEOUT_MS,
localeOverride?: string | null,
): Promise<any | null> { ): Promise<any | null> {
const controller = new AbortController(); const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs); const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try { try {
const lang = await resolveServerLocale(localeOverride);
const baseUrl = getApiBaseUrl(); const baseUrl = getApiBaseUrl();
const url = `${baseUrl}/api/marriage/config/`;
const url = `${baseUrl}/api/marriage/config/?lang=${lang}`;
const response = await fetch(url, { const response = await fetch(url, {
method: "GET", method: "GET",
@ -102,6 +146,8 @@ export async function fetchConfigSSR(
signal: controller.signal, signal: controller.signal,
headers: { headers: {
Accept: "application/json", Accept: "application/json",
"Accept-Language": lang,
"X-User-Language": lang,
}, },
}); });

Loading…
Cancel
Save