@mindful-web/marko-web-theme-monorail 1.80.2 → 1.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/I18N_GUIDE.md +354 -0
  2. package/README.md +8 -0
  3. package/components/ads/fixed-ad-bottom.marko.js +2 -2
  4. package/components/ads/reveal-ad-handler.marko.js +2 -2
  5. package/components/blocks/author-bios.marko.js +2 -2
  6. package/components/blocks/callout-cards.marko.js +2 -2
  7. package/components/blocks/company-inquiry-form.marko.js +2 -2
  8. package/components/blocks/company-search.marko.js +2 -2
  9. package/components/blocks/content-card-deck.marko.js +2 -2
  10. package/components/blocks/content-meter.marko +27 -9
  11. package/components/blocks/content-meter.marko.js +29 -10
  12. package/components/blocks/full-width-native-ad.marko.js +2 -2
  13. package/components/blocks/geo-summary.marko.js +2 -2
  14. package/components/blocks/header-announcement.marko.js +2 -2
  15. package/components/blocks/hero-card.marko.js +2 -2
  16. package/components/blocks/latest-content-list.marko.js +2 -2
  17. package/components/blocks/latest-podcast.marko.js +2 -2
  18. package/components/blocks/latest-products-feed.marko.js +2 -2
  19. package/components/blocks/more-products.marko.js +2 -2
  20. package/components/blocks/most-popular-list.marko.js +2 -2
  21. package/components/blocks/most-popular.marko.js +2 -2
  22. package/components/blocks/native-x-card-deck.marko.js +2 -2
  23. package/components/blocks/native-x-promo-card.marko.js +2 -2
  24. package/components/blocks/newsletter-signup-banner-external.marko.js +2 -2
  25. package/components/blocks/newsletter-signup-banner-large.marko.js +2 -2
  26. package/components/blocks/newsletter-signup-banner.marko.js +2 -2
  27. package/components/blocks/opinion.marko.js +2 -2
  28. package/components/blocks/primary-image.marko.js +2 -2
  29. package/components/blocks/products.marko.js +2 -2
  30. package/components/blocks/read-next.marko.js +2 -2
  31. package/components/blocks/related-stories.marko.js +2 -2
  32. package/components/blocks/resource-library.marko.js +2 -2
  33. package/components/blocks/section-body-feed.marko.js +2 -2
  34. package/components/blocks/section-card-deck-featured.marko.js +2 -2
  35. package/components/blocks/section-card-deck.marko.js +2 -2
  36. package/components/blocks/section-card-list.marko.js +2 -2
  37. package/components/blocks/section-feed.marko.js +2 -2
  38. package/components/blocks/section-forbes.marko.js +2 -2
  39. package/components/blocks/section-list-deck.marko.js +2 -2
  40. package/components/blocks/section-list.marko.js +2 -2
  41. package/components/blocks/section-search.marko.js +2 -2
  42. package/components/blocks/section-title-feed.marko.js +2 -2
  43. package/components/blocks/top-stories-menu.marko.js +2 -2
  44. package/components/blocks/top-stories.marko.js +2 -2
  45. package/components/blocks/white-papers.marko.js +2 -2
  46. package/components/breadcrumbs/content-page.marko.js +2 -2
  47. package/components/breadcrumbs/index.marko.js +2 -2
  48. package/components/breadcrumbs/website-section.marko.js +2 -2
  49. package/components/breadcrumbs/with-home.marko.js +2 -2
  50. package/components/client-side-block-loader.marko.js +2 -2
  51. package/components/client-side-blocks/most-popular-list.marko.js +2 -2
  52. package/components/client-side-blocks/most-popular.marko.js +2 -2
  53. package/components/content/body-with-injection.marko.js +2 -2
  54. package/components/content/contact-details/index.marko.js +2 -2
  55. package/components/content/contact-details/section.marko.js +2 -2
  56. package/components/content/download/form-dot-com.marko.js +2 -2
  57. package/components/content/download/identity-x.marko.js +2 -2
  58. package/components/content/download/index.marko.js +2 -2
  59. package/components/content/download/link.marko.js +2 -2
  60. package/components/content/download/wufoo.marko.js +2 -2
  61. package/components/content/link-url/index.marko.js +2 -2
  62. package/components/content/sections-listed-in.marko.js +2 -2
  63. package/components/content-attribution/attribution.marko.js +2 -2
  64. package/components/content-attribution/components/authors.marko.js +2 -2
  65. package/components/content-attribution/components/byline.marko.js +2 -2
  66. package/components/content-attribution/components/company.marko.js +2 -2
  67. package/components/content-attribution/components/contributors.marko.js +2 -2
  68. package/components/content-attribution/components/photographers.marko.js +2 -2
  69. package/components/content-attribution/components/source.marko.js +2 -2
  70. package/components/content-attribution/components/speakers.marko.js +2 -2
  71. package/components/content-attribution/components/sponsors.marko.js +2 -2
  72. package/components/content-attribution/index.marko.js +2 -2
  73. package/components/directory-facets/facet-container/facet-container.marko.js +2 -2
  74. package/components/directory-facets/facet-list/facet-list.marko.js +2 -2
  75. package/components/directory-facets/facet.marko.js +2 -2
  76. package/components/directory-facets/index.marko.js +2 -2
  77. package/components/facebook-connect.marko.js +2 -2
  78. package/components/flows/card-deck.marko.js +2 -2
  79. package/components/flows/content/card-deck-col.marko.js +2 -2
  80. package/components/flows/content/directory-section.marko.js +2 -2
  81. package/components/flows/content/list.marko.js +2 -2
  82. package/components/flows/section-feed.marko.js +2 -2
  83. package/components/gam/components/define-display-ad.marko.js +2 -2
  84. package/components/gam/define-display-ad.marko.js +2 -2
  85. package/components/gam/inject-ads.marko.js +2 -2
  86. package/components/gam/wallpaper-ad.marko.js +2 -2
  87. package/components/identity-x/comment-stream.marko.js +2 -2
  88. package/components/identity-x/content-page-gate.marko.js +2 -2
  89. package/components/identity-x/newsletter-footer.marko.js +2 -2
  90. package/components/identity-x/newsletter-inline.marko.js +2 -2
  91. package/components/identity-x/newsletter-modal.marko.js +2 -2
  92. package/components/identity-x/newsletter-pushdown.marko.js +2 -2
  93. package/components/layouts/ad-preview.marko.js +2 -2
  94. package/components/menu-toggle-button.marko.js +2 -2
  95. package/components/native-x/render.marko.js +2 -2
  96. package/components/nodes/author-bio.marko.js +2 -2
  97. package/components/nodes/author-card.marko.js +2 -2
  98. package/components/nodes/author-published.marko.js +2 -2
  99. package/components/nodes/author.marko.js +2 -2
  100. package/components/nodes/components/attribution.marko.js +2 -2
  101. package/components/nodes/components/authors.marko.js +2 -2
  102. package/components/nodes/components/company-name.marko.js +2 -2
  103. package/components/nodes/components/dates.marko.js +2 -2
  104. package/components/nodes/components/section-sponsor.marko.js +2 -2
  105. package/components/nodes/content-published.marko.js +2 -2
  106. package/components/nodes/content.marko.js +2 -2
  107. package/components/nodes/directory-section-feed-content.marko.js +2 -2
  108. package/components/nodes/featured-products-card.marko.js +2 -2
  109. package/components/nodes/product-feed-content.marko.js +2 -2
  110. package/components/nodes/section-feed-content.marko.js +2 -2
  111. package/components/nodes/standard-promo.marko.js +2 -2
  112. package/components/nodes/youtube-card.marko.js +2 -2
  113. package/components/page/attribution.marko.js +2 -2
  114. package/components/page/contact-details.marko.js +2 -2
  115. package/components/page/content.marko.js +2 -2
  116. package/components/page/contents.marko.js +2 -2
  117. package/components/page/dates.marko.js +2 -2
  118. package/components/page/default.marko.js +2 -2
  119. package/components/page/website-section.marko.js +2 -2
  120. package/components/pagination-controls.marko.js +2 -2
  121. package/components/query-total-count.marko.js +2 -2
  122. package/components/reveal-ad-handler.marko.js +2 -2
  123. package/components/site-footer/container.marko.js +2 -2
  124. package/components/site-footer/copyright.marko.js +2 -2
  125. package/components/site-footer/index.marko.js +2 -2
  126. package/components/site-footer/social-icons.marko.js +2 -2
  127. package/components/site-header.marko.js +2 -2
  128. package/components/site-menu/components/search.marko.js +2 -2
  129. package/components/site-menu/components/social-icons.marko.js +2 -2
  130. package/components/site-menu/header.marko.js +2 -2
  131. package/components/site-menu/index.marko.js +2 -2
  132. package/components/site-menu/section.marko.js +2 -2
  133. package/components/site-navbar/brand.marko.js +2 -2
  134. package/components/site-navbar/index.marko.js +2 -2
  135. package/components/site-navbar/item.marko.js +2 -2
  136. package/components/site-navbar/items.marko.js +2 -2
  137. package/components/site-navbar/logo.marko.js +2 -2
  138. package/components/site-navbar/search.marko.js +2 -2
  139. package/components/site-newsletter-menu.marko.js +2 -2
  140. package/components/social/icon-link.marko.js +2 -2
  141. package/components/social/icons.marko.js +2 -2
  142. package/components/social-follow.marko.js +2 -2
  143. package/components/sponsored-label-logo.marko.js +2 -2
  144. package/components/sponsored-section-logo.marko.js +2 -2
  145. package/components/sponsored-section-name-logo.marko.js +2 -2
  146. package/components/ssr-html-inject.marko.js +2 -2
  147. package/package.json +4 -4
  148. package/templates/ad-preview.marko.js +2 -2
  149. package/templates/content/components/presented-by.marko.js +2 -2
  150. package/templates/content/native-x-story.marko.js +2 -2
  151. package/templates/content/print.marko.js +2 -2
  152. package/templates/email-preview.marko.js +2 -2
  153. package/templates/search.marko.js +2 -2
  154. package/templates/taxonomy.marko.js +2 -2
