diff --git a/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx b/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx
index 46bb93b..b5204d5 100644
--- a/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx
+++ b/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx
@@ -6,6 +6,7 @@ import { FaCheck, FaEdit, FaTimes, FaTrash } from "react-icons/fa";
import Pagination from "../../../../components/globals/Pagination";
import { DateTimeDisplay } from "../../../../utils/formatDateTime";
import { getLocaleFromPathname, localizePath } from "../../../../utils/localeRouting";
+import { getFlagUrl } from "../../../../utils/countries";
import type { Reply, Thread } from "./types";
@@ -130,6 +131,7 @@ const ThreadDetail = ({
const actionButtonClass = "btn btn-sm btn-ghost gap-2";
const primaryActionButtonClass = "btn btn-sm btn-neutral gap-2";
+ const threadFlagUrl = getFlagUrl(thread.country_code, 20);
const toggleViewMoreReplies = (parentReplyId: string) => {
setExpandedReplyParents((previous) => ({
@@ -143,6 +145,7 @@ const ThreadDetail = ({
const nestedReplies = repliesByParent.get(reply.id) ?? [];
const isExpanded = Boolean(expandedReplyParents[reply.id]);
const hasMoreReplies = nestedReplies.length > 3;
+ const replyFlagUrl = getFlagUrl(reply.country_code, 20);
const visibleReplies = hasMoreReplies && !isExpanded
? nestedReplies.slice(0, 3)
: nestedReplies;
@@ -205,6 +208,14 @@ const ThreadDetail = ({
{reply.username || "Anonymous"}
)}
+ {replyFlagUrl && (
+

+ )}
)}
{!thread.user_id && {thread.username || "Anonymous"}}
+ {threadFlagUrl && (
+
+ )}
•
{thread.username || "Anonymous"}
)}
+ {threadFlagUrl && (
+
+ )}
•
{
+ if (!value) return null;
+ const normalized = value.trim().toUpperCase();
+ return /^[A-Z]{2}$/.test(normalized) ? normalized : null;
+};
+
+export const getFlagUrl = (countryCode?: string | null, size = 24): string | null => {
+ const normalized = normalizeCountryCode(countryCode);
+ if (!normalized) return null;
+ return `https://flagsapi.com/${normalized}/flat/${size}.png`;
+};
+
+const getDisplayName = (code: string, displayNames?: Intl.DisplayNames): string => {
+ return displayNames?.of(code) ?? code;
+};
+
+export const getCountryOptions = (locale = "en"): CountryOption[] => {
+ let displayNames: Intl.DisplayNames | undefined;
+ if (typeof Intl !== "undefined" && typeof Intl.DisplayNames === "function") {
+ try {
+ displayNames = new Intl.DisplayNames([locale], { type: "region" });
+ } catch {
+ displayNames = undefined;
+ }
+ }
+
+ // Intl.supportedValuesOf does not support "region" keys; use a curated fallback list.
+ const regionCodes = FALLBACK_COUNTRY_CODES;
+
+ const uniqueCodes = Array.from(
+ new Set(regionCodes.map((code) => normalizeCountryCode(code)).filter((code): code is string => Boolean(code))),
+ );
+
+ return uniqueCodes
+ .map((code) => ({
+ code,
+ name: getDisplayName(code, displayNames),
+ }))
+ .sort((a, b) => a.name.localeCompare(b.name));
+};
From 542fb4e723f5afb1585f3a29913dc88b62120b5f Mon Sep 17 00:00:00 2001
From: Stephen
Date: Mon, 20 Apr 2026 03:23:45 +0100
Subject: [PATCH 4/6] feat: normalize country code handling in forums and
threads for improved consistency
---
.../src/pages/public/travel-advice/Forums.tsx | 10 ++++++-
.../travel-advice/forums/ThreadDetail.tsx | 26 ++++++++++++++++---
.../travel-advice/forums/ThreadsList.tsx | 21 +++++++++++++--
3 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/frontend/src/pages/public/travel-advice/Forums.tsx b/frontend/src/pages/public/travel-advice/Forums.tsx
index 8142db4..fdb98d4 100644
--- a/frontend/src/pages/public/travel-advice/Forums.tsx
+++ b/frontend/src/pages/public/travel-advice/Forums.tsx
@@ -11,6 +11,10 @@ import ThreadsList from "./forums/ThreadsList";
import type { Reply, RepliesResponse, Thread, ThreadsResponse } from "./forums/types";
import { getLocaleFromPathname, localizePath } from "../../../utils/localeRouting";
+type ReplyApiShape = Reply & {
+ countryCode?: string | null;
+};
+
const Forums = () => {
const { profile, token } = useAuth();
const navigate = useNavigate();
@@ -137,7 +141,11 @@ const Forums = () => {
}
const result: RepliesResponse = await response.json();
- setReplies(result.data);
+ const normalizedReplies = (result.data as ReplyApiShape[]).map((reply) => ({
+ ...reply,
+ country_code: reply.country_code ?? reply.countryCode ?? null,
+ }));
+ setReplies(normalizedReplies);
setRepliesTotalPages(result.totalPages);
} catch (err) {
console.error("Error fetching replies:", err);
diff --git a/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx b/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx
index b5204d5..dfbd5c2 100644
--- a/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx
+++ b/frontend/src/pages/public/travel-advice/forums/ThreadDetail.tsx
@@ -10,6 +10,15 @@ import { getFlagUrl } from "../../../../utils/countries";
import type { Reply, Thread } from "./types";
+type CountryCodeCarrier = {
+ country_code?: string | null;
+ countryCode?: string | null;
+ profile?: {
+ country_code?: string | null;
+ countryCode?: string | null;
+ } | null;
+};
+
type ThreadDetailProps = {
thread: Thread;
replies: Reply[];
@@ -131,7 +140,15 @@ const ThreadDetail = ({
const actionButtonClass = "btn btn-sm btn-ghost gap-2";
const primaryActionButtonClass = "btn btn-sm btn-neutral gap-2";
- const threadFlagUrl = getFlagUrl(thread.country_code, 20);
+ const getCountryCode = (value: CountryCodeCarrier) => {
+ return value.country_code
+ ?? value.countryCode
+ ?? value.profile?.country_code
+ ?? value.profile?.countryCode
+ ?? null;
+ };
+ const threadCountryCode = getCountryCode(thread as Thread & CountryCodeCarrier);
+ const threadFlagUrl = getFlagUrl(threadCountryCode, 64);
const toggleViewMoreReplies = (parentReplyId: string) => {
setExpandedReplyParents((previous) => ({
@@ -145,7 +162,8 @@ const ThreadDetail = ({
const nestedReplies = repliesByParent.get(reply.id) ?? [];
const isExpanded = Boolean(expandedReplyParents[reply.id]);
const hasMoreReplies = nestedReplies.length > 3;
- const replyFlagUrl = getFlagUrl(reply.country_code, 20);
+ const replyCountryCode = getCountryCode(reply as Reply & CountryCodeCarrier);
+ const replyFlagUrl = getFlagUrl(replyCountryCode, 64);
const visibleReplies = hasMoreReplies && !isExpanded
? nestedReplies.slice(0, 3)
: nestedReplies;
@@ -211,7 +229,7 @@ const ThreadDetail = ({
{replyFlagUrl && (
@@ -361,7 +379,7 @@ const ThreadDetail = ({
{threadFlagUrl && (
diff --git a/frontend/src/pages/public/travel-advice/forums/ThreadsList.tsx b/frontend/src/pages/public/travel-advice/forums/ThreadsList.tsx
index 41eefb8..2fb9711 100644
--- a/frontend/src/pages/public/travel-advice/forums/ThreadsList.tsx
+++ b/frontend/src/pages/public/travel-advice/forums/ThreadsList.tsx
@@ -11,6 +11,15 @@ import { getFlagUrl } from "../../../../utils/countries";
import type { Thread } from "./types";
+type CountryCodeCarrier = {
+ country_code?: string | null;
+ countryCode?: string | null;
+ profile?: {
+ country_code?: string | null;
+ countryCode?: string | null;
+ } | null;
+};
+
type ThreadsListProps = {
threads: Thread[];
loading: boolean;
@@ -126,6 +135,13 @@ const ThreadsList = ({
{ value: "desc", label: descendingLabel },
{ value: "asc", label: ascendingLabel },
];
+ const getCountryCode = (value: CountryCodeCarrier) => {
+ return value.country_code
+ ?? value.countryCode
+ ?? value.profile?.country_code
+ ?? value.profile?.countryCode
+ ?? null;
+ };
return (
@@ -243,7 +259,8 @@ const ThreadsList = ({
currentUserId && thread.user_id === currentUserId,
);
const isEditing = editingThreadId === thread.id;
- const threadFlagUrl = getFlagUrl(thread.country_code, 20);
+ const threadCountryCode = getCountryCode(thread as Thread & CountryCodeCarrier);
+ const threadFlagUrl = getFlagUrl(threadCountryCode, 64);
return (
From d4f8398cd7efb03f0dc1b713e1f9723d3565d14a Mon Sep 17 00:00:00 2001
From: Stephen
Date: Mon, 20 Apr 2026 03:33:36 +0100
Subject: [PATCH 5/6] feat: refactor country code handling in profiles,
threads, and replies for improved consistency and settings management
---
backend/src/db/handlers/profiles.ts | 38 ++++++++----
.../routes/authenticated/forums/replies.ts | 2 +-
.../routes/authenticated/forums/threads.ts | 4 +-
backend/src/routes/authenticated/profiles.ts | 43 ++++++++++++--
frontend/src/App.tsx | 58 ++++++++++++++++++-
frontend/src/components/i18n/LangToggler.tsx | 28 +++++++++
frontend/src/context/AuthContext.tsx | 5 ++
frontend/src/pages/authenticated/Profile.tsx | 11 +++-
8 files changed, 166 insertions(+), 23 deletions(-)
diff --git a/backend/src/db/handlers/profiles.ts b/backend/src/db/handlers/profiles.ts
index 0036449..8c1c72e 100644
--- a/backend/src/db/handlers/profiles.ts
+++ b/backend/src/db/handlers/profiles.ts
@@ -7,9 +7,8 @@ type Profile = {
email?: string | null;
username?: string;
photo?: string | null;
- settings?: Record | null;
+ settings?: Record | null;
bio?: string | null;
- countryCode?: string | null;
};
function defaultUsername(email: string): string {
@@ -51,7 +50,16 @@ export const uploadAvatar = async (
const getProfileById = async (userId: string) => {
try {
const result = await pool.query(
- "SELECT id, photo, username, bio, country_code FROM profiles WHERE id = $1",
+ `
+ SELECT
+ id,
+ photo,
+ username,
+ bio,
+ settings->>'country_code' AS country_code
+ FROM profiles
+ WHERE id = $1
+ `,
[userId]
);
return result.rows[0];
@@ -64,7 +72,18 @@ const getProfileById = async (userId: string) => {
const getMyProfile = async (userId: string) => {
try {
const result = await pool.query(
- "SELECT id, photo, username, email, settings, bio, country_code FROM profiles WHERE id = $1",
+ `
+ SELECT
+ id,
+ photo,
+ username,
+ email,
+ settings,
+ bio,
+ settings->>'country_code' AS country_code
+ FROM profiles
+ WHERE id = $1
+ `,
[userId]
);
return result.rows[0];
@@ -80,9 +99,9 @@ const createProfile = async (userProfile: Profile) => {
}
const result = await pool.query(
`
- INSERT INTO profiles (id, email, username, photo, settings, bio, country_code, created_at, updated_at)
- VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())
- RETURNING id, email, username, photo, settings, bio, country_code
+ INSERT INTO profiles (id, email, username, photo, settings, bio, created_at, updated_at)
+ VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
+ RETURNING id, email, username, photo, settings, bio, settings->>'country_code' AS country_code
`,
[
userProfile.userId,
@@ -91,7 +110,6 @@ const createProfile = async (userProfile: Profile) => {
userProfile.photo,
userProfile.settings,
userProfile.bio,
- userProfile.countryCode ?? null,
]
);
return result.rows[0];
@@ -105,10 +123,9 @@ const updateProfile = async (userProfile: Profile) => {
photo = $3,
settings = $4,
bio = $5,
- country_code = $6,
updated_at = NOW()
WHERE id = $1
- RETURNING *
+ RETURNING id, email, username, photo, settings, bio, settings->>'country_code' AS country_code
`,
[
userProfile.userId,
@@ -116,7 +133,6 @@ const updateProfile = async (userProfile: Profile) => {
userProfile.photo,
userProfile.settings,
userProfile.bio,
- userProfile.countryCode ?? null,
]
);
return result.rows[0];
diff --git a/backend/src/routes/authenticated/forums/replies.ts b/backend/src/routes/authenticated/forums/replies.ts
index 2249a71..40a6e09 100644
--- a/backend/src/routes/authenticated/forums/replies.ts
+++ b/backend/src/routes/authenticated/forums/replies.ts
@@ -41,7 +41,7 @@ router.get("/", async (req, res) => {
r.created_at,
p.username,
p.photo,
- p.country_code
+ p.settings->>'country_code' AS country_code
FROM public.replies r
LEFT JOIN public.profiles p ON p.id = r.user_id
WHERE r.thread_id = $1
diff --git a/backend/src/routes/authenticated/forums/threads.ts b/backend/src/routes/authenticated/forums/threads.ts
index cac388c..c2f4d6a 100644
--- a/backend/src/routes/authenticated/forums/threads.ts
+++ b/backend/src/routes/authenticated/forums/threads.ts
@@ -73,7 +73,7 @@ router.get("/", async (req, res) => {
t.updated_at,
p.username,
p.photo,
- p.country_code
+ p.settings->>'country_code' AS country_code
FROM public.threads t
LEFT JOIN public.profiles p ON p.id = t.user_id
${whereSql}
@@ -115,7 +115,7 @@ router.get("/:id", async (req, res) => {
t.updated_at,
p.username,
p.photo,
- p.country_code
+ p.settings->>'country_code' AS country_code
FROM public.threads t
LEFT JOIN public.profiles p ON p.id = t.user_id
WHERE t.id = $1
diff --git a/backend/src/routes/authenticated/profiles.ts b/backend/src/routes/authenticated/profiles.ts
index 4219880..cdda23b 100644
--- a/backend/src/routes/authenticated/profiles.ts
+++ b/backend/src/routes/authenticated/profiles.ts
@@ -21,6 +21,27 @@ const normalizeCountryCode = (value: unknown): string | null => {
return /^[A-Z]{2}$/.test(normalized) ? normalized : null;
};
+const parseSettingsInput = (value: unknown): Record | null => {
+ if (!value) return null;
+
+ if (typeof value === "string") {
+ try {
+ const parsed = JSON.parse(value) as unknown;
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
+ ? (parsed as Record)
+ : null;
+ } catch {
+ return null;
+ }
+ }
+
+ if (typeof value === "object" && !Array.isArray(value)) {
+ return value as Record;
+ }
+
+ return null;
+};
+
// Personal profile routes
router.get("/me", authenticateToken, async (_req, res) => {
@@ -59,16 +80,30 @@ router.patch(
"country_code",
);
const normalizedCountryCode = normalizeCountryCode(req.body.country_code);
+ const incomingSettings = parseSettingsInput(req.body.settings);
+ const existingSettings =
+ existingProfile.settings && typeof existingProfile.settings === "object"
+ ? (existingProfile.settings as Record)
+ : {};
+ const mergedSettings: Record = {
+ ...existingSettings,
+ ...(incomingSettings ?? {}),
+ };
+
+ if (hasCountryCodeField) {
+ if (normalizedCountryCode) {
+ mergedSettings.country_code = normalizedCountryCode;
+ } else {
+ delete mergedSettings.country_code;
+ }
+ }
const updatedProfile = {
userId,
username: req.body.username ?? existingProfile.username,
photo: photoUrl ?? existingProfile.photo,
- settings: req.body.settings ?? existingProfile.settings ?? null, // never undefined
+ settings: Object.keys(mergedSettings).length > 0 ? mergedSettings : null,
bio: req.body.bio ?? existingProfile.bio ?? null,
- countryCode: hasCountryCodeField
- ? normalizedCountryCode
- : existingProfile.country_code ?? null,
};
const result = await updateProfile(updatedProfile);
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 4463e21..5487eb6 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -20,10 +20,64 @@ import {
DEFAULT_LOCALE,
normalizeLocale,
resolvePathLocaleSegment,
+ type AppLocale,
} from "./i18n/locales";
import { localizePath, parseLocaleFromPathname } from "./utils/localeRouting";
import TopAttractions from "./pages/public/explore/TopAttractions";
+const PROFILE_STORAGE_KEY = "profile";
+const HANT_DEFAULT_COUNTRY_CODES = new Set(["HK", "CN", "TW"]);
+
+const resolveLocaleFromCountryCode = (
+ countryCode: string | null | undefined,
+): AppLocale => {
+ const normalized = countryCode?.trim().toUpperCase() ?? "";
+ return HANT_DEFAULT_COUNTRY_CODES.has(normalized)
+ ? "zh-Hant-HK"
+ : "en-GB";
+};
+
+const getUserDefaultLocale = (): AppLocale => {
+ if (typeof window === "undefined") return DEFAULT_LOCALE;
+
+ try {
+ const rawProfile = window.localStorage.getItem(PROFILE_STORAGE_KEY);
+ if (!rawProfile) return DEFAULT_LOCALE;
+
+ const parsedProfile = JSON.parse(rawProfile) as {
+ settings?: {
+ last_used_locale?: unknown;
+ country_code?: unknown;
+ };
+ country_code?: unknown;
+ countryCode?: unknown;
+ };
+
+ const localeFromSettings = normalizeLocale(
+ typeof parsedProfile.settings?.last_used_locale === "string"
+ ? parsedProfile.settings.last_used_locale
+ : null,
+ );
+
+ if (localeFromSettings) {
+ return localeFromSettings;
+ }
+
+ const countryCode =
+ typeof parsedProfile.settings?.country_code === "string"
+ ? parsedProfile.settings.country_code
+ : typeof parsedProfile.country_code === "string"
+ ? parsedProfile.country_code
+ : typeof parsedProfile.countryCode === "string"
+ ? parsedProfile.countryCode
+ : null;
+
+ return resolveLocaleFromCountryCode(countryCode);
+ } catch {
+ return DEFAULT_LOCALE;
+ }
+};
+
const KNOWN_UNLOCALIZED_PATH_PATTERNS = [
/^\/$/,
/^\/events(?:\/[^/]+)?\/?$/,
@@ -68,7 +122,7 @@ const resolveLangQuery = (search: string) => {
const MissingLocaleRedirect = () => {
const location = useLocation();
const langQuery = resolveLangQuery(location.search);
- const nextLocale = langQuery?.locale ?? DEFAULT_LOCALE;
+ const nextLocale = langQuery?.locale ?? getUserDefaultLocale();
const nextSearch = langQuery?.search ?? location.search;
return (
@@ -125,7 +179,7 @@ const LocaleGate = () => {
return (
);
diff --git a/frontend/src/components/i18n/LangToggler.tsx b/frontend/src/components/i18n/LangToggler.tsx
index 71b2f22..16fa584 100644
--- a/frontend/src/components/i18n/LangToggler.tsx
+++ b/frontend/src/components/i18n/LangToggler.tsx
@@ -5,9 +5,12 @@ import { useState, useRef, useEffect } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import type { AppLocale } from "../../i18n/locales";
import { replaceLocaleInPathname } from "../../utils/localeRouting";
+import { useAuth } from "../../context/AuthContext";
+import CONFIG from "../../config";
const LangToggler = () => {
const { i18n, t } = useTranslation();
+ const { token, profile, refreshProfile } = useAuth();
const location = useLocation();
const navigate = useNavigate();
const [open, setOpen] = useState(false);
@@ -32,6 +35,31 @@ const LangToggler = () => {
const changeLang = async (lng: AppLocale) => {
const nextPathname = replaceLocaleInPathname(location.pathname, lng);
await i18n.changeLanguage(lng);
+
+ if (token && profile) {
+ try {
+ const mergedSettings = {
+ ...(profile.settings ?? {}),
+ last_used_locale: lng,
+ };
+
+ await fetch(`${CONFIG.API_BASE_URL}/profiles/me`, {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${token}`,
+ },
+ body: JSON.stringify({
+ settings: mergedSettings,
+ }),
+ });
+
+ await refreshProfile();
+ } catch {
+ // Ignore locale preference persistence failures and continue navigation.
+ }
+ }
+
navigate(`${nextPathname}${location.search}${location.hash}`);
setOpen(false);
};
diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx
index 0124354..fd4f498 100644
--- a/frontend/src/context/AuthContext.tsx
+++ b/frontend/src/context/AuthContext.tsx
@@ -10,6 +10,11 @@ export type ProfileType = {
photo: string | null;
bio: string | null;
country_code: string | null;
+ settings: {
+ country_code?: string;
+ last_used_locale?: string;
+ [key: string]: unknown;
+ } | null;
};
type AuthContextType = {
diff --git a/frontend/src/pages/authenticated/Profile.tsx b/frontend/src/pages/authenticated/Profile.tsx
index 5a86ff4..4383c06 100644
--- a/frontend/src/pages/authenticated/Profile.tsx
+++ b/frontend/src/pages/authenticated/Profile.tsx
@@ -13,6 +13,10 @@ import { DateTimeDisplay } from "../../utils/formatDateTime";
import { getLocaleFromPathname, localizePath } from "../../utils/localeRouting";
import { getCountryOptions, getFlagUrl, normalizeCountryCode } from "../../utils/countries";
+const getProfileCountryCode = (profile: ProfileType | null) => {
+ return profile?.settings?.country_code ?? profile?.country_code ?? null;
+};
+
const Profile = () => {
const { t } = useTranslation();
const location = useLocation();
@@ -136,7 +140,7 @@ const Profile = () => {
if (!currentProfile) return;
setEditUsername(currentProfile.username);
setEditBio(currentProfile.bio ?? "");
- setEditCountryCode(currentProfile.country_code ?? "");
+ setEditCountryCode(getProfileCountryCode(currentProfile) ?? "");
setEditPhoto(null);
setEditPhotoPreview(null);
setSaveError(null);
@@ -188,7 +192,8 @@ const Profile = () => {
const avatarSrc = editPhotoPreview ?? currentProfile?.photo ?? null;
const avatarFallback = currentProfile?.username?.[0]?.toUpperCase() ?? "?";
- const profileFlagUrl = getFlagUrl(currentProfile?.country_code, 24);
+ const profileCountryCode = getProfileCountryCode(currentProfile);
+ const profileFlagUrl = getFlagUrl(profileCountryCode, 24);
return (
@@ -245,7 +250,7 @@ const Profile = () => {
{profileFlagUrl && (
From b52223017e6ee14ae852f1f0a47e908ad0bb9980 Mon Sep 17 00:00:00 2001
From: Stephen
Date: Mon, 20 Apr 2026 03:33:46 +0100
Subject: [PATCH 6/6] fix: correct country code retrieval logic in
getUserDefaultLocale function
---
frontend/src/App.tsx | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 5487eb6..86463d4 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -67,10 +67,10 @@ const getUserDefaultLocale = (): AppLocale => {
typeof parsedProfile.settings?.country_code === "string"
? parsedProfile.settings.country_code
: typeof parsedProfile.country_code === "string"
- ? parsedProfile.country_code
- : typeof parsedProfile.countryCode === "string"
- ? parsedProfile.countryCode
- : null;
+ ? parsedProfile.country_code
+ : typeof parsedProfile.countryCode === "string"
+ ? parsedProfile.countryCode
+ : null;
return resolveLocaleFromCountryCode(countryCode);
} catch {