PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.17
Yatra – Travel Booking & Tour Operator Software v3.0.17
3.0.17 3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 All 85 releases
← All changes | resources/js/pages/account/utils.ts +97 -21 3.0.3 → 3.0.17 View file →
@@ -2,30 +2,43 @@
2 2 import {
3 3 applyCurrencyPosition,
4 4 formatYatraMoney,
5 5 } from "../../lib/currency-display";
6 +import {
7 + formatDate as formatGlobalDate,
8 + parseDate,
9 +} from "../../lib/dateFormat";
6 10
11 +function toBrowserLocaleTag(
12 + locale: string | undefined | null,
13 +): string | undefined {
14 + const raw = String(locale || "").trim();
15 + if (!raw) return undefined;
16 + // WP locales are often like "en_US"; Intl expects BCP47 like "en-US".
17 + return raw.replace(/_/g, "-");
18 +}
19 +
20 +function getAccountLocale(): string | undefined {
21 + if (typeof window === "undefined") return undefined;
22 + const raw = (window as unknown as { yatraAccountPage?: { locale?: string } })
23 + .yatraAccountPage?.locale;
24 + return toBrowserLocaleTag(raw);
25 +}
26 +
7 27 export const formatDate = (value: string | undefined | null) => {
8 28 if (!value) {
9 29 return __("N/A", "yatra");
10 30 }
11 31
12 - try {
13 - const date = new Date(value);
14 -
15 - // Check if date is valid
16 - if (isNaN(date.getTime())) {
17 - return __("Invalid date", "yatra");
18 - }
19 -
20 - return date.toLocaleDateString(undefined, {
21 - year: "numeric",
22 - month: "long",
23 - day: "numeric",
24 - });
25 - } catch (error) {
32 + // Render public account dates in the operator's configured global date
33 + // format (Settings → General) via the shared formatter — not a hardcoded
34 + // browser style. It also parses a date-only value (e.g. a booking's
35 + // travel_date) in LOCAL time, so it no longer rolls back a day in behind-UTC
36 + // timezones (Aug 1 → Jul 31).
37 + if (!parseDate(value)) {
26 38 return __("Invalid date", "yatra");
27 39 }
40 + return formatGlobalDate(value);
28 41 };
29 42
30 43 /** Leading Y-m-d from API datetime strings for stable range comparison. */
31 44 function extractYmd(value: string | undefined | null): string | null {
@@ -31,9 +44,11 @@
31 44 function extractYmd(value: string | undefined | null): string | null {
32 45 if (!value) {
33 46 return null;
34 47 }
35 - const m = String(value).trim().match(/^(\d{4}-\d{2}-\d{2})/);
48 + const m = String(value)
49 + .trim()
50 + .match(/^(\d{4}-\d{2}-\d{2})/);
36 51 return m ? m[1] : null;
37 52 }
38 53
39 54 /**
@@ -52,8 +67,9 @@
52 67 if (!endKey || endKey === startKey) {
53 68 return formatDate(travelDate);
54 69 }
55 70 return sprintf(
71 + // translators: 1: start date, 2: end date. Joined with an en-dash for travel date ranges.
56 72 __("%1$s – %2$s", "yatra"),
57 73 formatDate(travelDate),
58 74 formatDate(endDate),
59 75 );
@@ -58,8 +74,62 @@
58 74 formatDate(endDate),
59 75 );
60 76 };
61 77
78 +/**
79 + * Translate a known booking/payment/ticket status to a localized label.
80 + *
81 + * The previous account-page code did `__(booking.status, booking.status)` which
82 + * mis-uses the textdomain argument: WP's i18n runtime treats the second arg as
83 + * the textdomain (defaulting to 'default'), so it never finds the translation
84 + * and silently returns the raw English key like 'confirmed'/'pending'. Worse,
85 + * because the first argument is a runtime variable, the WP-CLI i18n extractor
86 + * skips it — those strings never reach the .pot file and Loco never gets a
87 + * chance to translate them.
88 + *
89 + * Mapping each known status to a static `__('Foo', 'yatra')` call fixes both
90 + * problems at once: extractor sees the literals, translators can localize, and
91 + * unknown values fall back to a title-cased rendition of the raw key.
92 + */
93 +export const getStatusLabel = (status: string | undefined | null): string => {
94 + const raw = typeof status === "string" ? status.toLowerCase().trim() : "";
95 + switch (raw) {
96 + case "pending":
97 + return __("Pending", "yatra");
98 + case "confirmed":
99 + return __("Confirmed", "yatra");
100 + case "processing":
101 + return __("Processing", "yatra");
102 + case "completed":
103 + return __("Completed", "yatra");
104 + case "cancelled":
105 + return __("Cancelled", "yatra");
106 + case "refunded":
107 + return __("Refunded", "yatra");
108 + case "failed":
109 + return __("Failed", "yatra");
110 + case "on_hold":
111 + return __("On hold", "yatra");
112 + case "paid":
113 + return __("Paid", "yatra");
114 + case "partial":
115 + return __("Partial", "yatra");
116 + case "awaiting_response":
117 + return __("Awaiting response", "yatra");
118 + case "resolved":
119 + return __("Resolved", "yatra");
120 + case "closed":
121 + return __("Closed", "yatra");
122 + case "open":
123 + return __("Open", "yatra");
124 + case "":
125 + return __("Pending", "yatra");
126 + default:
127 + // Unknown status — title-case it so admins can see what's coming through.
128 + return raw.charAt(0).toUpperCase() + raw.slice(1).replace(/_/g, " ");
129 + }
130 +};
131 +
62 132 export const getBadge = (status: string | undefined | null) => {
63 133 const base = "px-2.5 py-0.5 rounded-full text-xs font-medium";
64 134
65 135 // Handle undefined/null/empty status
@@ -131,9 +201,9 @@
131 201 if (!price || price === 0) {
132 202 return __("Contact for pricing", "yatra");
133 203 }
134 204
135 - const formattedAmount = new Intl.NumberFormat(undefined, {
205 + const formattedAmount = new Intl.NumberFormat(getAccountLocale(), {
136 206 minimumFractionDigits: decimalPlaces,
137 207 maximumFractionDigits: decimalPlaces,
138 208 })
139 209 .format(price)
@@ -140,9 +210,9 @@
140 210 .replace(/,/g, "TEMP_THOUSAND")
141 211 .replace(/\./g, decimalSeparator)
142 212 .replace(/TEMP_THOUSAND/g, thousandSeparator);
143 213
144 - const currencySymbol = new Intl.NumberFormat(undefined, {
214 + const currencySymbol = new Intl.NumberFormat(getAccountLocale(), {
145 215 style: "currency",
146 216 currency: globalCurrency,
147 217 })
148 218 .format(0)
@@ -170,9 +240,9 @@
170 240
171 241 // Always format the price, even if 0 - don't show "Contact for pricing" for bookings
172 242 const numPrice = Number(price) || 0;
173 243
174 - const formattedAmount = new Intl.NumberFormat(undefined, {
244 + const formattedAmount = new Intl.NumberFormat(getAccountLocale(), {
175 245 minimumFractionDigits: decimalPlaces,
176 246 maximumFractionDigits: decimalPlaces,
177 247 })
178 248 .format(numPrice)
@@ -179,9 +249,9 @@
179 249 .replace(/,/g, "TEMP_THOUSAND")
180 250 .replace(/\./g, decimalSeparator)
181 251 .replace(/TEMP_THOUSAND/g, thousandSeparator);
182 252
183 - const currencySymbol = new Intl.NumberFormat(undefined, {
253 + const currencySymbol = new Intl.NumberFormat(getAccountLocale(), {
184 254 style: "currency",
185 255 currency: currencyToUse,
186 256 })
187 257 .format(0)
@@ -194,10 +264,13 @@
194 264 currencyPosition,
195 265 );
196 266 };
197 267
198 -export const currency = (value: number, currencyCode: string = "USD") =>
199 - formatYatraMoney(Number(value) || 0, currencyCode, { zeroAsUnknown: false });
268 +export const currency = (value: number, currencyCode?: string) => {
269 + const cfg = readPriceConfig();
270 + const code = (currencyCode || cfg.globalCurrency || "USD") as string;
271 + return formatYatraMoney(Number(value) || 0, code, { zeroAsUnknown: false });
272 +};
200 273
201 274 /** Values from `wp_localize_script(…, 'yatraAccountPage', …)` on the account page. */
202 275 export function getYatraAccountPageGlobals(): {
203 276 logoutUrl: string;
@@ -203,8 +276,9 @@
203 276 logoutUrl: string;
204 277 companyPhone: string;
205 278 companyName: string;
206 279 companyEmail: string;
280 + locale: string;
207 281 } {
208 282 if (typeof window === "undefined") {
209 283 return {
210 284 logoutUrl: "",
@@ -210,8 +284,9 @@
210 284 logoutUrl: "",
211 285 companyPhone: "",
212 286 companyName: "",
213 287 companyEmail: "",
288 + locale: "",
214 289 };
215 290 }
216 291 const p = (window as unknown as { yatraAccountPage?: Record<string, string> })
217 292 .yatraAccountPage;
@@ -220,8 +295,9 @@
220 295 logoutUrl: String(raw.logoutUrl || "").trim(),
221 296 companyPhone: String(raw.companyPhone || "").trim(),
222 297 companyName: String(raw.companyName || "").trim(),
223 298 companyEmail: String(raw.companyEmail || "").trim(),
299 + locale: String((raw as any).locale || "").trim(),
224 300 };
225 301 }
226 302
227 303 export function phoneToTelHref(phone: string): string {