package/I18N_GUIDE.md ADDED
@@ -0,0 +1,354 @@
1
+ # Internationalization (i18n) Guide
2
+
3
+ ## Overview
4
+
5
+ `marko-web-theme-monorail` supports internationalization through an `i18n` function that must be provided by consuming sites. This guide explains how the theme handles translations and how to contribute components that respect multilingual requirements.
6
+
7
+ ## Core Principle
8
+
9
+ **Any hardcoded user-facing text in theme components MUST be wrapped with the i18n function.** This ensures sites can translate UI text without modifying the theme package itself.
10
+
11
+ ---
12
+
13
+ ## How It Works
14
+
15
+ ### For Sites (Consuming Projects)
16
+
17
+ Sites provide an i18n function that maps English strings to their translated equivalents:
18
+
19
+ **Example: `sites/mundopmmi.com/config/i18n.js`**
20
+ ```javascript
21
+ module.exports = {
22
+ "We hope you've enjoyed your articles.": "Esperamos haya disfrutado sus artículos.",
23
+ "Create a free account": "Cree una cuenta gratuita",
24
+ "account to continue reading": "cuenta gratuita para continuar leyendo",
25
+ // ... hundreds more translations
26
+ };
27
+ ```
28
+
29
+ Then in the site's start-server call:
30
+ ```javascript
31
+ // sites/mundopmmi.com/index.js
32
+ const i18n = require('./config/i18n');
33
+
34
+ module.exports = startServer({
35
+ // ... config ...
36
+ i18n: (v) => i18n[`${v}`.toLowerCase()] || v,
37
+ });
38
+ ```
39
+
40
+ This makes `out.global.i18n` available to all theme components.
41
+
42
+ ### For Theme Components
43
+
44
+ #### Marko Components (Server-side)
45
+
46
+ 1. **Destructure i18n with a fallback:**
47
+ ```marko
48
+ $ const { i18n } = out.global;
49
+ $ const i18nFunc = typeof i18n === 'function' ? i18n : (v) => v;
50
+ ```
51
+
52
+ 2. **Wrap user-facing strings:**
53
+ ```marko
54
+ $ const title = i18nFunc("We hope you've enjoyed your articles.");
55
+ $ const buttonLabel = i18nFunc("Create a free account");
56
+ ```
57
+
58
+ 3. **Handle dynamic content carefully:**
59
+ ```marko
60
+ // For singular/plural variants:
61
+ $ const remaining = viewLimit - views;
62
+ $ let message;
63
+ $ if (remaining === 1) {
64
+ $ message = i18nFunc("You have 1 article view remaining.");
65
+ $ } else {
66
+ $ // Use placeholder for numbers
67
+ $ message = i18nFunc("You have {count} article views remaining.");
68
+ $ message = message.replace('{count}', remaining);
69
+ $ }
70
+ ```
71
+
72
+ #### Vue/Browser Components (Client-side)
73
+
74
+ For client-side Vue components, translations must be passed as props from the Marko template:
75
+
76
+ **In Marko template:**
77
+ ```marko
78
+ $ const { i18n } = out.global;
79
+ $ const i18nFunc = typeof i18n === 'function' ? i18n : (v) => v;
80
+
81
+ $ const locale = {
82
+ "Sign up": i18nFunc("Sign up"),
83
+ "Email address": i18nFunc("Email address"),
84
+ "Subscribe": i18nFunc("Subscribe"),
85
+ };
86
+
87
+ <marko-web-browser-component
88
+ name="InlineNewsletterForm"
89
+ props={ locale, defaultNewsletter, ... }
90
+ />
91
+ ```
92
+
93
+ **In Vue component:**
94
+ ```vue
95
+ <template>
96
+ <form @submit="onSubmit">
97
+ <label>{{ locale['Email address'] || 'Email address' }}</label>
98
+ <input type="email" placeholder="user@example.com" />
99
+ <button type="submit">{{ locale['Subscribe'] || 'Subscribe' }}</button>
100
+ </form>
101
+ </template>
102
+
103
+ <script>
104
+ export default {
105
+ props: {
106
+ locale: {
107
+ type: Object,
108
+ default: () => ({}),
109
+ },
110
+ },
111
+ methods: {
112
+ onSubmit() {
113
+ // ...
114
+ },
115
+ },
116
+ }
117
+ </script>
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Best Practices
123
+
124
+ ### 1. Use Simple, Descriptive English Strings
125
+
126
+ ✅ **Good:**
127
+ ```marko
128
+ $ const label = i18nFunc("Create a free account");
129
+ ```
130
+
131
+ ❌ **Bad:**
132
+ ```marko
133
+ $ const label = i18nFunc("Create Account"); // Too vague, hard to translate consistently
134
+ ```
135
+
136
+ ### 2. Avoid Inline Interpolation with Numbers
137
+
138
+ ✅ **Good:**
139
+ ```marko
140
+ $ const template = i18nFunc("You have {count} article views remaining.");
141
+ $ const message = template.replace('{count}', remaining);
142
+ ```
143
+
144
+ ❌ **Bad:**
145
+ ```marko
146
+ $ const message = i18nFunc(`You have ${remaining} article views remaining.`);
147
+ // Translators can't translate this—the number is embedded
148
+ ```
149
+
150
+ ### 3. Keep Related Strings Together
151
+
152
+ ✅ **Good:**
153
+ ```marko
154
+ $ const createLabel = i18nFunc("Create a free");
155
+ $ const accountLabel = i18nFunc("account to continue reading");
156
+ $ const message = `${createLabel} <strong>${siteName}</strong> ${accountLabel}`;
157
+ ```
158
+
159
+ This allows translators to reorder the sentence structure if needed.
160
+
161
+ ❌ **Bad:**
162
+ ```marko
163
+ $ const message = i18nFunc(`Create a free ${siteName} account to continue reading`);
164
+ ```
165
+
166
+ ### 4. Always Provide a Fallback
167
+
168
+ Always check if i18n exists and fall back to English:
169
+
170
+ ```marko
171
+ $ const i18nFunc = typeof i18n === 'function' ? i18n : (v) => v;
172
+ $ const label = i18nFunc("Your label");
173
+ // If i18n doesn't exist, label will be "Your label" (English)
174
+ ```
175
+
176
+ This ensures backward compatibility with sites that don't have an i18n config.
177
+
178
+ ### 5. Document Required Translation Strings
179
+
180
+ When adding new user-facing text, document it in the component or in a comment:
181
+
182
+ ```marko
183
+ <!--
184
+ Required translation strings for this component:
185
+ - "We hope you've enjoyed your articles."
186
+ - "You have 1 article view remaining."
187
+ - "You have {count} article views remaining."
188
+ - "This is your last free article."
189
+ - "Enjoy this free article."
190
+ - "Create a free account"
191
+ - "Create a free"
192
+ - "account to continue reading"
193
+ -->
194
+ ```
195
+
196
+ Or add a comment in your PR describing what strings need to be added to site i18n configs.
197
+
198
+ ---
199
+
200
+ ## Example: Adding i18n to a Component
201
+
202
+ ### Before (No i18n)
203
+ ```marko
204
+ $ const title = "View All Products";
205
+ $ const emptyMessage = "No products found.";
206
+
207
+ <div class="products">
208
+ <h2>${title}</h2>
209
+ <if(!products.length)>
210
+ <p>${emptyMessage}</p>
211
+ </if>
212
+ </div>
213
+ ```
214
+
215
+ ### After (With i18n)
216
+ ```marko
217
+ $ const { i18n } = out.global;
218
+ $ const i18nFunc = typeof i18n === 'function' ? i18n : (v) => v;
219
+
220
+ $ const title = i18nFunc("View All Products");
221
+ $ const emptyMessage = i18nFunc("No products found.");
222
+
223
+ <div class="products">
224
+ <h2>${title}</h2>
225
+ <if(!products.length)>
226
+ <p>${emptyMessage}</p>
227
+ </if>
228
+ </div>
229
+ ```
230
+
231
+ ### Site Implementation
232
+ Sites using the component add translations to their i18n config:
233
+
234
+ ```javascript
235
+ // sites/example-spanish/config/i18n.js
236
+ module.exports = {
237
+ "View All Products": "Ver Todos los Productos",
238
+ "No products found.": "No se encontraron productos.",
239
+ };
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Handling Missing Translations
245
+
246
+ If a site doesn't have a translation in its i18n config, the fallback behavior is:
247
+
248
+ ```javascript
249
+ // sites/example-spanish/config/i18n.js
250
+ i18n: (v) => i18n[`${v}`.toLowerCase()] || v
251
+ // ^ returns English if not found
252
+ ```
253
+
254
+ This means:
255
+ - ✅ Sites will display in English if a translation is missing
256
+ - ✅ No runtime errors
257
+ - ✅ Graceful degradation
258
+ - ⚠️ Encourages sites to keep their i18n configs up-to-date with new theme versions
259
+
260
+ ---
261
+
262
+ ## Release Notes Template
263
+
264
+ When releasing a new version with i18n changes, include:
265
+
266
+ ```markdown
267
+ ## vX.Y.Z
268
+
269
+ ### New Features
270
+ - Added internationalization support to `content-meter` block component
271
+
272
+ ### i18n Changes (⚠️ Action Required for Multilingual Sites)
273
+ The following new translation strings are required:
274
+
275
+ **content-meter.marko:**
276
+ - `We hope you've enjoyed your articles.`
277
+ - `You have 1 article view remaining.`
278
+ - `You have {count} article views remaining.`
279
+ - `This is your last free article.`
280
+ - `Enjoy this free article.`
281
+ - `Create a free account`
282
+ - `Create a free`
283
+ - `account to continue reading`
284
+
285
+ **Action:** Add these strings to your site's `config/i18n.js` file and provide translations.
286
+
287
+ See [I18N_GUIDE.md](./I18N_GUIDE.md) for details.
288
+ ```
289
+
290
+ ---
291
+
292
+ ## Common Questions
293
+
294
+ ### Q: What if my site doesn't have multilingual requirements?
295
+ A: You don't need to do anything. The i18n function is optional, and the theme will fall back to English text automatically.
296
+
297
+ ### Q: Can I override a translation string in my site?
298
+ A: Yes. Your site's i18n config is the source of truth. Add (or modify) a translation string and it will be used instead of the theme's default English.
299
+
300
+ ### Q: Should all text go through i18n, or just user-facing labels?
301
+ A: Only **user-facing text** should be translated. Technical strings (class names, data attributes, IDs, etc.) should not.
302
+
303
+ ✅ Translate:
304
+ - Button labels
305
+ - Form placeholders
306
+ - Error messages
307
+ - Section titles
308
+ - Empty state messages
309
+
310
+ ❌ Don't translate:
311
+ - CSS class names
312
+ - Data attributes
313
+ - HTML IDs
314
+ - Variable names
315
+ - Code comments
316
+
317
+ ### Q: What about accessibility strings (aria-labels)?
318
+ A: Yes, translate these too. They're user-facing for screen readers.
319
+
320
+ ```marko
321
+ $ const ariaLabel = i18nFunc("Content Meter");
322
+ <div role="region" aria-label=ariaLabel>...</div>
323
+ ```
324
+
325
+ ### Q: How do I handle pluralization in other languages?
326
+ A: Use placeholder strings and handle pluralization at the template level:
327
+
328
+ ```marko
329
+ $ const count = items.length;
330
+ $ let message;
331
+ $ if (count === 0) {
332
+ $ message = i18nFunc("No items");
333
+ $ } else if (count === 1) {
334
+ $ message = i18nFunc("1 item");
335
+ $ } else {
336
+ $ message = i18nFunc("{count} items").replace('{count}', count);
337
+ $ }
338
+ ```
339
+
340
+ Then sites provide translations for each variant:
341
+ ```javascript
342
+ {
343
+ "No items": "Sin artículos",
344
+ "1 item": "1 artículo",
345
+ "{count} items": "{count} artículos",
346
+ }
347
+ ```
348
+
349
+ ---
350
+
351
+ ## References
352
+
353
+ - [marko-web-theme-monorail Repository](https://github.com/parameter1/mindful-web/tree/main/packages/marko-web-theme-monorail)
354
+ - [Consuming Site Example: mundopmmi](https://github.com/parameter1/pmmi-media-group-websites/tree/main/sites/mundopmmi.com)
package/README.md CHANGED
@@ -101,3 +101,11 @@ $ let body = content.body;
101
101
  $ // ...
102
102
 
103
103
  ```
