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/i18n.ts +100 -2 3.0.3 → 3.0.16 View file →
@@ -6,10 +6,21 @@
6 6 declare global {
7 7 interface Window {
8 8 yatraAdmin?: {
9 9 apiUrl?: string;
10 + restUrl?: string;
10 11 nonce?: string;
11 12 brandLogoUrl?: string;
13 + /**
14 + * Operator-facing brand name. When the White Label module is
15 + * active (Agency-tier only) and the operator has filled in
16 + * "Plugin name" in WL settings, this is THAT value — otherwise
17 + * it's "Yatra". Use this everywhere instead of hardcoding
18 + * "Yatra" so the UI reflects the operator's brand for resellers.
19 + *
20 + * Injected by AdminAssetsProvider via `yatra_get_brand_name()`.
21 + */
22 + brandName?: string;
12 23 pluginUrl?: string;
13 24 currentUserAvatar?: string;
14 25 currentUser?: number;
15 26 siteUrl?: string;
@@ -16,8 +27,10 @@
16 27 permissions?: string[];
17 28 roles?: string[];
18 29 capabilities?: Record<string, boolean>;
19 30 isPro?: boolean;
31 + /** Yatra → Modules → Custom Landing Pages enabled (Pro). */
32 + customLandingPagesModuleEnabled?: boolean;
20 33 isProActive?: boolean;
21 34 version?: string;
22 35 proVersion?: string | null;
23 36 translations?: Record<string, string>;
@@ -22,13 +35,15 @@
22 35 proVersion?: string | null;
23 36 translations?: Record<string, string>;
24 37 locale?: string;
25 38 emailAutomationEnabled?: boolean;
39 + emailTemplateOverridesEnabled?: boolean;
26 40 tripConsentEnabled?: boolean;
27 41 additionalServicesEnabled?: boolean;
28 42 abandonedBookingRecoveryEnabled?: boolean;
29 43 dynamicPricingEnabled?: boolean;
30 44 dynamicFormFieldEnabled?: boolean;
45 + bookingFormConditionsEnabled?: boolean;
31 46 advancedDiscountEnabled?: boolean;
32 47 showGoogleCalendarSettingsUI?: boolean;
33 48 showMailchimpSettingsUI?: boolean;
34 49 showFacebookPixelSettingsUI?: boolean;
@@ -33,8 +48,19 @@
33 48 showMailchimpSettingsUI?: boolean;
34 49 showFacebookPixelSettingsUI?: boolean;
35 50 showGoogleAnalyticsSettingsUI?: boolean;
36 51 flexiblePaymentsEnabled?: boolean;
52 + // Growth + Agency tier modules — set by their respective Pro
53 + // modules via yatra_admin_localized_data filter, OR by the
54 + // free plugin's AdminAssetsProvider (canonical source via
55 + // ModuleManager::isModuleEnabled). useModules() also writes
56 + // these at runtime once /modules resolves.
57 + aiAssistantEnabled?: boolean;
58 + whiteLabelEnabled?: boolean;
59 + whatsappEnabled?: boolean;
60 + channelManagerEnabled?: boolean;
61 + webhooksEnabled?: boolean;
62 + scheduledPaymentsEnabled?: boolean;
37 63 currency?: string;
38 64 date_format?: string;
39 65 time_format?: string;
40 66 calendar_name?: string;
@@ -93,8 +119,33 @@
93 119 connected?: boolean;
94 120 redirect_uri?: string;
95 121 last_sync?: string | null;
96 122 };
123 + // Team & Access (Agency-tier) — injected by Team module's
124 + // LocalizedData service. Absent when module isn't installed.
125 + teamEnabled?: boolean;
126 + /**
127 + * Forward-looking "keep access on module disable" setting.
128 + * Only consulted when the Team & Access module is DISABLED:
129 + * - `false` (default): yatra_* caps are stripped for non-admin
130 + * users until the module is re-enabled.
131 + * - `true`: WP-native role machinery keeps resolving caps from
132 + * the stored role records — team members keep their access
133 + * even after disabling the module.
134 + *
135 + * When the module is enabled, this setting is irrelevant —
136 + * caps resolve normally through the full layered chain (admin
137 + * fallback, expiry, revoke, role, grant).
138 + */
139 + teamKeepAccessOnModuleDisable?: boolean;
140 + isWpAdmin?: boolean;
141 + userCaps?: string[];
142 + userScopes?: {
143 + destinations: number[];
144 + activities: number[];
145 + trips: number[];
146 + categories: number[];
147 + };
97 148 };
98 149 }
99 150 }
100 151
@@ -111,8 +162,26 @@
111 162
112 163 function __(key: string): string;
113 164 function __(key: string, textDomain: string): string;
114 165 function __(key: string, textDomain?: string): string {
166 + // If the frontend bootstrapped a translations map (e.g., account page),
167 + // use it as the highest priority source. This allows Loco Translate / PHP
168 + // string catalogs to power React UIs without requiring JS translation JSON files.
169 + if (typeof window !== "undefined") {
170 + const w = window as unknown as {
171 + yatraAccountPage?: { translations?: Record<string, string> };
172 + yatraAdmin?: { translations?: Record<string, string> };
173 + };
174 + const fromAccount = w.yatraAccountPage?.translations?.[key];
175 + if (typeof fromAccount === "string" && fromAccount !== "") {
176 + return fromAccount;
177 + }
178 + const fromAdmin = w.yatraAdmin?.translations?.[key];
179 + if (typeof fromAdmin === "string" && fromAdmin !== "") {
180 + return fromAdmin;
181 + }
182 + }
183 +
115 184 // Use direct WordPress i18n function which is working correctly
116 185 if (typeof window !== "undefined" && (window as any).wp?.i18n?.__) {
117 186 return (window as any).wp.i18n.__(key, textDomain || "yatra");
118 187 }
@@ -140,16 +209,45 @@
140 209 ...args,
141 210 );
142 211 }
143 212
144 -export { __, _x, sprintf };
213 +/**
214 + * Operator brand name — "Yatra" by default, or whatever the operator
215 + * has set in the White Label module (Agency tier).
216 + *
217 + * Use this in user-visible strings instead of hardcoding "Yatra":
218 + *
219 + * const brand = brandName();
220 + * sprintf(__("%s role", "yatra"), brand) // "Acme role" if rebranded
221 + *
222 + * Always pass the brand as an interpolated argument so the translatable
223 + * string stays generic — that keeps `make-pot` extraction working AND
224 + * means a translator only has to translate "%s role" once, regardless
225 + * of brand.
226 + */
227 +function brandName(): string {
228 + if (typeof window === "undefined") return "Yatra";
229 + return (window.yatraAdmin?.brandName as string | undefined) || "Yatra";
230 +}
145 231
232 +export { __, _x, sprintf, brandName };
233 +
146 234 /**
147 235 * Get translated string with number
148 236 * @param single - Single form
149 237 * @param plural - Plural form
150 238 * @param number - Number to determine form
239 + * @param textDomain - Optional text domain; accepted for API parity with
240 + * WordPress's own `_n()` so call sites that already pass
241 + * `"yatra"` as a fourth arg type-check. Currently
242 + * unused — `__()` does its own domain resolution via
243 + * the translations map injected on `window.yatraAdmin`.
151 244 * @returns Translated string
152 245 */
153 -export const _n = (single: string, plural: string, number: number): string => {
246 +export const _n = (
247 + single: string,
248 + plural: string,
249 + number: number,
250 + _textDomain?: string,
251 +): string => {
154 252 return number === 1 ? __(single) : __(plural);
155 253 };