PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
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 2.0.1 All 84 releases
← All changes | resources/js/lib/currency-display.ts +52 -17 3.0.13 → 3.0.16 View file →
@@ -94,31 +94,62 @@
94 94 "before"
95 95 );
96 96 }
97 97
98 -function readAdminNumberFormatConfig(): {
98 +function readYatraNumberFormatConfig(): {
99 99 decimalPlaces: number;
100 100 thousandSeparator: string;
101 101 decimalSeparator: string;
102 102 } {
103 + const fallback = {
104 + decimalPlaces: 2,
105 + thousandSeparator: ",",
106 + decimalSeparator: ".",
107 + };
103 108 if (typeof window === "undefined") {
104 - return { decimalPlaces: 2, thousandSeparator: ",", decimalSeparator: "." };
109 + return fallback;
105 110 }
106 - const a = ((window as AdminWindow).yatraAdmin || {}) as Record<
107 - string,
108 - unknown
109 - >;
110 - const decimals = Number(a.decimalPlaces ?? a.currency_decimals ?? 2) || 2;
111 + // Read from the SAME set of globals as the currency position, not just
112 + // yatraAdmin. On public pages (customer account, checkout, single trip)
113 + // window.yatraAdmin is absent, so reading separators only from it made the
114 + // decimal/thousand separators silently fall back to defaults ("." / ",")
115 + // while the position — read from these public globals — was correct. That is
116 + // the "decimal separator ignored in payment amounts" bug on the storefront.
117 + const w = window as AdminWindow;
118 + const sources: Array<Record<string, unknown> | undefined> = [
119 + w.yatraAdmin as Record<string, unknown> | undefined,
120 + w.yatraBookingData as Record<string, unknown> | undefined,
121 + w.yatraTripData as Record<string, unknown> | undefined,
122 + w.yatraAccountPage as Record<string, unknown> | undefined,
123 + ];
124 + const pickString = (field: string): string | undefined => {
125 + for (const o of sources) {
126 + const v = o?.[field];
127 + if (typeof v === "string" && v !== "") {
128 + return v;
129 + }
130 + }
131 + return undefined;
132 + };
133 + const pickNumber = (...fields: string[]): number | undefined => {
134 + for (const o of sources) {
135 + if (!o) {
136 + continue;
137 + }
138 + for (const field of fields) {
139 + const v = o[field];
140 + if (v !== undefined && v !== null && v !== "" && !Number.isNaN(Number(v))) {
141 + return Number(v);
142 + }
143 + }
144 + }
145 + return undefined;
146 + };
147 + const decimals = pickNumber("decimalPlaces", "currency_decimals") ?? 2;
111 148 return {
112 149 decimalPlaces: Math.max(0, Math.min(4, decimals)),
113 - thousandSeparator:
114 - typeof a.thousandSeparator === "string" && a.thousandSeparator !== ""
115 - ? (a.thousandSeparator as string)
116 - : ",",
117 - decimalSeparator:
118 - typeof a.decimalSeparator === "string" && a.decimalSeparator !== ""
119 - ? (a.decimalSeparator as string)
120 - : ".",
150 + thousandSeparator: pickString("thousandSeparator") ?? ",",
151 + decimalSeparator: pickString("decimalSeparator") ?? ".",
121 152 };
122 153 }
123 154
124 155 /**
@@ -137,9 +168,9 @@
137 168 return __("Contact for pricing", "yatra");
138 169 }
139 170
140 171 const { decimalPlaces, thousandSeparator, decimalSeparator } =
141 - readAdminNumberFormatConfig();
172 + readYatraNumberFormatConfig();
142 173 const currencyData = getCurrency(currencyCode);
143 174 const decimals =
144 175 currencyData?.decimalDigits !== undefined
145 176 ? Math.max(0, Math.min(4, currencyData.decimalDigits))
@@ -144,9 +175,13 @@
144 175 currencyData?.decimalDigits !== undefined
145 176 ? Math.max(0, Math.min(4, currencyData.decimalDigits))
146 177 : decimalPlaces;
147 178
148 - const formattedCore = new Intl.NumberFormat(undefined, {
179 + // Format with a FIXED "en-US" base (grouping ",", decimal ".") so the
180 + // replace-with-configured-separators step below is deterministic. Using the
181 + // viewer's locale here (undefined) would already yield locale separators and
182 + // the naive comma/dot replacement would swap them for e.g. German browsers.
183 + const formattedCore = new Intl.NumberFormat("en-US", {
149 184 minimumFractionDigits: decimals,
150 185 maximumFractionDigits: decimals,
151 186 })
152 187 .format(num)