@luigisbox/luma 0.0.0-stage → 0.2.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.
- package/LICENSE.md +90 -0
- package/README.md +615 -2
- package/a11y/audit.mjs +735 -0
- package/a11y/axe.mjs +73 -0
- package/a11y/report.mjs +347 -0
- package/a11y/run.mjs +256 -0
- package/a11y/wcag.mjs +233 -0
- package/bin/config.mjs +60 -0
- package/bin/luma.mjs +99 -0
- package/bin/paths.mjs +11 -0
- package/bin/tools.mjs +43 -0
- package/build/baseline.d.mts +8 -0
- package/build/baseline.mjs +167 -0
- package/build/tooling.mjs +102 -0
- package/build/vite.mjs +507 -0
- package/chrome/block.mjs +8 -0
- package/chrome/run.mjs +150 -0
- package/docs/ACCESSIBILITY.md +501 -0
- package/docs/INTEGRATION-PERFORMANCE.md +213 -0
- package/docs/PARITY.md +946 -0
- package/footprint/model.mjs +184 -0
- package/footprint/run.mjs +331 -0
- package/package.json +58 -4
- package/parity/alignment.mjs +109 -0
- package/parity/archive.mjs +223 -0
- package/parity/args.mjs +137 -0
- package/parity/behaviour.mjs +379 -0
- package/parity/compare.mjs +985 -0
- package/parity/engine.mjs +848 -0
- package/parity/hints.mjs +132 -0
- package/parity/hold.mjs +54 -0
- package/parity/init.mjs +703 -0
- package/parity/map.mjs +640 -0
- package/parity/owner.mjs +170 -0
- package/parity/pairing.mjs +110 -0
- package/parity/pixels.mjs +33 -0
- package/parity/probe.mjs +1239 -0
- package/parity/report.mjs +236 -0
- package/parity/run.mjs +267 -0
- package/snippet/early-hold.js +64 -0
- package/snippet/early-hold.min.js +1 -0
- package/src/analytics/chain.ts +137 -0
- package/src/analytics/collect.ts +64 -0
- package/src/analytics/datalayer.ts +67 -0
- package/src/analytics/from-ga4.ts +68 -0
- package/src/analytics/from-luma.ts +21 -0
- package/src/analytics/index.ts +24 -0
- package/src/analytics/outbox.ts +118 -0
- package/src/analytics/page.ts +46 -0
- package/src/analytics/pageview.ts +82 -0
- package/src/analytics/ref.ts +19 -0
- package/src/analytics/setup.ts +41 -0
- package/src/analytics/start.ts +53 -0
- package/src/analytics/triggers.ts +239 -0
- package/src/analytics/user.ts +12 -0
- package/src/analytics/wire.ts +67 -0
- package/src/api/ai.ts +98 -0
- package/src/api/index.ts +87 -0
- package/src/api/token-key.ts +42 -0
- package/src/api/token.ts +312 -0
- package/src/core/a11y-keys.ts +60 -0
- package/src/core/a11y.ts +160 -0
- package/src/core/boot-state.ts +6 -0
- package/src/core/color.ts +42 -0
- package/src/core/context.ts +108 -0
- package/src/core/early-rules.ts +96 -0
- package/src/core/entries.ts +25 -0
- package/src/core/fold.ts +7 -0
- package/src/core/health.ts +26 -0
- package/src/core/hold.ts +74 -0
- package/src/core/i18n.ts +66 -0
- package/src/core/image-load.ts +102 -0
- package/src/core/image-tags.ts +26 -0
- package/src/core/images.ts +170 -0
- package/src/core/integration.ts +126 -0
- package/src/core/kept.ts +25 -0
- package/src/core/listings.ts +100 -0
- package/src/core/locales.ts +14 -0
- package/src/core/own.ts +49 -0
- package/src/core/page.ts +14 -0
- package/src/core/prefetch.ts +88 -0
- package/src/core/recommenders.ts +166 -0
- package/src/core/reconciler.ts +397 -0
- package/src/core/result.ts +73 -0
- package/src/core/routes.ts +115 -0
- package/src/core/scheduler.ts +83 -0
- package/src/core/sense.ts +107 -0
- package/src/core/speculation.ts +59 -0
- package/src/core/stash.ts +38 -0
- package/src/core/storage.ts +45 -0
- package/src/core/styles.ts +106 -0
- package/src/core/support.ts +12 -0
- package/src/core/takeover.ts +220 -0
- package/src/core/templates.ts +74 -0
- package/src/core/tiles.ts +137 -0
- package/src/core/turbo.ts +64 -0
- package/src/core/url.ts +164 -0
- package/src/core/widget-inits.ts +40 -0
- package/src/env.d.ts +3 -0
- package/src/lit.ts +11 -0
- package/src/locales/cs.json +94 -0
- package/src/locales/de.json +88 -0
- package/src/locales/en.json +88 -0
- package/src/main.ts +493 -0
- package/src/types.ts +778 -0
- package/src/widgets/autocomplete/index.ts +1387 -0
- package/src/widgets/autocomplete/style-autocomplete.css +266 -0
- package/src/widgets/autocomplete/template-autocomplete-box.ts +61 -0
- package/src/widgets/autocomplete/template-autocomplete-empty.ts +53 -0
- package/src/widgets/autocomplete/template-autocomplete-result-default.ts +82 -0
- package/src/widgets/autocomplete/template-autocomplete-sheet.ts +74 -0
- package/src/widgets/listing/element.ts +1772 -0
- package/src/widgets/listing/flow.ts +30 -0
- package/src/widgets/listing/instant.ts +133 -0
- package/src/widgets/listing/intent.ts +193 -0
- package/src/widgets/listing/query.ts +298 -0
- package/src/widgets/listing/stash.ts +97 -0
- package/src/widgets/listing/state.ts +131 -0
- package/src/widgets/listing/view.ts +257 -0
- package/src/widgets/plp/index.ts +11 -0
- package/src/widgets/plp/route.ts +263 -0
- package/src/widgets/recommender/index.ts +261 -0
- package/src/widgets/recommender/style-recommender.css +26 -0
- package/src/widgets/recommender/template-recommender-box-default.ts +11 -0
- package/src/widgets/recommender/template-recommender-popup.ts +12 -0
- package/src/widgets/recommender/template-recommender-result-default.ts +10 -0
- package/src/widgets/search/assets.ts +7 -0
- package/src/widgets/search/first.ts +15 -0
- package/src/widgets/search/form-url.ts +59 -0
- package/src/widgets/search/in-place.ts +226 -0
- package/src/widgets/search/index.ts +16 -0
- package/src/widgets/search/range.ts +260 -0
- package/src/widgets/search/route.ts +32 -0
- package/src/widgets/search/speculate.ts +202 -0
- package/src/widgets/search/style-search.css +65 -0
- package/src/widgets/search/template-search-box.ts +17 -0
- package/src/widgets/search/template-search-facets-default.ts +73 -0
- package/src/widgets/search/template-search-header.ts +14 -0
- package/src/widgets/search/template-search-pagination.ts +12 -0
- package/src/widgets/search/template-search-range-default.ts +48 -0
- package/src/widgets/search/template-search-result-default.ts +13 -0
- package/src/widgets/search/template-search-results-default.ts +8 -0
- package/tasks/model.mjs +116 -0
- package/tasks/run.mjs +305 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// An integration's `_widget.ts` (IntegrationFiles.widgetInits): hooks only a
|
|
2
|
+
// widget calls, run when it loads. In lbx-core (core/support.ts), not the
|
|
3
|
+
// entry: the hooks' modules are in the widget's own chunks anyway. No DOM:
|
|
4
|
+
// the server renderer runs them for its listings too.
|
|
5
|
+
|
|
6
|
+
import { folderOf, slot, type IntegrationFiles } from './integration';
|
|
7
|
+
import type { LumaApi, LumaConfigType, LumaWidgetInitType } from '../types';
|
|
8
|
+
|
|
9
|
+
const widgetInitsRun = new WeakMap<object, Map<string, Promise<void>>>();
|
|
10
|
+
/**
|
|
11
|
+
* The `_widget.ts` of a widget's folders, in folder order, each run once per
|
|
12
|
+
* config (a folder shared by widgets, `_global`, runs for the first): before
|
|
13
|
+
* the widget's context is made from the config they complete.
|
|
14
|
+
*/
|
|
15
|
+
export const loadWidgetInits = (config: LumaConfigType, files: Pick<IntegrationFiles, 'widgetInits'>, folders: readonly string[], version: string) => {
|
|
16
|
+
let ran = widgetInitsRun.get(config);
|
|
17
|
+
if (!ran) widgetInitsRun.set(config, (ran = new Map()));
|
|
18
|
+
const Luma: LumaApi = { version, config };
|
|
19
|
+
const entries = Object.entries(files.widgetInits ?? {});
|
|
20
|
+
let chain = Promise.resolve();
|
|
21
|
+
for (const folder of folders) {
|
|
22
|
+
const found = entries.find(([p]) => folderOf(p) === folder);
|
|
23
|
+
if (!found) continue;
|
|
24
|
+
const [, v] = found;
|
|
25
|
+
let p = ran.get(folder);
|
|
26
|
+
if (!p) {
|
|
27
|
+
// In folder order: _global's hooks are there before a widget's own (it may build on them).
|
|
28
|
+
p = chain.then(async () => {
|
|
29
|
+
const f: LumaWidgetInitType<any> = await v();
|
|
30
|
+
await f(folder === '_global' ? config : slot(config, folder), Luma);
|
|
31
|
+
});
|
|
32
|
+
ran.set(folder, p);
|
|
33
|
+
// A failed one (its chunk, the hook) fails this load; the next one tries again.
|
|
34
|
+
p.catch(() => ran!.get(folder) === p && ran!.delete(folder));
|
|
35
|
+
}
|
|
36
|
+
chain = p;
|
|
37
|
+
}
|
|
38
|
+
return chain;
|
|
39
|
+
};
|
|
40
|
+
|
package/src/env.d.ts
ADDED
package/src/lit.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// lit-html for templates: `import { html, repeat } from '@/lit'` in an
|
|
2
|
+
// integration, so every template uses the framework's one copy of lit.
|
|
3
|
+
// Only what a template uses ends up in the bundle. Note for form controls:
|
|
4
|
+
// bind `.checked` / `.selected` plainly (not with live()): lit then leaves a
|
|
5
|
+
// control the user just changed alone until the state it drives agrees.
|
|
6
|
+
export { html, svg, nothing } from 'lit-html';
|
|
7
|
+
export { repeat } from 'lit-html/directives/repeat.js';
|
|
8
|
+
export { classMap } from 'lit-html/directives/class-map.js';
|
|
9
|
+
export { styleMap } from 'lit-html/directives/style-map.js';
|
|
10
|
+
export { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
11
|
+
export { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_name": "Čeština",
|
|
3
|
+
"autocomplete": {
|
|
4
|
+
"showAllResults": "Zobrazit všechny výsledky",
|
|
5
|
+
"empty": "Pro „{query}“ jsme nic nenašli",
|
|
6
|
+
"types": {
|
|
7
|
+
"product": "Produkty",
|
|
8
|
+
"category": "Kategorie",
|
|
9
|
+
"brand": "Značky",
|
|
10
|
+
"query": "Návrhy",
|
|
11
|
+
"article": "Články"
|
|
12
|
+
},
|
|
13
|
+
"label": "Návrhy vyhledávání",
|
|
14
|
+
"count": "Návrhy: {count}",
|
|
15
|
+
"phrases": "Fráze",
|
|
16
|
+
"topProduct": "Top produkt",
|
|
17
|
+
"products": "Produkty",
|
|
18
|
+
"showAllProducts": "Zobrazit všechny produkty",
|
|
19
|
+
"emptyHint": "Zkontrolujte, jestli v hledání není překlep, nebo zkuste kratší či obecnější slovo.",
|
|
20
|
+
"tryLabel": "Zkuste třeba",
|
|
21
|
+
"browseLabel": "Nebo projděte",
|
|
22
|
+
"fallbackTitle": "Nejprodávanější",
|
|
23
|
+
"fallbackNote": "Tipy z celého obchodu, nesouvisí s vaším hledáním",
|
|
24
|
+
"help": {
|
|
25
|
+
"title": "Potřebujete poradit?",
|
|
26
|
+
"phone": "",
|
|
27
|
+
"hours": ""
|
|
28
|
+
},
|
|
29
|
+
"inStock": "Skladem",
|
|
30
|
+
"was": "Původně",
|
|
31
|
+
"closeSearch": "Zavřít hledání",
|
|
32
|
+
"clear": "Smazat",
|
|
33
|
+
"tabs": "Typy výsledků",
|
|
34
|
+
"call": "Zavolat",
|
|
35
|
+
"poweredBy": "Powered by Luigi’s Box",
|
|
36
|
+
"specs": {}
|
|
37
|
+
},
|
|
38
|
+
"search": {
|
|
39
|
+
"results": {
|
|
40
|
+
"one": "{count} výsledek pro „{query}“",
|
|
41
|
+
"few": "{count} výsledky pro „{query}“",
|
|
42
|
+
"many": "{count} výsledku pro „{query}“",
|
|
43
|
+
"other": "{count} výsledků pro „{query}“"
|
|
44
|
+
},
|
|
45
|
+
"empty": "Pro „{query}“ jsme nic nenašli.",
|
|
46
|
+
"error": "Vyhledávání se nepodařilo načíst.",
|
|
47
|
+
"sort": "Řadit:",
|
|
48
|
+
"filters": "Filtry",
|
|
49
|
+
"sorts": {
|
|
50
|
+
"": "Relevance"
|
|
51
|
+
},
|
|
52
|
+
"facets": {},
|
|
53
|
+
"more": "Zobrazit další",
|
|
54
|
+
"label": "Výsledky vyhledávání",
|
|
55
|
+
"shown": "Zobrazeno {shown} z {total}",
|
|
56
|
+
"drawer": "Filtry",
|
|
57
|
+
"removeFilter": "Odebrat filtr: {label}",
|
|
58
|
+
"chosen": "Vybrané filtry",
|
|
59
|
+
"clearAll": "Zrušit vše",
|
|
60
|
+
"facetSearch": "Hledat v: {facet}",
|
|
61
|
+
"facetSearchPlaceholder": "Hledat",
|
|
62
|
+
"facetMatches": {
|
|
63
|
+
"one": "{count} shoda",
|
|
64
|
+
"few": "{count} shody",
|
|
65
|
+
"many": "{count} shody",
|
|
66
|
+
"other": "{count} shod"
|
|
67
|
+
},
|
|
68
|
+
"rangeMin": "{facet}: minimum",
|
|
69
|
+
"rangeMax": "{facet}: maximum",
|
|
70
|
+
"rangeFrom": "{facet} od",
|
|
71
|
+
"rangeTo": "{facet} do",
|
|
72
|
+
"rangeSeparator": "do"
|
|
73
|
+
},
|
|
74
|
+
"plp": {
|
|
75
|
+
"results": {
|
|
76
|
+
"one": "{count} produkt",
|
|
77
|
+
"few": "{count} produkty",
|
|
78
|
+
"many": "{count} produktu",
|
|
79
|
+
"other": "{count} produktů"
|
|
80
|
+
},
|
|
81
|
+
"empty": "V této kategorii teď nic nenajdete.",
|
|
82
|
+
"error": "Produkty se nepodařilo načíst.",
|
|
83
|
+
"sorts": {
|
|
84
|
+
"": "Doporučené"
|
|
85
|
+
},
|
|
86
|
+
"flags": {},
|
|
87
|
+
"label": "Produkty"
|
|
88
|
+
},
|
|
89
|
+
"recommender": {
|
|
90
|
+
"close": "Zavřít",
|
|
91
|
+
"title": "Doporučujeme"
|
|
92
|
+
},
|
|
93
|
+
"contrast": "Režim vysokého kontrastu"
|
|
94
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_name": "Deutsch",
|
|
3
|
+
"autocomplete": {
|
|
4
|
+
"showAllResults": "Alle Ergebnisse anzeigen",
|
|
5
|
+
"empty": "Keine Treffer für „{query}“",
|
|
6
|
+
"types": {
|
|
7
|
+
"product": "Produkte",
|
|
8
|
+
"category": "Kategorien",
|
|
9
|
+
"brand": "Marken",
|
|
10
|
+
"query": "Vorschläge",
|
|
11
|
+
"article": "Artikel"
|
|
12
|
+
},
|
|
13
|
+
"label": "Suchvorschläge",
|
|
14
|
+
"count": "Vorschläge: {count}",
|
|
15
|
+
"phrases": "Suchbegriffe",
|
|
16
|
+
"topProduct": "Top-Produkt",
|
|
17
|
+
"products": "Produkte",
|
|
18
|
+
"showAllProducts": "Alle Produkte anzeigen",
|
|
19
|
+
"emptyHint": "Prüfen Sie die Schreibweise oder versuchen Sie ein kürzeres oder allgemeineres Wort.",
|
|
20
|
+
"tryLabel": "Versuchen Sie",
|
|
21
|
+
"browseLabel": "Oder stöbern Sie",
|
|
22
|
+
"fallbackTitle": "Bestseller",
|
|
23
|
+
"fallbackNote": "Tipps aus dem ganzen Shop, keine Ergebnisse Ihrer Suche",
|
|
24
|
+
"help": {
|
|
25
|
+
"title": "Brauchen Sie Beratung?",
|
|
26
|
+
"phone": "",
|
|
27
|
+
"hours": ""
|
|
28
|
+
},
|
|
29
|
+
"inStock": "Auf Lager",
|
|
30
|
+
"was": "Statt",
|
|
31
|
+
"closeSearch": "Suche schließen",
|
|
32
|
+
"clear": "Löschen",
|
|
33
|
+
"tabs": "Ergebnisarten",
|
|
34
|
+
"call": "Anrufen",
|
|
35
|
+
"poweredBy": "Powered by Luigi’s Box",
|
|
36
|
+
"specs": {}
|
|
37
|
+
},
|
|
38
|
+
"search": {
|
|
39
|
+
"results": {
|
|
40
|
+
"one": "{count} Artikel für „{query}“",
|
|
41
|
+
"other": "{count} Artikel für „{query}“"
|
|
42
|
+
},
|
|
43
|
+
"empty": "Keine Treffer für „{query}“.",
|
|
44
|
+
"error": "Die Suche konnte nicht geladen werden.",
|
|
45
|
+
"sort": "Sortieren:",
|
|
46
|
+
"filters": "Filtern",
|
|
47
|
+
"sorts": {
|
|
48
|
+
"": "Relevanz"
|
|
49
|
+
},
|
|
50
|
+
"facets": {},
|
|
51
|
+
"more": "Mehr anzeigen",
|
|
52
|
+
"label": "Suchergebnisse",
|
|
53
|
+
"shown": "{shown} von {total} angezeigt",
|
|
54
|
+
"drawer": "Filter",
|
|
55
|
+
"removeFilter": "Filter entfernen: {label}",
|
|
56
|
+
"chosen": "Ausgewählte Filter",
|
|
57
|
+
"clearAll": "Alle entfernen",
|
|
58
|
+
"facetSearch": "In {facet} suchen",
|
|
59
|
+
"facetSearchPlaceholder": "Suchen",
|
|
60
|
+
"facetMatches": {
|
|
61
|
+
"one": "{count} Treffer",
|
|
62
|
+
"other": "{count} Treffer"
|
|
63
|
+
},
|
|
64
|
+
"rangeMin": "{facet}: Minimum",
|
|
65
|
+
"rangeMax": "{facet}: Maximum",
|
|
66
|
+
"rangeFrom": "{facet} von",
|
|
67
|
+
"rangeTo": "{facet} bis",
|
|
68
|
+
"rangeSeparator": "bis"
|
|
69
|
+
},
|
|
70
|
+
"plp": {
|
|
71
|
+
"results": {
|
|
72
|
+
"one": "{count} Artikel",
|
|
73
|
+
"other": "{count} Artikel"
|
|
74
|
+
},
|
|
75
|
+
"empty": "In dieser Kategorie gibt es gerade keine Artikel.",
|
|
76
|
+
"error": "Die Artikel konnten nicht geladen werden.",
|
|
77
|
+
"sorts": {
|
|
78
|
+
"": "Empfohlen"
|
|
79
|
+
},
|
|
80
|
+
"flags": {},
|
|
81
|
+
"label": "Artikel"
|
|
82
|
+
},
|
|
83
|
+
"recommender": {
|
|
84
|
+
"close": "Schließen",
|
|
85
|
+
"title": "Empfehlungen für Sie"
|
|
86
|
+
},
|
|
87
|
+
"contrast": "Hoher Kontrast"
|
|
88
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_name": "English",
|
|
3
|
+
"autocomplete": {
|
|
4
|
+
"showAllResults": "See all results",
|
|
5
|
+
"empty": "No results for “{query}”",
|
|
6
|
+
"types": {
|
|
7
|
+
"product": "Products",
|
|
8
|
+
"category": "Categories",
|
|
9
|
+
"brand": "Brands",
|
|
10
|
+
"query": "Suggestions",
|
|
11
|
+
"article": "Articles"
|
|
12
|
+
},
|
|
13
|
+
"label": "Search suggestions",
|
|
14
|
+
"count": "Suggestions: {count}",
|
|
15
|
+
"phrases": "Phrases",
|
|
16
|
+
"topProduct": "Top product",
|
|
17
|
+
"products": "Products",
|
|
18
|
+
"showAllProducts": "Show all products",
|
|
19
|
+
"emptyHint": "Check the spelling, or try a shorter or more general word.",
|
|
20
|
+
"tryLabel": "Try",
|
|
21
|
+
"browseLabel": "Or browse",
|
|
22
|
+
"fallbackTitle": "Bestsellers",
|
|
23
|
+
"fallbackNote": "Picks from the whole shop, not results for your search",
|
|
24
|
+
"help": {
|
|
25
|
+
"title": "Need advice?",
|
|
26
|
+
"phone": "",
|
|
27
|
+
"hours": ""
|
|
28
|
+
},
|
|
29
|
+
"inStock": "In stock",
|
|
30
|
+
"was": "Was",
|
|
31
|
+
"closeSearch": "Close search",
|
|
32
|
+
"clear": "Clear",
|
|
33
|
+
"tabs": "Result types",
|
|
34
|
+
"call": "Call",
|
|
35
|
+
"poweredBy": "Powered by Luigi’s Box",
|
|
36
|
+
"specs": {}
|
|
37
|
+
},
|
|
38
|
+
"search": {
|
|
39
|
+
"results": {
|
|
40
|
+
"one": "{count} result for “{query}”",
|
|
41
|
+
"other": "{count} results for “{query}”"
|
|
42
|
+
},
|
|
43
|
+
"empty": "No results for “{query}”.",
|
|
44
|
+
"error": "Search could not be loaded.",
|
|
45
|
+
"sort": "Sort by",
|
|
46
|
+
"filters": "Filter by",
|
|
47
|
+
"sorts": {
|
|
48
|
+
"": "Relevance"
|
|
49
|
+
},
|
|
50
|
+
"facets": {},
|
|
51
|
+
"more": "Show more",
|
|
52
|
+
"label": "Search results",
|
|
53
|
+
"shown": "Showing {shown} of {total}",
|
|
54
|
+
"drawer": "Filters",
|
|
55
|
+
"removeFilter": "Remove filter: {label}",
|
|
56
|
+
"chosen": "Selected filters",
|
|
57
|
+
"clearAll": "Clear all",
|
|
58
|
+
"facetSearch": "Search in {facet}",
|
|
59
|
+
"facetSearchPlaceholder": "Search",
|
|
60
|
+
"facetMatches": {
|
|
61
|
+
"one": "{count} match",
|
|
62
|
+
"other": "{count} matches"
|
|
63
|
+
},
|
|
64
|
+
"rangeMin": "{facet}: minimum",
|
|
65
|
+
"rangeMax": "{facet}: maximum",
|
|
66
|
+
"rangeFrom": "{facet} from",
|
|
67
|
+
"rangeTo": "{facet} to",
|
|
68
|
+
"rangeSeparator": "to"
|
|
69
|
+
},
|
|
70
|
+
"plp": {
|
|
71
|
+
"results": {
|
|
72
|
+
"one": "{count} product",
|
|
73
|
+
"other": "{count} products"
|
|
74
|
+
},
|
|
75
|
+
"empty": "No products in this category right now.",
|
|
76
|
+
"error": "Products could not be loaded.",
|
|
77
|
+
"sorts": {
|
|
78
|
+
"": "Recommended"
|
|
79
|
+
},
|
|
80
|
+
"flags": {},
|
|
81
|
+
"label": "Products"
|
|
82
|
+
},
|
|
83
|
+
"recommender": {
|
|
84
|
+
"close": "Close",
|
|
85
|
+
"title": "Recommended for you"
|
|
86
|
+
},
|
|
87
|
+
"contrast": "High-contrast mode"
|
|
88
|
+
}
|