104
+
105
+ ## Internationalization (i18n)
106
+
107
+ This theme supports internationalization for components. See [I18N_GUIDE.md](./I18N_GUIDE.md) for:
108
+ - How to add i18n support to new components
109
+ - Best practices for translatable strings
110
+ - Examples for both Marko and Vue components
111
+ - Common questions and answers
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/ads/fixed-ad-bottom.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/ads/fixed-ad-bottom.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  marko_assign = require("marko/dist/runtime/helpers/assign"),
8
8
  marko_web_gam_fixed_ad_bottom_template = require("@mindful-web/marko-web-gam/components/fixed-ad-bottom.marko"),
@@ -29,7 +29,7 @@ marko_template._ = marko_renderer(render, {
29
29
  });
30
30
 
31
31
  marko_template.meta = {
32
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/ads/fixed-ad-bottom.marko",
32
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/ads/fixed-ad-bottom.marko",
33
33
  tags: [
34
34
  "@mindful-web/marko-web-gam/components/fixed-ad-bottom.marko"
35
35
  ]
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/ads/reveal-ad-handler.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/ads/reveal-ad-handler.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  marko_web_browser_component_template = require("@mindful-web/marko-web/components/browser-component.marko"),
8
8
  marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
@@ -31,7 +31,7 @@ marko_template._ = marko_renderer(render, {
31
31
  });
32
32
 
33
33
  marko_template.meta = {
34
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/ads/reveal-ad-handler.marko",
34
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/ads/reveal-ad-handler.marko",
35
35
  tags: [
36
36
  "@mindful-web/marko-web/components/browser-component.marko"
37
37
  ]
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/author-bios.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/author-bios.marko",
6
6
  marko_component = require("./author-bios.marko"),
7
7
  marko_renderer = require("marko/dist/runtime/components/renderer"),
8
8
  module_defaultValue = require("@mindful-web/marko-core/utils/default-value"),
@@ -67,7 +67,7 @@ marko_template._ = marko_renderer(render, {
67
67
  }, marko_component);
68
68
 
69
69
  marko_template.meta = {
70
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/author-bios.marko",
70
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/author-bios.marko",
71
71
  component: "./author-bios.marko",
72
72
  tags: [
73
73
  "../nodes/author-bio.marko",
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/callout-cards.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/callout-cards.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  module_objectPath_module = require("@mindful-web/object-path"),
8
8
  objectPath_module = module_objectPath_module.default || module_objectPath_module,
@@ -66,7 +66,7 @@ marko_template._ = marko_renderer(render, {
66
66
  });
67
67
 
68
68
  marko_template.meta = {
69
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/callout-cards.marko",
69
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/callout-cards.marko",
70
70
  tags: [
71
71
  "@mindful-web/marko-web/components/element/index.marko",
72
72
  "@mindful-web/marko-web/components/element/block.marko"
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/company-inquiry-form.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/company-inquiry-form.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  module_defaultValue = require("@mindful-web/marko-core/utils/default-value"),
8
8
  defaultValue = module_defaultValue.default || module_defaultValue,
@@ -83,7 +83,7 @@ marko_template._ = marko_renderer(render, {
83
83
  });
84
84
 
85
85
  marko_template.meta = {
86
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/company-inquiry-form.marko",
86
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/company-inquiry-form.marko",
87
87
  tags: [
88
88
  "@mindful-web/marko-web/components/browser-component.marko",
89
89
  "@mindful-web/marko-web-p1-events/components/track-inquiry-submission.marko",
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/company-search.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/company-search.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  marko_web_browser_component_template = require("@mindful-web/marko-web/components/browser-component.marko"),
8
8
  marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
@@ -22,7 +22,7 @@ marko_template._ = marko_renderer(render, {
22
22
  });
23
23
 
24
24
  marko_template.meta = {
25
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/company-search.marko",
25
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/company-search.marko",
26
26
  tags: [
27
27
  "@mindful-web/marko-web/components/browser-component.marko"
28
28
  ]
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/content-card-deck.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/content-card-deck.marko",
6
6
  marko_component = require("./content-card-deck.marko"),
7
7
  marko_renderer = require("marko/dist/runtime/components/renderer"),
8
8
  module_utils_module = require("@mindful-web/marko-web/utils"),
@@ -317,7 +317,7 @@ marko_template._ = marko_renderer(render, {
317
317
  }, marko_component);
318
318
 
319
319
  marko_template.meta = {
320
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/content-card-deck.marko",
320
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/content-card-deck.marko",
321
321
  component: "./content-card-deck.marko",
322
322
  tags: [
323
323
  "@mindful-web/marko-web/components/element/link.marko",
@@ -1,7 +1,7 @@
1
1
  import defaultValue from "@mindful-web/marko-core/utils/default-value";
2
2
  import baseContentEntity from "@mindful-web/marko-web-p1-events/utils/base-content-entity";
3
3
 
4
- $ const { config, site, contentMeterState, req } = out.global;
4
+ $ const { config, site, contentMeterState, req, i18n } = out.global;
5
5
  $ const { content } = input;
6
6
  $ const {
7
7
  displayGate,
@@ -24,20 +24,38 @@ $ const additionalEventData = {
24
24
  ...(contentEntity && { ent: contentEntity }),
25
25
  };
26
26
 
27
-
27
+ // Fallback to identity function if i18n is not available (backward compatibility)
28
+ $ const i18nFunc = typeof i18n === ‘function’ ? i18n : (v) => v;
28
29
 
29
30
  $ const setTextVariables = () => {
30
31
  // Set title based on views remaining
31
- let dynamicTitle = defaultValue(input.dynamicTitle, "We hope you’ve enjoyed your articles.");
32
- if (views < viewLimit) dynamicTitle = `You have ${viewLimit - views} article views remaining.`;
33
- if (viewLimit - views === 1) dynamicTitle = `You have 1 article view remaining.`;
34
- if (viewLimit === views && !displayOverlay) dynamicTitle = `This is your last free article.`;
35
- if (viewLimit === 1 && !displayOverlay) dynamicTitle = 'Enjoy this free article.';
32
+ let dynamicTitle = defaultValue(
33
+ input.dynamicTitle,
34
+ i18nFunc("We hope you’ve enjoyed your articles.")
35
+ );
36
+
37
+ if (views < viewLimit) {
38
+ const remaining = viewLimit - views;
39
+ if (remaining === 1) {
40
+ dynamicTitle = i18nFunc("You have 1 article view remaining.");
41
+ } else {
42
+ const template = i18nFunc("You have {count} article views remaining.");
43
+ dynamicTitle = template.replace(‘{count}’, remaining);
44
+ }
45
+ }
46
+
47
+ if (viewLimit === views && !displayOverlay) {
48
+ dynamicTitle = i18nFunc("This is your last free article.");
49
+ }
50
+
51
+ if (viewLimit === 1 && !displayOverlay) {
52
+ dynamicTitle = i18nFunc("Enjoy this free article.");
53
+ }
36
54
 
37
55
  return {
38
56
  title: dynamicTitle,
39
- collapsedTitle: "Create a free account",
40
- callToAction: `Create a free <span class="content-meter__call-to-action--site-name">${config.siteName()}</span> account to continue reading`,
57
+ collapsedTitle: i18nFunc("Create a free account"),
58
+ callToAction: `${i18nFunc("Create a free")} <span class="content-meter__call-to-action--site-name">${config.siteName()}</span> ${i18nFunc("account to continue reading")}`,
41
59
  };
42
60
  }
43
61
  $ const textVariables = setTextVariables();
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/content-meter.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/content-meter.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  module_defaultValue = require("@mindful-web/marko-core/utils/default-value"),
8
8
  defaultValue = module_defaultValue.default || module_defaultValue,
@@ -21,7 +21,7 @@ var marko_template = module.exports = require("marko/dist/html").t(__filename),
21
21
  function render(input, out, __component, component, state) {
22
22
  var data = input;
23
23
 
24
- const { config, site, contentMeterState, req } = out.global;
24
+ const { config, site, contentMeterState, req, i18n } = out.global;
25
25
 
26
26
  const { content } = input;
27
27
 
@@ -46,18 +46,37 @@ function render(input, out, __component, component, state) {
46
46
  ...(contentEntity && { ent: contentEntity }),
47
47
  };
48
48
 
49
+ const i18nFunc = typeof i18n === ‘function’ ? i18n : (v) => v;
50
+
49
51
  const setTextVariables = () => {
50
52
  // Set title based on views remaining
51
- let dynamicTitle = defaultValue(input.dynamicTitle, "We hope you’ve enjoyed your articles.");
52
- if (views < viewLimit) dynamicTitle = `You have ${viewLimit - views} article views remaining.`;
53
- if (viewLimit - views === 1) dynamicTitle = `You have 1 article view remaining.`;
54
- if (viewLimit === views && !displayOverlay) dynamicTitle = `This is your last free article.`;
55
- if (viewLimit === 1 && !displayOverlay) dynamicTitle = 'Enjoy this free article.';
53
+ let dynamicTitle = defaultValue(
54
+ input.dynamicTitle,
55
+ i18nFunc("We hope you’ve enjoyed your articles.")
56
+ );
57
+
58
+ if (views < viewLimit) {
59
+ const remaining = viewLimit - views;
60
+ if (remaining === 1) {
61
+ dynamicTitle = i18nFunc("You have 1 article view remaining.");
62
+ } else {
63
+ const template = i18nFunc("You have {count} article views remaining.");
64
+ dynamicTitle = template.replace(‘{count}’, remaining);
65
+ }
66
+ }
67
+
68
+ if (viewLimit === views && !displayOverlay) {
69
+ dynamicTitle = i18nFunc("This is your last free article.");
70
+ }
71
+
72
+ if (viewLimit === 1 && !displayOverlay) {
73
+ dynamicTitle = i18nFunc("Enjoy this free article.");
74
+ }
56
75
 
57
76
  return {
58
77
  title: dynamicTitle,
59
- collapsedTitle: "Create a free account",
60
- callToAction: `Create a free <span class="content-meter__call-to-action--site-name">${config.siteName()}</span> account to continue reading`,
78
+ collapsedTitle: i18nFunc("Create a free account"),
79
+ callToAction: `${i18nFunc("Create a free")} <span class="content-meter__call-to-action--site-name">${config.siteName()}</span> ${i18nFunc("account to continue reading")}`,
61
80
  };
62
81
  }
63
82
 
@@ -135,7 +154,7 @@ marko_template._ = marko_renderer(render, {
135
154
  });
136
155
 
137
156
  marko_template.meta = {
138
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/content-meter.marko",
157
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/content-meter.marko",
139
158
  tags: [
140
159
  "@mindful-web/marko-web/components/browser-component.marko",
141
160
  "../menu-toggle-button.marko",
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/full-width-native-ad.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/full-width-native-ad.marko",
6
6
  marko_component = require("./full-width-native-ad.marko"),
7
7
  marko_renderer = require("marko/dist/runtime/components/renderer"),
8
8
  module_objectPath_module = require("@mindful-web/object-path"),
@@ -52,7 +52,7 @@ marko_template._ = marko_renderer(render, {
52
52
  }, marko_component);
53
53
 
54
54
  marko_template.meta = {
55
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/full-width-native-ad.marko",
55
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/full-width-native-ad.marko",
56
56
  component: "./full-width-native-ad.marko",
57
57
  tags: [
58
58
  "../nodes/section-feed-content.marko",
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
- marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/geo-summary.marko",
5
+ marko_componentType = "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/geo-summary.marko",
6
6
  marko_renderer = require("marko/dist/runtime/components/renderer"),
7
7
  module_objectPath_module = require("@mindful-web/object-path"),
8
8
  objectPath_module = module_objectPath_module.default || module_objectPath_module,
@@ -150,7 +150,7 @@ marko_template._ = marko_renderer(render, {
150
150
  });
151
151
 
152
152
  marko_template.meta = {
153
- id: "/@mindful-web/marko-web-theme-monorail$1.80.2/components/blocks/geo-summary.marko",
153
+ id: "/@mindful-web/marko-web-theme-monorail$1.81.0/components/blocks/geo-summary.marko",
154
154
  tags: [
155
155
  "../menu-toggle-button.marko",
156
156
  "@mindful-web/marko-web/components/element/index.marko",