diff --git a/packages/visual-editor/i18next-cli.components.config.ts b/packages/visual-editor/i18next-cli.components.config.ts index 2b7ac756e..d901388c9 100644 --- a/packages/visual-editor/i18next-cli.components.config.ts +++ b/packages/visual-editor/i18next-cli.components.config.ts @@ -17,7 +17,7 @@ export default defineConfig({ pluralSeparator: "_", interpolationPrefix: "{{", interpolationSuffix: "}}", - functions: ["t", "*.t", "i18next.t"], + functions: ["t", "*.t", "i18next.t", "defaultText", "defaultRichText"], primaryLanguage: "en", defaultValue: "", sort: true, diff --git a/packages/visual-editor/i18next-cli.platform.config.ts b/packages/visual-editor/i18next-cli.platform.config.ts index d709bee83..bcb8b3d59 100644 --- a/packages/visual-editor/i18next-cli.platform.config.ts +++ b/packages/visual-editor/i18next-cli.platform.config.ts @@ -17,7 +17,15 @@ export default defineConfig({ pluralSeparator: "_", interpolationPrefix: "{{", interpolationSuffix: "}}", - functions: ["t", "*.t", "i18next.t", "pt", "msg"], + functions: [ + "t", + "*.t", + "i18next.t", + "pt", + "msg", + "defaultText", + "defaultRichText", + ], primaryLanguage: "en", defaultValue: "", sort: true, diff --git a/packages/visual-editor/locales/components/cs/visual-editor.json b/packages/visual-editor/locales/components/cs/visual-editor.json index a95ddd495..412db63d6 100644 --- a/packages/visual-editor/locales/components/cs/visual-editor.json +++ b/packages/visual-editor/locales/components/cs/visual-editor.json @@ -17,6 +17,55 @@ "closed": "ZAVŘENO", "closesAtTime": "Zavírá v {{time}}", "closesAtTimeWeek": "Zavírá v {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "O [[name]]", + "articleName": "Název článku", + "associateAgent": "Přidružený agent", + "bannerText": "Text banneru", + "businessName": "Obchodní název", + "button": "Tlačítko", + "callToAction": "Výzva k akci", + "category": "Kategorie", + "contactMe": "Kontaktujte mě", + "credentials": "Pověření", + "directoryRoot": "Kořen adresáře", + "eventImage": "Obrázek události", + "eventTitle": "Název události", + "featuredProducts": "Vybrané produkty", + "featuredPromotion": "Doporučená propagace", + "featuredTestimonials": "Doporučené posudky", + "findALocation": "Najděte polohu", + "firstLast": "První Poslední", + "followUs": "Sledujte nás", + "footerLabel": "Štítek zápatí", + "footerLink": "Odkaz v zápatí", + "frequentlyAskedQuestions": "Často kladené otázky", + "gallery": "Galerie", + "geomodifier": "Geomodifikátor", + "getDirections": "Získejte pokyny", + "header": "Záhlaví", + "headerLink": "Odkaz na záhlaví", + "hours": "Hodiny", + "information": "Informace", + "insights": "Postřehy", + "learnMore": "Další informace", + "logo": "Logo", + "meetOurTeam": "Seznamte se s naším týmem", + "name": "Jméno", + "nearbyLocations": "Místa v okolí", + "phone": "Telefon", + "price": "123,00 Kč", + "productName": "Název produktu", + "professionalName": "Profesní jméno", + "professionalTitle": "Profesionální titul", + "readMore": "Číst více", + "services": "Služby", + "servicesOffered": "Nabízené služby", + "subtitle": "Titulky", + "text": "Text", + "upcomingEvents": "Nadcházející události", + "visitProfile": "Navštivte profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Obslužný obrázek {{number}}" diff --git a/packages/visual-editor/locales/components/da/visual-editor.json b/packages/visual-editor/locales/components/da/visual-editor.json index 0f67eb1c7..b7c537a76 100644 --- a/packages/visual-editor/locales/components/da/visual-editor.json +++ b/packages/visual-editor/locales/components/da/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Lukket", "closesAtTime": "Lukker kl. {{time}}", "closesAtTimeWeek": "Lukker kl. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Om [[name]]", + "articleName": "Artikelnavn", + "associateAgent": "Associeret agent", + "bannerText": "Bannertekst", + "businessName": "Virksomhedens navn", + "button": "Knap", + "callToAction": "Opfordring til handling", + "category": "Kategori", + "contactMe": "Kontakt mig", + "credentials": "Akkreditiver", + "directoryRoot": "Biblioteksrod", + "eventImage": "Begivenhedsbillede", + "eventTitle": "Begivenhedens titel", + "featuredProducts": "Udvalgte produkter", + "featuredPromotion": "Fremhævet kampagne", + "featuredTestimonials": "Udvalgte testimonials", + "findALocation": "Find en placering", + "firstLast": "Første Sidste", + "followUs": "Følg os", + "footerLabel": "Footer label", + "footerLink": "Sidefodslink", + "frequentlyAskedQuestions": "Ofte stillede spørgsmål", + "gallery": "Galleri", + "geomodifier": "Geomodifikator", + "getDirections": "Få rutevejledning", + "header": "Overskrift", + "headerLink": "Overskriftslink", + "hours": "Timer", + "information": "Information", + "insights": "Indsigt", + "learnMore": "Lær mere", + "logo": "Logo", + "meetOurTeam": "Mød vores team", + "name": "Navn", + "nearbyLocations": "Steder i nærheden", + "phone": "Telefon", + "price": "123,00 DKK", + "productName": "Produktnavn", + "professionalName": "Professionelt navn", + "professionalTitle": "Professionel titel", + "readMore": "Læs mere", + "services": "Tjenester", + "servicesOffered": "Udbudte tjenester", + "subtitle": "Undertekst", + "text": "Tekst", + "upcomingEvents": "Kommende begivenheder", + "visitProfile": "Besøg profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Hjælpebillede {{number}}" diff --git a/packages/visual-editor/locales/components/de/visual-editor.json b/packages/visual-editor/locales/components/de/visual-editor.json index 2c78ba659..8cea6b28d 100644 --- a/packages/visual-editor/locales/components/de/visual-editor.json +++ b/packages/visual-editor/locales/components/de/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Geschlossen", "closesAtTime": "Schließt um {{time}} Uhr", "closesAtTimeWeek": "Schließt um {{time}} Uhr am {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Über [[name]]", + "articleName": "Artikelname", + "associateAgent": "Assoziierter Agent", + "bannerText": "Bannertext", + "businessName": "Firmenname", + "button": "Button", + "callToAction": "Aufruf zum Handeln", + "category": "Kategorie", + "contactMe": "Kontaktieren Sie mich", + "credentials": "Anmeldeinformationen", + "directoryRoot": "Verzeichnisstamm", + "eventImage": "Veranstaltung-Bild", + "eventTitle": "Veranstaltungstitel", + "featuredProducts": "Ausgewählte Produkte", + "featuredPromotion": "Empfohlene Werbeaktion", + "featuredTestimonials": "Ausgewählte Erfahrungsberichte", + "findALocation": "Finden Sie einen Standort", + "firstLast": "Erster Letzter", + "followUs": "Folgen Sie uns", + "footerLabel": "Fußzeilenbeschriftung", + "footerLink": "Fußzeilen-Link", + "frequentlyAskedQuestions": "Häufig gestellte Fragen", + "gallery": "Galerie", + "geomodifier": "Geomodifikator", + "getDirections": "Wegbeschreibung abrufen", + "header": "Kopfzeile", + "headerLink": "Header-Link", + "hours": "Öffnungszeiten", + "information": "Information", + "insights": "Einblicke", + "learnMore": "Erfahren Sie mehr", + "logo": "Logo", + "meetOurTeam": "Lernen Sie unser Team kennen", + "name": "Name", + "nearbyLocations": "Standorte in der Nähe", + "phone": "Telefon", + "price": "123,00 €", + "productName": "Produktname", + "professionalName": "Berufsname", + "professionalTitle": "Berufsbezeichnung", + "readMore": "Mehr lesen", + "services": "Dienstleistungen", + "servicesOffered": "Angebotene Dienstleistungen", + "subtitle": "Untertitel", + "text": "Text", + "upcomingEvents": "Kommende Veranstaltungen", + "visitProfile": "Besuchen Sie das Profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Utility-Bilder {{number}}" diff --git a/packages/visual-editor/locales/components/en-GB/visual-editor.json b/packages/visual-editor/locales/components/en-GB/visual-editor.json index 59a46bf16..37b0dc059 100644 --- a/packages/visual-editor/locales/components/en-GB/visual-editor.json +++ b/packages/visual-editor/locales/components/en-GB/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Closed", "closesAtTime": "Closes at {{time}}", "closesAtTimeWeek": "Closes at {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "About [[name]]", + "articleName": "Article Name", + "associateAgent": "Associate Agent", + "bannerText": "Banner Text", + "businessName": "Business Name", + "button": "Button", + "callToAction": "Call to Action", + "category": "Category", + "contactMe": "Contact Me", + "credentials": "Credentials", + "directoryRoot": "Directory Root", + "eventImage": "Event Image", + "eventTitle": "Event Title", + "featuredProducts": "Featured Products", + "featuredPromotion": "Featured Promotion", + "featuredTestimonials": "Featured Testimonials", + "findALocation": "Find a Location", + "firstLast": "First Last", + "followUs": "Follow Us", + "footerLabel": "Footer Label", + "footerLink": "Footer Link", + "frequentlyAskedQuestions": "Frequently Asked Questions", + "gallery": "Gallery", + "geomodifier": "Geomodifier", + "getDirections": "Get Directions", + "header": "Header", + "headerLink": "Header Link", + "hours": "Hours", + "information": "Information", + "insights": "Insights", + "learnMore": "Learn More", + "logo": "Logo", + "meetOurTeam": "Meet Our Team", + "name": "Name", + "nearbyLocations": "Nearby Locations", + "phone": "Phone", + "price": "£123.00", + "productName": "Product Name", + "professionalName": "Professional Name", + "professionalTitle": "Professional Title", + "readMore": "Read More", + "services": "Services", + "servicesOffered": "Services Offered", + "subtitle": "Subtitle", + "text": "Text", + "upcomingEvents": "Upcoming Events", + "visitProfile": "Visit Profile" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Utility Image {{number}}" diff --git a/packages/visual-editor/locales/components/en/visual-editor.json b/packages/visual-editor/locales/components/en/visual-editor.json index a721714c4..e1cb7896b 100644 --- a/packages/visual-editor/locales/components/en/visual-editor.json +++ b/packages/visual-editor/locales/components/en/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Closed", "closesAtTime": "Closes at {{time}}", "closesAtTimeWeek": "Closes at {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "About [[name]]", + "articleName": "Article Name", + "associateAgent": "Associate Agent", + "bannerText": "Banner Text", + "businessName": "Business Name", + "button": "Button", + "callToAction": "Call to Action", + "category": "Category", + "contactMe": "Contact Me", + "credentials": "Credentials", + "directoryRoot": "Directory Root", + "eventImage": "Event Image", + "eventTitle": "Event Title", + "featuredProducts": "Featured Products", + "featuredPromotion": "Featured Promotion", + "featuredTestimonials": "Featured Testimonials", + "findALocation": "Find a Location", + "firstLast": "First Last", + "followUs": "Follow Us", + "footerLabel": "Footer Label", + "footerLink": "Footer Link", + "frequentlyAskedQuestions": "Frequently Asked Questions", + "gallery": "Gallery", + "geomodifier": "Geomodifier", + "getDirections": "Get Directions", + "header": "Header", + "headerLink": "Header Link", + "hours": "Hours", + "information": "Information", + "insights": "Insights", + "learnMore": "Learn More", + "logo": "Logo", + "meetOurTeam": "Meet Our Team", + "name": "Name", + "nearbyLocations": "Nearby Locations", + "phone": "Phone", + "price": "$123.00", + "productName": "Product Name", + "professionalName": "Professional Name", + "professionalTitle": "Professional Title", + "readMore": "Read More", + "services": "Services", + "servicesOffered": "Services Offered", + "subtitle": "Subtitle", + "text": "Text", + "upcomingEvents": "Upcoming Events", + "visitProfile": "Visit Profile" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Utility Image {{number}}" diff --git a/packages/visual-editor/locales/components/es/visual-editor.json b/packages/visual-editor/locales/components/es/visual-editor.json index 813582ff1..a37519a73 100644 --- a/packages/visual-editor/locales/components/es/visual-editor.json +++ b/packages/visual-editor/locales/components/es/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Cerrado", "closesAtTime": "Cierra a las {{time}}", "closesAtTimeWeek": "Cierra a las {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Acerca de [[name]]", + "articleName": "Nombre del artículo", + "associateAgent": "Agente asociado", + "bannerText": "Texto del cartel", + "businessName": "Nombre comercial", + "button": "Botón", + "callToAction": "Llamado a la acción", + "category": "Categoría", + "contactMe": "Contáctame", + "credentials": "Cartas credenciales", + "directoryRoot": "Raíz del directorio", + "eventImage": "Imagen del evento", + "eventTitle": "Título del evento", + "featuredProducts": "Productos destacados", + "featuredPromotion": "Promoción destacada", + "featuredTestimonials": "Testimonios destacados", + "findALocation": "Encontrar una ubicación", + "firstLast": "Primero último", + "followUs": "Síganos", + "footerLabel": "Etiqueta de pie de página", + "footerLink": "Enlace de pie de página", + "frequentlyAskedQuestions": "Preguntas frecuentes", + "gallery": "Galería", + "geomodifier": "Geomodificador", + "getDirections": "Obtener direcciones", + "header": "Encabezamiento", + "headerLink": "Enlace de encabezado", + "hours": "Horas", + "information": "Información", + "insights": "Perspectivas", + "learnMore": "Más información", + "logo": "Logo", + "meetOurTeam": "Conozca a nuestro equipo", + "name": "Nombre", + "nearbyLocations": "Ubicaciones cercanas", + "phone": "Teléfono", + "price": "$123.00", + "productName": "Nombre del producto", + "professionalName": "Nombre profesional", + "professionalTitle": "Título profesional", + "readMore": "Leer más", + "services": "Servicios", + "servicesOffered": "Servicios ofrecidos", + "subtitle": "Subtitular", + "text": "Texto", + "upcomingEvents": "Próximos eventos", + "visitProfile": "Visitar perfil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Imagen de utilidad {{number}}" diff --git a/packages/visual-editor/locales/components/et/visual-editor.json b/packages/visual-editor/locales/components/et/visual-editor.json index 5e41d305a..eae663bfd 100644 --- a/packages/visual-editor/locales/components/et/visual-editor.json +++ b/packages/visual-editor/locales/components/et/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Suletud", "closesAtTime": "Suletakse {{time}}", "closesAtTimeWeek": "Suletakse kell {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Umbes [[name]]", + "articleName": "Artikli nimi", + "associateAgent": "Abiagent", + "bannerText": "Bänneri tekst", + "businessName": "Ettevõtte nimi", + "button": "Nupp", + "callToAction": "Üleskutse tegevusele", + "category": "Kategooria", + "contactMe": "Võtke minuga ühendust", + "credentials": "Mandaat", + "directoryRoot": "Kataloogi juur", + "eventImage": "Sündmuse pilt", + "eventTitle": "Sündmuse pealkiri", + "featuredProducts": "Esiletõstetud tooted", + "featuredPromotion": "Esiletõstetud reklaam", + "featuredTestimonials": "Esiletõstetud iseloomustused", + "findALocation": "Leidke asukoht", + "firstLast": "Esimene Viimane", + "followUs": "Jälgi meid", + "footerLabel": "Jaluse silt", + "footerLink": "Jaluse link", + "frequentlyAskedQuestions": "Korduma kippuvad küsimused", + "gallery": "Galerii", + "geomodifier": "Geomodifier", + "getDirections": "Hankige juhiseid", + "header": "Päis", + "headerLink": "Päise link", + "hours": "Tööaeg", + "information": "Teave", + "insights": "Ülevaated", + "learnMore": "Lisateave", + "logo": "Logo", + "meetOurTeam": "Tutvuge meie meeskonnaga", + "name": "Nimi", + "nearbyLocations": "Lähedal asuvad asukohad", + "phone": "Telefon", + "price": "123,00 €", + "productName": "Toote nimi", + "professionalName": "Professionaalne nimi", + "professionalTitle": "Ametinimetus", + "readMore": "Lugege rohkem", + "services": "Teenused", + "servicesOffered": "Pakutavad teenused", + "subtitle": "Alapealkiri", + "text": "Tekst", + "upcomingEvents": "Eelseisvad sündmused", + "visitProfile": "Külastage profiili" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Kasulik pilt {{number}}" diff --git a/packages/visual-editor/locales/components/fi/visual-editor.json b/packages/visual-editor/locales/components/fi/visual-editor.json index 66bc8bd6a..f89fad864 100644 --- a/packages/visual-editor/locales/components/fi/visual-editor.json +++ b/packages/visual-editor/locales/components/fi/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Suljettu", "closesAtTime": "Suljetaan {{time}}", "closesAtTimeWeek": "Suljetaan klo {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Tietoja paikasta [[name]]", + "articleName": "Artikkelin nimi", + "associateAgent": "Apulaisagentti", + "bannerText": "Bannerin teksti", + "businessName": "Yrityksen nimi", + "button": "Painike", + "callToAction": "Toimintakehotus", + "category": "Luokka", + "contactMe": "Ota minuun yhteyttä", + "credentials": "Valtuustiedot", + "directoryRoot": "Hakemiston juuri", + "eventImage": "Tapahtuman kuva", + "eventTitle": "Tapahtuman otsikko", + "featuredProducts": "Suositellut tuotteet", + "featuredPromotion": "Suositeltu kampanja", + "featuredTestimonials": "Suositellut suosittelut", + "findALocation": "Etsi sijainti", + "firstLast": "Ensimmäinen Viimeinen", + "followUs": "Seuraa meitä", + "footerLabel": "Alatunnisteen etiketti", + "footerLink": "Alatunnisteen linkki", + "frequentlyAskedQuestions": "Usein kysytyt kysymykset", + "gallery": "Galleria", + "geomodifier": "Geomodifier", + "getDirections": "Hanki reittiohjeet", + "header": "Otsikko", + "headerLink": "Otsikkolinkki", + "hours": "Tuntia", + "information": "Tiedot", + "insights": "Näkemyksiä", + "learnMore": "Lisätietoja", + "logo": "Logo", + "meetOurTeam": "Tutustu tiimiimme", + "name": "Nimi", + "nearbyLocations": "Läheiset paikat", + "phone": "Puhelin", + "price": "123,00 €", + "productName": "Tuotteen nimi", + "professionalName": "Ammattilaisen nimi", + "professionalTitle": "Ammattinimike", + "readMore": "Lue lisää", + "services": "Palvelut", + "servicesOffered": "Tarjotut palvelut", + "subtitle": "Alaotsikko", + "text": "Teksti", + "upcomingEvents": "Tulevat tapahtumat", + "visitProfile": "Vieraile profiilissa" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Hyötykuva {{number}}" diff --git a/packages/visual-editor/locales/components/fr/visual-editor.json b/packages/visual-editor/locales/components/fr/visual-editor.json index 731718858..1bb2488c7 100644 --- a/packages/visual-editor/locales/components/fr/visual-editor.json +++ b/packages/visual-editor/locales/components/fr/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Fermé", "closesAtTime": "Ferme à {{time}}", "closesAtTimeWeek": "Ferme à {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "À propos de [[name]]", + "articleName": "Nom de l'article", + "associateAgent": "Agent associé", + "bannerText": "Texte de la bannière", + "businessName": "Nom de l'entreprise", + "button": "Bouton", + "callToAction": "Appel à l'action", + "category": "Catégorie", + "contactMe": "Contactez-moi", + "credentials": "Informations d'identification", + "directoryRoot": "Racine du répertoire", + "eventImage": "Image de l'événement", + "eventTitle": "Titre de l'événement", + "featuredProducts": "Produits en vedette", + "featuredPromotion": "Promotion en vedette", + "featuredTestimonials": "Témoignages en vedette", + "findALocation": "Trouver un emplacement", + "firstLast": "Premier Dernier", + "followUs": "Suivez-nous", + "footerLabel": "Étiquette de pied de page", + "footerLink": "Lien de pied de page", + "frequentlyAskedQuestions": "Foire aux questions", + "gallery": "Galerie", + "geomodifier": "Géomodificateur", + "getDirections": "Obtenir un itinéraire", + "header": "En-tête", + "headerLink": "Lien d'en-tête", + "hours": "Heures", + "information": "Information", + "insights": "Connaissances", + "learnMore": "En savoir plus", + "logo": "Logo", + "meetOurTeam": "Rencontrez notre équipe", + "name": "Nom", + "nearbyLocations": "Emplacements à proximité", + "phone": "Téléphone", + "price": "123,00 €", + "productName": "Nom du produit", + "professionalName": "Nom professionnel", + "professionalTitle": "Titre professionnel", + "readMore": "En savoir plus", + "services": "Services", + "servicesOffered": "Services offerts", + "subtitle": "Sous-titre", + "text": "Texte", + "upcomingEvents": "Événements à venir", + "visitProfile": "Visiter le profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Image utilitaire {{number}}" diff --git a/packages/visual-editor/locales/components/hr/visual-editor.json b/packages/visual-editor/locales/components/hr/visual-editor.json index a6b10e801..0f2950f05 100644 --- a/packages/visual-editor/locales/components/hr/visual-editor.json +++ b/packages/visual-editor/locales/components/hr/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Zatvoreno", "closesAtTime": "Zatvara se u {{time}}", "closesAtTimeWeek": "Zatvara se u {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "O [[name]]", + "articleName": "Naziv artikla", + "associateAgent": "Pridruženi agent", + "bannerText": "Tekst natpisa", + "businessName": "Naziv tvrtke", + "button": "Gumb", + "callToAction": "Poziv na akciju", + "category": "Kategorija", + "contactMe": "Kontaktirajte me", + "credentials": "Vjerodajnice", + "directoryRoot": "Korijen imenika", + "eventImage": "Slika događaja", + "eventTitle": "Naslov događaja", + "featuredProducts": "Istaknuti proizvodi", + "featuredPromotion": "Istaknuta promocija", + "featuredTestimonials": "Istaknuta svjedočanstva", + "findALocation": "Pronađite lokaciju", + "firstLast": "Prvi Zadnji", + "followUs": "Pratite nas", + "footerLabel": "Oznaka podnožja", + "footerLink": "Veza podnožja", + "frequentlyAskedQuestions": "Često postavljana pitanja", + "gallery": "Galerija", + "geomodifier": "Geomodifier", + "getDirections": "Dobiti upute", + "header": "Zaglavlje", + "headerLink": "Veza zaglavlja", + "hours": "Sati", + "information": "Informacija", + "insights": "Uvidi", + "learnMore": "Saznajte više", + "logo": "Logo", + "meetOurTeam": "Upoznajte naš tim", + "name": "Ime", + "nearbyLocations": "Lokacije u blizini", + "phone": "Telefon", + "price": "123,00 €", + "productName": "Naziv proizvoda", + "professionalName": "Profesionalni naziv", + "professionalTitle": "Stručno zvanje", + "readMore": "Pročitaj više", + "services": "Usluge", + "servicesOffered": "Ponuđene usluge", + "subtitle": "Podnaslov", + "text": "Tekst", + "upcomingEvents": "Nadolazeći događaji", + "visitProfile": "Posjetite profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Uslužna slika {{number}}" diff --git a/packages/visual-editor/locales/components/hu/visual-editor.json b/packages/visual-editor/locales/components/hu/visual-editor.json index 205c317d9..e45e24569 100644 --- a/packages/visual-editor/locales/components/hu/visual-editor.json +++ b/packages/visual-editor/locales/components/hu/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Zárt", "closesAtTime": "Zárás: {{time}}", "closesAtTimeWeek": "Zárás: {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Körülbelül [[name]]", + "articleName": "Cikk neve", + "associateAgent": "társult ügynök", + "bannerText": "Banner szöveg", + "businessName": "Vállalkozás neve", + "button": "Gomb", + "callToAction": "Felhívás cselekvésre", + "category": "Kategória", + "contactMe": "Lépjen kapcsolatba velem", + "credentials": "Hitelesítő adatok", + "directoryRoot": "Címtárgyökér", + "eventImage": "Esemény képe", + "eventTitle": "Esemény címe", + "featuredProducts": "Kiemelt termékek", + "featuredPromotion": "Kiemelt promóció", + "featuredTestimonials": "Kiemelt ajánlások", + "findALocation": "Hely keresése", + "firstLast": "Első Utolsó", + "followUs": "Kövess minket", + "footerLabel": "Lábléc címke", + "footerLink": "Lábléc hivatkozás", + "frequentlyAskedQuestions": "Gyakran Ismételt Kérdések", + "gallery": "Galéria", + "geomodifier": "Geomodifikátor", + "getDirections": "Útvonalterv", + "header": "Fejléc", + "headerLink": "Fejléc hivatkozás", + "hours": "Órák", + "information": "Információ", + "insights": "Betekintés", + "learnMore": "További információ", + "logo": "Logó", + "meetOurTeam": "Ismerje meg csapatunkat", + "name": "Név", + "nearbyLocations": "Közeli helyek", + "phone": "Telefon", + "price": "123 euró", + "productName": "Termék neve", + "professionalName": "Szakmai név", + "professionalTitle": "Szakmai cím", + "readMore": "Olvasson tovább", + "services": "Szolgáltatások", + "servicesOffered": "Ajánlott szolgáltatások", + "subtitle": "Felirat", + "text": "Szöveg", + "upcomingEvents": "Közelgő események", + "visitProfile": "Látogassa meg a Profilt" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Segédkép {{number}}" diff --git a/packages/visual-editor/locales/components/it/visual-editor.json b/packages/visual-editor/locales/components/it/visual-editor.json index 9483df31a..d35cf1abc 100644 --- a/packages/visual-editor/locales/components/it/visual-editor.json +++ b/packages/visual-editor/locales/components/it/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Chiuso", "closesAtTime": "Chiude alle {{time}}", "closesAtTimeWeek": "Chiude alle {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Informazioni su [[name]]", + "articleName": "Nome dell'articolo", + "associateAgent": "Agente associato", + "bannerText": "Testo della bandiera", + "businessName": "Nome dell'azienda", + "button": "Pulsante", + "callToAction": "Invito all'azione", + "category": "Categoria", + "contactMe": "Contattami", + "credentials": "Credenziali", + "directoryRoot": "Radice della directory", + "eventImage": "Immagine dell'evento", + "eventTitle": "Titolo dell'evento", + "featuredProducts": "Prodotti in evidenza", + "featuredPromotion": "Promozione in primo piano", + "featuredTestimonials": "Testimonianze in primo piano", + "findALocation": "Trova una posizione", + "firstLast": "Primo Ultimo", + "followUs": "Seguici", + "footerLabel": "Etichetta piè di pagina", + "footerLink": "Collegamento a piè di pagina", + "frequentlyAskedQuestions": "Domande frequenti", + "gallery": "Galleria", + "geomodifier": "Geomodificatore", + "getDirections": "Ottieni indicazioni stradali", + "header": "Intestazione", + "headerLink": "Collegamento dell'intestazione", + "hours": "Ore", + "information": "Informazioni", + "insights": "Approfondimenti", + "learnMore": "Saperne di più", + "logo": "Logo", + "meetOurTeam": "Incontra il nostro team", + "name": "Nome", + "nearbyLocations": "Località vicine", + "phone": "Telefono", + "price": "123,00 €", + "productName": "Nome del prodotto", + "professionalName": "Nome professionale", + "professionalTitle": "Titolo professionale", + "readMore": "Per saperne di più", + "services": "Servizi", + "servicesOffered": "Servizi offerti", + "subtitle": "Sottotitolo", + "text": "Testo", + "upcomingEvents": "Prossimi eventi", + "visitProfile": "Visita il profilo" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Immagine utilità {{number}}" diff --git a/packages/visual-editor/locales/components/ja/visual-editor.json b/packages/visual-editor/locales/components/ja/visual-editor.json index e6e36244e..de5ecbfc0 100644 --- a/packages/visual-editor/locales/components/ja/visual-editor.json +++ b/packages/visual-editor/locales/components/ja/visual-editor.json @@ -17,6 +17,55 @@ "closed": "閉店", "closesAtTime": "{{time}}に閉まります", "closesAtTimeWeek": "{{time}} {{dayOfWeek}} に閉店", + "componentDefaults": { + "aboutName": "[[name]] について", + "articleName": "記事名", + "associateAgent": "アソシエイトエージェント", + "bannerText": "バナーテキスト", + "businessName": "商号", + "button": "ボタン", + "callToAction": "行動喚起", + "category": "カテゴリ", + "contactMe": "連絡してください", + "credentials": "資格", + "directoryRoot": "ディレクトリルート", + "eventImage": "イベント画像", + "eventTitle": "イベントタイトル", + "featuredProducts": "注目の製品", + "featuredPromotion": "注目のプロモーション", + "featuredTestimonials": "注目のお客様の声", + "findALocation": "場所を探す", + "firstLast": "姓名", + "followUs": "フォローしてください", + "footerLabel": "フッターラベル", + "footerLink": "フッターリンク", + "frequentlyAskedQuestions": "よくある質問", + "gallery": "ギャラリー", + "geomodifier": "ジオモディファイアー", + "getDirections": "道順を調べる", + "header": "ヘッダー", + "headerLink": "ヘッダーリンク", + "hours": "営業時間", + "information": "情報", + "insights": "洞察", + "learnMore": "もっと詳しく知る", + "logo": "ロゴ", + "meetOurTeam": "私たちのチームのご紹介", + "name": "名前", + "nearbyLocations": "近くの場所", + "phone": "電話", + "price": "¥123", + "productName": "製品名", + "professionalName": "専門職名", + "professionalTitle": "専門職の称号", + "readMore": "続きを読む", + "services": "サービス", + "servicesOffered": "提供されるサービス", + "subtitle": "小見出し", + "text": "文章", + "upcomingEvents": "今後のイベント", + "visitProfile": "プロフィールにアクセス" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "ユーティリティ イメージ {{number}}" diff --git a/packages/visual-editor/locales/components/lt/visual-editor.json b/packages/visual-editor/locales/components/lt/visual-editor.json index 87934731e..68c469a62 100644 --- a/packages/visual-editor/locales/components/lt/visual-editor.json +++ b/packages/visual-editor/locales/components/lt/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Uždarytas", "closesAtTime": "Uždaroma {{time}}", "closesAtTimeWeek": "Uždaroma {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Apie [[name]]", + "articleName": "Straipsnio pavadinimas", + "associateAgent": "Asocijuotasis agentas", + "bannerText": "Reklaminio skydelio tekstas", + "businessName": "Įmonės pavadinimas", + "button": "Mygtukas", + "callToAction": "Raginimas veikti", + "category": "Kategorija", + "contactMe": "Susisiekite su manimi", + "credentials": "Įgaliojimai", + "directoryRoot": "Katalogo šaknis", + "eventImage": "Įvykio vaizdas", + "eventTitle": "Renginio pavadinimas", + "featuredProducts": "Teminiai produktai", + "featuredPromotion": "Teminė reklama", + "featuredTestimonials": "Teminiai atsiliepimai", + "findALocation": "Raskite vietą", + "firstLast": "Pirmas Paskutinis", + "followUs": "Sekite mus", + "footerLabel": "Poraštės etiketė", + "footerLink": "Poraštės nuoroda", + "frequentlyAskedQuestions": "Dažnai užduodami klausimai", + "gallery": "Galerija", + "geomodifier": "Geomodifikatorius", + "getDirections": "Gaukite nuorodas", + "header": "Antraštė", + "headerLink": "Antraštės nuoroda", + "hours": "Valandos", + "information": "Informacija", + "insights": "Įžvalgos", + "learnMore": "Sužinokite daugiau", + "logo": "Logotipas", + "meetOurTeam": "Susipažinkite su mūsų komanda", + "name": "Vardas", + "nearbyLocations": "Netoliese esančios vietos", + "phone": "Telefonas", + "price": "123,00 USD", + "productName": "Produkto pavadinimas", + "professionalName": "Profesionalus vardas", + "professionalTitle": "Profesinis titulas", + "readMore": "Skaityti daugiau", + "services": "Paslaugos", + "servicesOffered": "Siūlomos paslaugos", + "subtitle": "Subtitrai", + "text": "Tekstas", + "upcomingEvents": "Būsimi įvykiai", + "visitProfile": "Apsilankykite profilyje" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Naudingumo vaizdas {{number}}" diff --git a/packages/visual-editor/locales/components/lv/visual-editor.json b/packages/visual-editor/locales/components/lv/visual-editor.json index e398df495..d9724c04b 100644 --- a/packages/visual-editor/locales/components/lv/visual-editor.json +++ b/packages/visual-editor/locales/components/lv/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Slēgts", "closesAtTime": "Tiek slēgts plkst. {{time}}", "closesAtTimeWeek": "Tiek slēgts plkst. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Aptuveni [[name]]", + "articleName": "Raksta nosaukums", + "associateAgent": "Asociētais aģents", + "bannerText": "Reklāmkaroga teksts", + "businessName": "Uzņēmuma nosaukums", + "button": "Poga", + "callToAction": "Aicinājums uz darbību", + "category": "Kategorija", + "contactMe": "Sazinieties ar mani", + "credentials": "Akreditācijas dati", + "directoryRoot": "Direktorija sakne", + "eventImage": "Pasākuma attēls", + "eventTitle": "Pasākuma nosaukums", + "featuredProducts": "Piedāvātie produkti", + "featuredPromotion": "Piedāvātā akcija", + "featuredTestimonials": "Piedāvātās atsauksmes", + "findALocation": "Atrodiet atrašanās vietu", + "firstLast": "Pirmais Pēdējais", + "followUs": "Sekojiet mums", + "footerLabel": "Kājenes etiķete", + "footerLink": "Kājenes saite", + "frequentlyAskedQuestions": "Bieži uzdotie jautājumi", + "gallery": "Galerija", + "geomodifier": "Ģeomodifikators", + "getDirections": "Saņemiet norādes", + "header": "Virsraksts", + "headerLink": "Galvenes saite", + "hours": "Stundas", + "information": "Informācija", + "insights": "Ieskats", + "learnMore": "Uzziniet vairāk", + "logo": "Logotips", + "meetOurTeam": "Iepazīstieties ar mūsu komandu", + "name": "Vārds", + "nearbyLocations": "Atrašanās vietas tuvumā", + "phone": "Tālrunis", + "price": "123,00 USD", + "productName": "Produkta nosaukums", + "professionalName": "Profesionālais vārds", + "professionalTitle": "Profesionālais tituls", + "readMore": "Lasīt vairāk", + "services": "Pakalpojumi", + "servicesOffered": "Piedāvātie pakalpojumi", + "subtitle": "Apakšvirsraksts", + "text": "Teksts", + "upcomingEvents": "Gaidāmie notikumi", + "visitProfile": "Apmeklējiet profilu" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Lietderības attēls {{number}}" diff --git a/packages/visual-editor/locales/components/nb/visual-editor.json b/packages/visual-editor/locales/components/nb/visual-editor.json index 06c19927d..c09404f55 100644 --- a/packages/visual-editor/locales/components/nb/visual-editor.json +++ b/packages/visual-editor/locales/components/nb/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Lukket", "closesAtTime": "Stenger kl. {{time}}", "closesAtTimeWeek": "Stenger kl. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Om [[name]]", + "articleName": "Artikkelnavn", + "associateAgent": "Tilknyttet agent", + "bannerText": "Bannertekst", + "businessName": "Bedriftsnavn", + "button": "Knapp", + "callToAction": "Ring til handling", + "category": "Kategori", + "contactMe": "Kontakt meg", + "credentials": "Legitimasjon", + "directoryRoot": "Katalogrot", + "eventImage": "Hendelsesbilde", + "eventTitle": "Begivenhetstittel", + "featuredProducts": "Utvalgte produkter", + "featuredPromotion": "Utvalgt kampanje", + "featuredTestimonials": "Utvalgte attester", + "findALocation": "Finn en plassering", + "firstLast": "Første Siste", + "followUs": "Følg oss", + "footerLabel": "Bunntekstetikett", + "footerLink": "Bunntekstlenke", + "frequentlyAskedQuestions": "Ofte stilte spørsmål", + "gallery": "Galleri", + "geomodifier": "Geomodifikator", + "getDirections": "Få veibeskrivelse", + "header": "Overskrift", + "headerLink": "Overskriftskobling", + "hours": "Timer", + "information": "Informasjon", + "insights": "Innsikt", + "learnMore": "Lær mer", + "logo": "Logo", + "meetOurTeam": "Møt teamet vårt", + "name": "Navn", + "nearbyLocations": "Steder i nærheten", + "phone": "Telefon", + "price": "123,00 kr", + "productName": "Produktnavn", + "professionalName": "Profesjonelt navn", + "professionalTitle": "Yrkestittel", + "readMore": "Les mer", + "services": "Tjenester", + "servicesOffered": "Tjenester som tilbys", + "subtitle": "Undertekst", + "text": "Tekst", + "upcomingEvents": "Kommende arrangementer", + "visitProfile": "Besøk profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Verktøybilde {{number}}" diff --git a/packages/visual-editor/locales/components/nl/visual-editor.json b/packages/visual-editor/locales/components/nl/visual-editor.json index 620810d79..6135a461b 100644 --- a/packages/visual-editor/locales/components/nl/visual-editor.json +++ b/packages/visual-editor/locales/components/nl/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Gesloten", "closesAtTime": "Sluit om {{time}}", "closesAtTimeWeek": "Sluit om {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Over [[name]]", + "articleName": "Artikelnaam", + "associateAgent": "Associate-agent", + "bannerText": "Bannertekst", + "businessName": "Bedrijfsnaam", + "button": "Knop", + "callToAction": "Oproep tot actie", + "category": "Categorie", + "contactMe": "Neem contact met mij op", + "credentials": "Referenties", + "directoryRoot": "Directorywortel", + "eventImage": "Evenement afbeelding", + "eventTitle": "Titel van evenement", + "featuredProducts": "Uitgelichte producten", + "featuredPromotion": "Uitgelichte promotie", + "featuredTestimonials": "Uitgelichte getuigenissen", + "findALocation": "Vind een locatie", + "firstLast": "Eerste Laatste", + "followUs": "Volg ons", + "footerLabel": "Voettekstlabel", + "footerLink": "Voettekstlink", + "frequentlyAskedQuestions": "Veelgestelde vragen", + "gallery": "Galerij", + "geomodifier": "Geomodificator", + "getDirections": "Routebeschrijving opvragen", + "header": "Koptekst", + "headerLink": "Koplink", + "hours": "Uren", + "information": "Informatie", + "insights": "Inzichten", + "learnMore": "Meer informatie", + "logo": "Logo", + "meetOurTeam": "Maak kennis met ons team", + "name": "Naam", + "nearbyLocations": "Locaties in de buurt", + "phone": "Telefoon", + "price": "123,00 €", + "productName": "Productnaam", + "professionalName": "Professionele naam", + "professionalTitle": "Professionele titel", + "readMore": "Lees meer", + "services": "Diensten", + "servicesOffered": "Aangeboden diensten", + "subtitle": "Ondertitel", + "text": "Tekst", + "upcomingEvents": "Aankomende evenementen", + "visitProfile": "Bezoek profiel" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Hulpprogramma-afbeelding {{number}}" diff --git a/packages/visual-editor/locales/components/pl/visual-editor.json b/packages/visual-editor/locales/components/pl/visual-editor.json index 5b393f0aa..91a62d4bd 100644 --- a/packages/visual-editor/locales/components/pl/visual-editor.json +++ b/packages/visual-editor/locales/components/pl/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Zamknięte", "closesAtTime": "Zamyka się o {{time}}", "closesAtTimeWeek": "Zamyka się o {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Informacje o [[name]]", + "articleName": "Nazwa artykułu", + "associateAgent": "Agent stowarzyszony", + "bannerText": "Tekst banera", + "businessName": "Nazwa firmy", + "button": "Przycisk", + "callToAction": "Wezwanie do działania", + "category": "Kategoria", + "contactMe": "Skontaktuj się ze mną", + "credentials": "Referencje", + "directoryRoot": "Katalog główny", + "eventImage": "Obraz wydarzenia", + "eventTitle": "Tytuł wydarzenia", + "featuredProducts": "Polecane produkty", + "featuredPromotion": "Wyróżniona promocja", + "featuredTestimonials": "Wyróżnione referencje", + "findALocation": "Znajdź lokalizację", + "firstLast": "Pierwszy Ostatni", + "followUs": "Śledź nas", + "footerLabel": "Etykieta stopki", + "footerLink": "Link do stopki", + "frequentlyAskedQuestions": "Często zadawane pytania", + "gallery": "Galeria", + "geomodifier": "Geomodyfikator", + "getDirections": "Uzyskaj wskazówki", + "header": "Nagłówek", + "headerLink": "Link do nagłówka", + "hours": "Godziny", + "information": "Informacja", + "insights": "Spostrzeżenia", + "learnMore": "Dowiedz się więcej", + "logo": "Logo", + "meetOurTeam": "Poznaj nasz zespół", + "name": "Nazwa", + "nearbyLocations": "Pobliskie lokalizacje", + "phone": "Telefon", + "price": "123,00 zł", + "productName": "Nazwa produktu", + "professionalName": "Nazwa zawodowa", + "professionalTitle": "Tytuł zawodowy", + "readMore": "Przeczytaj więcej", + "services": "Usługi", + "servicesOffered": "Oferowane usługi", + "subtitle": "Podtytuł", + "text": "Tekst", + "upcomingEvents": "Nadchodzące wydarzenia", + "visitProfile": "Odwiedź profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Obraz użytkowy {{number}}" diff --git a/packages/visual-editor/locales/components/pt/visual-editor.json b/packages/visual-editor/locales/components/pt/visual-editor.json index 64a4026c8..5de2a44d7 100644 --- a/packages/visual-editor/locales/components/pt/visual-editor.json +++ b/packages/visual-editor/locales/components/pt/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Fechado", "closesAtTime": "Fecha às {{time}}", "closesAtTimeWeek": "Fecha às {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Sobre [[name]]", + "articleName": "Nome do artigo", + "associateAgent": "Agente Associado", + "bannerText": "Texto do banner", + "businessName": "Nome comercial", + "button": "Botão", + "callToAction": "Chamada para ação", + "category": "Categoria", + "contactMe": "Entre em contato comigo", + "credentials": "Credenciais", + "directoryRoot": "Raiz do diretório", + "eventImage": "Imagem do Evento", + "eventTitle": "Título do Evento", + "featuredProducts": "Produtos em destaque", + "featuredPromotion": "Promoção em destaque", + "featuredTestimonials": "Depoimentos em destaque", + "findALocation": "Encontre um local", + "firstLast": "Primeiro Último", + "followUs": "Siga-nos", + "footerLabel": "Etiqueta de rodapé", + "footerLink": "Link do rodapé", + "frequentlyAskedQuestions": "Perguntas frequentes", + "gallery": "Galeria", + "geomodifier": "Geomodificador", + "getDirections": "Obter direções", + "header": "Cabeçalho", + "headerLink": "Link do cabeçalho", + "hours": "Horas", + "information": "Informação", + "insights": "Percepções", + "learnMore": "Saber mais", + "logo": "Logotipo", + "meetOurTeam": "Conheça nossa equipe", + "name": "Nome", + "nearbyLocations": "Locais próximos", + "phone": "Telefone", + "price": "R$ 123,00", + "productName": "Nome do produto", + "professionalName": "Nome Profissional", + "professionalTitle": "Título Profissional", + "readMore": "Leia mais", + "services": "Serviços", + "servicesOffered": "Serviços oferecidos", + "subtitle": "Legenda", + "text": "Texto", + "upcomingEvents": "Próximos eventos", + "visitProfile": "Visitar perfil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Imagem utilitária {{number}}" diff --git a/packages/visual-editor/locales/components/ro/visual-editor.json b/packages/visual-editor/locales/components/ro/visual-editor.json index faa3bad5b..b6c12a25c 100644 --- a/packages/visual-editor/locales/components/ro/visual-editor.json +++ b/packages/visual-editor/locales/components/ro/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Închis", "closesAtTime": "Se închide la {{time}}", "closesAtTimeWeek": "Se închide la {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Despre [[name]]", + "articleName": "Nume articol", + "associateAgent": "Agent asociat", + "bannerText": "Text banner", + "businessName": "Numele companiei", + "button": "Buton", + "callToAction": "Apel la acțiune", + "category": "Categorie", + "contactMe": "Contactați-mă", + "credentials": "Acreditări", + "directoryRoot": "Rădăcină director", + "eventImage": "Imaginea evenimentului", + "eventTitle": "Titlul evenimentului", + "featuredProducts": "Produse recomandate", + "featuredPromotion": "Promoție recomandată", + "featuredTestimonials": "Mărturii recomandate", + "findALocation": "Găsiți o locație", + "firstLast": "Primul Ultimul", + "followUs": "Urmați-ne", + "footerLabel": "Etichetă de subsol", + "footerLink": "Link de subsol", + "frequentlyAskedQuestions": "Întrebări frecvente", + "gallery": "Galerie", + "geomodifier": "Geomodificator", + "getDirections": "Obțineți indicații", + "header": "Antet", + "headerLink": "Link antet", + "hours": "Ore", + "information": "Informaţii", + "insights": "Perspective", + "learnMore": "Află mai multe", + "logo": "Logo", + "meetOurTeam": "Faceți cunoștință cu echipa noastră", + "name": "Nume", + "nearbyLocations": "Locații din apropiere", + "phone": "Telefon", + "price": "123,00 RON", + "productName": "Numele produsului", + "professionalName": "Nume profesional", + "professionalTitle": "Titlul profesional", + "readMore": "Citiți mai mult", + "services": "Servicii", + "servicesOffered": "Servicii oferite", + "subtitle": "Subtitlu", + "text": "Text", + "upcomingEvents": "Evenimente viitoare", + "visitProfile": "Vizitați profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Imagine utilitar {{number}}" diff --git a/packages/visual-editor/locales/components/sk/visual-editor.json b/packages/visual-editor/locales/components/sk/visual-editor.json index 5403778b9..5aedd8289 100644 --- a/packages/visual-editor/locales/components/sk/visual-editor.json +++ b/packages/visual-editor/locales/components/sk/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Zatvorené", "closesAtTime": "Zatvára sa o {{time}}", "closesAtTimeWeek": "Zatvára sa o {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "O [[name]]", + "articleName": "Názov článku", + "associateAgent": "Pridružený agent", + "bannerText": "Text bannera", + "businessName": "Obchodné meno", + "button": "Tlačidlo", + "callToAction": "Výzva na akciu", + "category": "Kategória", + "contactMe": "Kontaktujte ma", + "credentials": "Poverenia", + "directoryRoot": "Koreň adresára", + "eventImage": "Obrázok udalosti", + "eventTitle": "Názov udalosti", + "featuredProducts": "Odporúčané produkty", + "featuredPromotion": "Odporúčaná propagácia", + "featuredTestimonials": "Odporúčané referencie", + "findALocation": "Nájdite miesto", + "firstLast": "Prvý posledný", + "followUs": "Sledujte nás", + "footerLabel": "Štítok päty", + "footerLink": "Odkaz v päte", + "frequentlyAskedQuestions": "Často kladené otázky", + "gallery": "Galéria", + "geomodifier": "Geomodifikátor", + "getDirections": "Získajte trasu", + "header": "Hlavička", + "headerLink": "Odkaz na hlavičku", + "hours": "Hodiny", + "information": "Informácie", + "insights": "Insights", + "learnMore": "Zistite viac", + "logo": "Logo", + "meetOurTeam": "Spoznajte náš tím", + "name": "Meno", + "nearbyLocations": "Polohy v okolí", + "phone": "Telefón", + "price": "123,00 dolárov", + "productName": "Názov produktu", + "professionalName": "Profesionálne meno", + "professionalTitle": "Profesionálny titul", + "readMore": "Prečítajte si viac", + "services": "Služby", + "servicesOffered": "Ponúkané služby", + "subtitle": "Podnadpis", + "text": "Text", + "upcomingEvents": "Nadchádzajúce udalosti", + "visitProfile": "Navštívte profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Pomocný obrázok {{number}}" diff --git a/packages/visual-editor/locales/components/sv/visual-editor.json b/packages/visual-editor/locales/components/sv/visual-editor.json index 54e327b49..88741bc03 100644 --- a/packages/visual-editor/locales/components/sv/visual-editor.json +++ b/packages/visual-editor/locales/components/sv/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Stängd", "closesAtTime": "Stänger kl. {{time}}", "closesAtTimeWeek": "Stänger kl. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Om [[name]]", + "articleName": "Artikelnamn", + "associateAgent": "Associerad agent", + "bannerText": "Bannertext", + "businessName": "Företagsnamn", + "button": "Knapp", + "callToAction": "Uppmaning till handling", + "category": "Kategori", + "contactMe": "Kontakta mig", + "credentials": "Referenser", + "directoryRoot": "Katalogrot", + "eventImage": "Händelsebild", + "eventTitle": "Händelsens titel", + "featuredProducts": "Utvalda produkter", + "featuredPromotion": "Utvald kampanj", + "featuredTestimonials": "Utvalda vittnesmål", + "findALocation": "Hitta en plats", + "firstLast": "Första Sista", + "followUs": "Följ oss", + "footerLabel": "Sidfotsetikett", + "footerLink": "Sidfotlänkar", + "frequentlyAskedQuestions": "Vanliga frågor", + "gallery": "Galleri", + "geomodifier": "Geomodifierare", + "getDirections": "Få vägbeskrivningar", + "header": "Rubrik", + "headerLink": "Rubriklänk", + "hours": "Timmar", + "information": "Information", + "insights": "Insikter", + "learnMore": "Läs mer", + "logo": "Logotyp", + "meetOurTeam": "Möt vårt team", + "name": "Namn", + "nearbyLocations": "Närliggande platser", + "phone": "Telefon", + "price": "123,00 SEK", + "productName": "Produktnamn", + "professionalName": "Professionellt namn", + "professionalTitle": "Yrkestitel", + "readMore": "Läs mer", + "services": "Tjänster", + "servicesOffered": "Tjänster som erbjuds", + "subtitle": "Underrubrik", + "text": "Text", + "upcomingEvents": "Kommande evenemang", + "visitProfile": "Besök profil" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Verktygsbild {{number}}" diff --git a/packages/visual-editor/locales/components/tr/visual-editor.json b/packages/visual-editor/locales/components/tr/visual-editor.json index 7b4702e0a..b60b2a3a2 100644 --- a/packages/visual-editor/locales/components/tr/visual-editor.json +++ b/packages/visual-editor/locales/components/tr/visual-editor.json @@ -17,6 +17,55 @@ "closed": "Kapalı", "closesAtTime": "{{time}} itibarıyla kapanıyor", "closesAtTimeWeek": "{{time}} {{dayOfWeek}} itibarıyla kapanıyor", + "componentDefaults": { + "aboutName": "[[name]] Hakkında", + "articleName": "Makale Adı", + "associateAgent": "Yardımcı Temsilci", + "bannerText": "Banner Metni", + "businessName": "İşletme Adı", + "button": "Düğme", + "callToAction": "Eylem Çağrısı", + "category": "Kategori", + "contactMe": "Bana Ulaşın", + "credentials": "Kimlik bilgileri", + "directoryRoot": "Dizin Kökü", + "eventImage": "Etkinlik Resmi", + "eventTitle": "Etkinlik Başlığı", + "featuredProducts": "Öne Çıkan Ürünler", + "featuredPromotion": "Öne Çıkan Promosyon", + "featuredTestimonials": "Öne Çıkan Görüşler", + "findALocation": "Konum Bul", + "firstLast": "İlk Son", + "followUs": "Bizi takip edin", + "footerLabel": "Alt Bilgi Etiketi", + "footerLink": "Alt Bilgi Bağlantısı", + "frequentlyAskedQuestions": "Sıkça Sorulan Sorular", + "gallery": "Galeri", + "geomodifier": "Geomodifier", + "getDirections": "Yol Tarifi Al", + "header": "Başlık", + "headerLink": "Başlık Bağlantısı", + "hours": "Saat", + "information": "Bilgi", + "insights": "Analizler", + "learnMore": "Daha fazla bilgi edin", + "logo": "Logo", + "meetOurTeam": "Ekibimizle Tanışın", + "name": "İsim", + "nearbyLocations": "Yakın Yerler", + "phone": "Telefon", + "price": "₺123", + "productName": "Ürün Adı", + "professionalName": "Meslek Adı", + "professionalTitle": "Mesleki Ünvan", + "readMore": "Devamını oku", + "services": "Hizmetler", + "servicesOffered": "Sunulan Hizmetler", + "subtitle": "Altyazı", + "text": "Metin", + "upcomingEvents": "Yaklaşan Etkinlikler", + "visitProfile": "Profili Ziyaret Et" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "Yardımcı Resim {{number}}" diff --git a/packages/visual-editor/locales/components/zh-TW/visual-editor.json b/packages/visual-editor/locales/components/zh-TW/visual-editor.json index 0acc63fcb..2d22714b7 100644 --- a/packages/visual-editor/locales/components/zh-TW/visual-editor.json +++ b/packages/visual-editor/locales/components/zh-TW/visual-editor.json @@ -17,6 +17,55 @@ "closed": "關閉", "closesAtTime": "於 {{time}} 關閉", "closesAtTimeWeek": "於 {{time}} {{dayOfWeek}} 關閉", + "componentDefaults": { + "aboutName": "關於 [[name]]", + "articleName": "文章名稱", + "associateAgent": "助理代理", + "bannerText": "橫幅文字", + "businessName": "公司名稱", + "button": "按鈕", + "callToAction": "號召性用語", + "category": "類別", + "contactMe": "聯絡我", + "credentials": "證書", + "directoryRoot": "目錄根", + "eventImage": "活動圖片", + "eventTitle": "活動標題", + "featuredProducts": "特色產品", + "featuredPromotion": "特色促銷", + "featuredTestimonials": "特色推薦", + "findALocation": "尋找地點", + "firstLast": "名 姓", + "followUs": "跟著我們", + "footerLabel": "頁尾標籤", + "footerLink": "頁尾連結", + "frequentlyAskedQuestions": "常見問題解答", + "gallery": "畫廊", + "geomodifier": "地理修改器", + "getDirections": "獲取路線", + "header": "標頭", + "headerLink": "標題連結", + "hours": "時間", + "information": "資訊", + "insights": "見解", + "learnMore": "了解更多", + "logo": "標識", + "meetOurTeam": "認識我們的團隊", + "name": "姓名", + "nearbyLocations": "附近地點", + "phone": "電話", + "price": "NT$123.00", + "productName": "產品名稱", + "professionalName": "專業名稱", + "professionalTitle": "職稱", + "readMore": "閱讀更多", + "services": "服務", + "servicesOffered": "提供的服務", + "subtitle": "副標題", + "text": "文字", + "upcomingEvents": "即將舉行的活動", + "visitProfile": "訪問簡介" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "實用程序圖像 {{number}}" diff --git a/packages/visual-editor/locales/components/zh/visual-editor.json b/packages/visual-editor/locales/components/zh/visual-editor.json index a86815270..58a75fd67 100644 --- a/packages/visual-editor/locales/components/zh/visual-editor.json +++ b/packages/visual-editor/locales/components/zh/visual-editor.json @@ -17,6 +17,55 @@ "closed": "关闭", "closesAtTime": "于 {{time}} 关闭", "closesAtTimeWeek": "于 {{time}} {{dayOfWeek}} 关闭", + "componentDefaults": { + "aboutName": "关于 [[name]]", + "articleName": "文章名称", + "associateAgent": "助理代理", + "bannerText": "横幅文字", + "businessName": "公司名称", + "button": "按钮", + "callToAction": "号召性用语", + "category": "类别", + "contactMe": "联系我", + "credentials": "证书", + "directoryRoot": "目录根", + "eventImage": "活动图片", + "eventTitle": "活动标题", + "featuredProducts": "特色产品", + "featuredPromotion": "特色促销", + "featuredTestimonials": "特色推荐", + "findALocation": "寻找地点", + "firstLast": "第一个 最后一个", + "followUs": "关注我们", + "footerLabel": "页脚标签", + "footerLink": "页脚链接", + "frequentlyAskedQuestions": "常见问题解答", + "gallery": "画廊", + "geomodifier": "地理修改器", + "getDirections": "获取路线", + "header": "标头", + "headerLink": "标题链接", + "hours": "时间", + "information": "信息", + "insights": "见解", + "learnMore": "了解更多", + "logo": "标识", + "meetOurTeam": "认识我们的团队", + "name": "姓名", + "nearbyLocations": "附近地点", + "phone": "电话", + "price": "$123.00", + "productName": "产品名称", + "professionalName": "专业名称", + "professionalTitle": "职称", + "readMore": "阅读更多", + "services": "服务", + "servicesOffered": "提供的服务", + "subtitle": "副标题", + "text": "文本", + "upcomingEvents": "即将举行的活动", + "visitProfile": "访问简介" + }, "components": { "footerUtilityImagesSlot": { "defaultAlt": "实用程序图像 {{number}}" diff --git a/packages/visual-editor/locales/platform/cs/visual-editor.json b/packages/visual-editor/locales/platform/cs/visual-editor.json index 19fdcc0ee..c9dc34384 100644 --- a/packages/visual-editor/locales/platform/cs/visual-editor.json +++ b/packages/visual-editor/locales/platform/cs/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Zavřít menu", "closesAtTime": "Zavírá v {{time}}", "closesAtTimeWeek": "Zavírá v {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "O [[name]]", + "articleName": "Název článku", + "associateAgent": "Přidružený agent", + "bannerText": "Text banneru", + "businessName": "Obchodní název", + "button": "Tlačítko", + "callToAction": "Výzva k akci", + "category": "Kategorie", + "contactMe": "Kontaktujte mě", + "credentials": "Pověření", + "directoryRoot": "Kořen adresáře", + "eventImage": "Obrázek události", + "eventTitle": "Název události", + "featuredProducts": "Vybrané produkty", + "featuredPromotion": "Doporučená propagace", + "featuredTestimonials": "Doporučené posudky", + "findALocation": "Najděte polohu", + "firstLast": "První Poslední", + "followUs": "Sledujte nás", + "footerLabel": "Štítek zápatí", + "footerLink": "Odkaz v zápatí", + "frequentlyAskedQuestions": "Často kladené otázky", + "gallery": "Galerie", + "geomodifier": "Geomodifikátor", + "getDirections": "Získejte pokyny", + "header": "Záhlaví", + "headerLink": "Odkaz na záhlaví", + "hours": "Hodiny", + "information": "Informace", + "insights": "Postřehy", + "learnMore": "Další informace", + "logo": "Logo", + "meetOurTeam": "Seznamte se s naším týmem", + "name": "Jméno", + "nearbyLocations": "Místa v okolí", + "phone": "Telefon", + "price": "123,00 Kč", + "productName": "Název produktu", + "professionalName": "Profesní jméno", + "professionalTitle": "Profesionální titul", + "readMore": "Číst více", + "services": "Služby", + "servicesOffered": "Nabízené služby", + "subtitle": "Titulky", + "text": "Text", + "upcomingEvents": "Nadcházející události", + "visitProfile": "Navštivte profil" + }, "componentErrorBoundary": { "error": "Chyba", "message": "Tuto sekci nelze vykreslit. Zkuste aktualizovat knihovnu komponent." diff --git a/packages/visual-editor/locales/platform/da/visual-editor.json b/packages/visual-editor/locales/platform/da/visual-editor.json index 1ae49df70..3a2bd1fb3 100644 --- a/packages/visual-editor/locales/platform/da/visual-editor.json +++ b/packages/visual-editor/locales/platform/da/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Luk menu", "closesAtTime": "Lukker kl. {{time}}", "closesAtTimeWeek": "Lukker kl. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Om [[name]]", + "articleName": "Artikelnavn", + "associateAgent": "Associeret agent", + "bannerText": "Bannertekst", + "businessName": "Virksomhedens navn", + "button": "Knap", + "callToAction": "Opfordring til handling", + "category": "Kategori", + "contactMe": "Kontakt mig", + "credentials": "Akkreditiver", + "directoryRoot": "Biblioteksrod", + "eventImage": "Begivenhedsbillede", + "eventTitle": "Begivenhedens titel", + "featuredProducts": "Udvalgte produkter", + "featuredPromotion": "Fremhævet kampagne", + "featuredTestimonials": "Udvalgte testimonials", + "findALocation": "Find en placering", + "firstLast": "Første Sidste", + "followUs": "Følg os", + "footerLabel": "Footer label", + "footerLink": "Sidefodslink", + "frequentlyAskedQuestions": "Ofte stillede spørgsmål", + "gallery": "Galleri", + "geomodifier": "Geomodifikator", + "getDirections": "Få rutevejledning", + "header": "Overskrift", + "headerLink": "Overskriftslink", + "hours": "Timer", + "information": "Information", + "insights": "Indsigt", + "learnMore": "Lær mere", + "logo": "Logo", + "meetOurTeam": "Mød vores team", + "name": "Navn", + "nearbyLocations": "Steder i nærheden", + "phone": "Telefon", + "price": "123,00 DKK", + "productName": "Produktnavn", + "professionalName": "Professionelt navn", + "professionalTitle": "Professionel titel", + "readMore": "Læs mere", + "services": "Tjenester", + "servicesOffered": "Udbudte tjenester", + "subtitle": "Undertekst", + "text": "Tekst", + "upcomingEvents": "Kommende begivenheder", + "visitProfile": "Besøg profil" + }, "componentErrorBoundary": { "error": "Fejl", "message": "Kan ikke gengive denne sektion. Prøv at opdatere dit komponentbibliotek." diff --git a/packages/visual-editor/locales/platform/de/visual-editor.json b/packages/visual-editor/locales/platform/de/visual-editor.json index 4c7edcaee..3089369d8 100644 --- a/packages/visual-editor/locales/platform/de/visual-editor.json +++ b/packages/visual-editor/locales/platform/de/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Menü schließen", "closesAtTime": "Schließt um {{time}} Uhr", "closesAtTimeWeek": "Schließt um {{time}} Uhr am {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Über [[name]]", + "articleName": "Artikelname", + "associateAgent": "Assoziierter Agent", + "bannerText": "Bannertext", + "businessName": "Firmenname", + "button": "Button", + "callToAction": "Aufruf zum Handeln", + "category": "Kategorie", + "contactMe": "Kontaktieren Sie mich", + "credentials": "Anmeldeinformationen", + "directoryRoot": "Verzeichnisstamm", + "eventImage": "Veranstaltung-Bild", + "eventTitle": "Veranstaltungstitel", + "featuredProducts": "Ausgewählte Produkte", + "featuredPromotion": "Empfohlene Werbeaktion", + "featuredTestimonials": "Ausgewählte Erfahrungsberichte", + "findALocation": "Finden Sie einen Standort", + "firstLast": "Erster Letzter", + "followUs": "Folgen Sie uns", + "footerLabel": "Fußzeilenbeschriftung", + "footerLink": "Fußzeilen-Link", + "frequentlyAskedQuestions": "Häufig gestellte Fragen", + "gallery": "Galerie", + "geomodifier": "Geomodifikator", + "getDirections": "Wegbeschreibung abrufen", + "header": "Kopfzeile", + "headerLink": "Header-Link", + "hours": "Öffnungszeiten", + "information": "Information", + "insights": "Einblicke", + "learnMore": "Erfahren Sie mehr", + "logo": "Logo", + "meetOurTeam": "Lernen Sie unser Team kennen", + "name": "Name", + "nearbyLocations": "Standorte in der Nähe", + "phone": "Telefon", + "price": "123,00 €", + "productName": "Produktname", + "professionalName": "Berufsname", + "professionalTitle": "Berufsbezeichnung", + "readMore": "Mehr lesen", + "services": "Dienstleistungen", + "servicesOffered": "Angebotene Dienstleistungen", + "subtitle": "Untertitel", + "text": "Text", + "upcomingEvents": "Kommende Veranstaltungen", + "visitProfile": "Besuchen Sie das Profil" + }, "componentErrorBoundary": { "error": "Fehler", "message": "Dieses Modul kann nicht gerendert werden. Versuchen Sie, Ihre Komponentenbibliothek zu aktualisieren." diff --git a/packages/visual-editor/locales/platform/en-GB/visual-editor.json b/packages/visual-editor/locales/platform/en-GB/visual-editor.json index 7df5f7fe7..5bc22d5d5 100644 --- a/packages/visual-editor/locales/platform/en-GB/visual-editor.json +++ b/packages/visual-editor/locales/platform/en-GB/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Close menu", "closesAtTime": "Closes at {{time}}", "closesAtTimeWeek": "Closes at {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "About [[name]]", + "articleName": "Article Name", + "associateAgent": "Associate Agent", + "bannerText": "Banner Text", + "businessName": "Business Name", + "button": "Button", + "callToAction": "Call to Action", + "category": "Category", + "contactMe": "Contact Me", + "credentials": "Credentials", + "directoryRoot": "Directory Root", + "eventImage": "Event Image", + "eventTitle": "Event Title", + "featuredProducts": "Featured Products", + "featuredPromotion": "Featured Promotion", + "featuredTestimonials": "Featured Testimonials", + "findALocation": "Find a Location", + "firstLast": "First Last", + "followUs": "Follow Us", + "footerLabel": "Footer Label", + "footerLink": "Footer Link", + "frequentlyAskedQuestions": "Frequently Asked Questions", + "gallery": "Gallery", + "geomodifier": "Geomodifier", + "getDirections": "Get Directions", + "header": "Header", + "headerLink": "Header Link", + "hours": "Hours", + "information": "Information", + "insights": "Insights", + "learnMore": "Learn More", + "logo": "Logo", + "meetOurTeam": "Meet Our Team", + "name": "Name", + "nearbyLocations": "Nearby Locations", + "phone": "Phone", + "price": "£123.00", + "productName": "Product Name", + "professionalName": "Professional Name", + "professionalTitle": "Professional Title", + "readMore": "Read More", + "services": "Services", + "servicesOffered": "Services Offered", + "subtitle": "Subtitle", + "text": "Text", + "upcomingEvents": "Upcoming Events", + "visitProfile": "Visit Profile" + }, "componentErrorBoundary": { "error": "Error", "message": "Can't render this section. Try updating your component library." diff --git a/packages/visual-editor/locales/platform/en/visual-editor.json b/packages/visual-editor/locales/platform/en/visual-editor.json index 31298b2ee..296875951 100644 --- a/packages/visual-editor/locales/platform/en/visual-editor.json +++ b/packages/visual-editor/locales/platform/en/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Close menu", "closesAtTime": "Closes at {{time}}", "closesAtTimeWeek": "Closes at {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "About [[name]]", + "articleName": "Article Name", + "associateAgent": "Associate Agent", + "bannerText": "Banner Text", + "businessName": "Business Name", + "button": "Button", + "callToAction": "Call to Action", + "category": "Category", + "contactMe": "Contact Me", + "credentials": "Credentials", + "directoryRoot": "Directory Root", + "eventImage": "Event Image", + "eventTitle": "Event Title", + "featuredProducts": "Featured Products", + "featuredPromotion": "Featured Promotion", + "featuredTestimonials": "Featured Testimonials", + "findALocation": "Find a Location", + "firstLast": "First Last", + "followUs": "Follow Us", + "footerLabel": "Footer Label", + "footerLink": "Footer Link", + "frequentlyAskedQuestions": "Frequently Asked Questions", + "gallery": "Gallery", + "geomodifier": "Geomodifier", + "getDirections": "Get Directions", + "header": "Header", + "headerLink": "Header Link", + "hours": "Hours", + "information": "Information", + "insights": "Insights", + "learnMore": "Learn More", + "logo": "Logo", + "meetOurTeam": "Meet Our Team", + "name": "Name", + "nearbyLocations": "Nearby Locations", + "phone": "Phone", + "price": "$123.00", + "productName": "Product Name", + "professionalName": "Professional Name", + "professionalTitle": "Professional Title", + "readMore": "Read More", + "services": "Services", + "servicesOffered": "Services Offered", + "subtitle": "Subtitle", + "text": "Text", + "upcomingEvents": "Upcoming Events", + "visitProfile": "Visit Profile" + }, "componentErrorBoundary": { "error": "Error", "message": "Can't render this section. Try updating your component library." diff --git a/packages/visual-editor/locales/platform/es/visual-editor.json b/packages/visual-editor/locales/platform/es/visual-editor.json index e3f2d4b07..4173fadb9 100644 --- a/packages/visual-editor/locales/platform/es/visual-editor.json +++ b/packages/visual-editor/locales/platform/es/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Menú cerrado", "closesAtTime": "Cierra a las {{time}}", "closesAtTimeWeek": "Cierra a las {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Acerca de [[name]]", + "articleName": "Nombre del artículo", + "associateAgent": "Agente asociado", + "bannerText": "Texto del cartel", + "businessName": "Nombre comercial", + "button": "Botón", + "callToAction": "Llamado a la acción", + "category": "Categoría", + "contactMe": "Contáctame", + "credentials": "Cartas credenciales", + "directoryRoot": "Raíz del directorio", + "eventImage": "Imagen del evento", + "eventTitle": "Título del evento", + "featuredProducts": "Productos destacados", + "featuredPromotion": "Promoción destacada", + "featuredTestimonials": "Testimonios destacados", + "findALocation": "Encontrar una ubicación", + "firstLast": "Primero último", + "followUs": "Síganos", + "footerLabel": "Etiqueta de pie de página", + "footerLink": "Enlace de pie de página", + "frequentlyAskedQuestions": "Preguntas frecuentes", + "gallery": "Galería", + "geomodifier": "Geomodificador", + "getDirections": "Obtener direcciones", + "header": "Encabezamiento", + "headerLink": "Enlace de encabezado", + "hours": "Horas", + "information": "Información", + "insights": "Perspectivas", + "learnMore": "Más información", + "logo": "Logo", + "meetOurTeam": "Conozca a nuestro equipo", + "name": "Nombre", + "nearbyLocations": "Ubicaciones cercanas", + "phone": "Teléfono", + "price": "$123.00", + "productName": "Nombre del producto", + "professionalName": "Nombre profesional", + "professionalTitle": "Título profesional", + "readMore": "Leer más", + "services": "Servicios", + "servicesOffered": "Servicios ofrecidos", + "subtitle": "Subtitular", + "text": "Texto", + "upcomingEvents": "Próximos eventos", + "visitProfile": "Visitar perfil" + }, "componentErrorBoundary": { "error": "Error", "message": "No se puede renderizar esta sección. Intente actualizar su biblioteca de componentes." diff --git a/packages/visual-editor/locales/platform/et/visual-editor.json b/packages/visual-editor/locales/platform/et/visual-editor.json index a0144ff23..6af953049 100644 --- a/packages/visual-editor/locales/platform/et/visual-editor.json +++ b/packages/visual-editor/locales/platform/et/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Sulgemenüü", "closesAtTime": "Suletakse {{time}}", "closesAtTimeWeek": "Suletakse kell {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Umbes [[name]]", + "articleName": "Artikli nimi", + "associateAgent": "Abiagent", + "bannerText": "Bänneri tekst", + "businessName": "Ettevõtte nimi", + "button": "Nupp", + "callToAction": "Üleskutse tegevusele", + "category": "Kategooria", + "contactMe": "Võtke minuga ühendust", + "credentials": "Mandaat", + "directoryRoot": "Kataloogi juur", + "eventImage": "Sündmuse pilt", + "eventTitle": "Sündmuse pealkiri", + "featuredProducts": "Esiletõstetud tooted", + "featuredPromotion": "Esiletõstetud reklaam", + "featuredTestimonials": "Esiletõstetud iseloomustused", + "findALocation": "Leidke asukoht", + "firstLast": "Esimene Viimane", + "followUs": "Jälgi meid", + "footerLabel": "Jaluse silt", + "footerLink": "Jaluse link", + "frequentlyAskedQuestions": "Korduma kippuvad küsimused", + "gallery": "Galerii", + "geomodifier": "Geomodifier", + "getDirections": "Hankige juhiseid", + "header": "Päis", + "headerLink": "Päise link", + "hours": "Tööaeg", + "information": "Teave", + "insights": "Ülevaated", + "learnMore": "Lisateave", + "logo": "Logo", + "meetOurTeam": "Tutvuge meie meeskonnaga", + "name": "Nimi", + "nearbyLocations": "Lähedal asuvad asukohad", + "phone": "Telefon", + "price": "123,00 €", + "productName": "Toote nimi", + "professionalName": "Professionaalne nimi", + "professionalTitle": "Ametinimetus", + "readMore": "Lugege rohkem", + "services": "Teenused", + "servicesOffered": "Pakutavad teenused", + "subtitle": "Alapealkiri", + "text": "Tekst", + "upcomingEvents": "Eelseisvad sündmused", + "visitProfile": "Külastage profiili" + }, "componentErrorBoundary": { "error": "Viga", "message": "Seda jaotist ei saa renderdada. Proovige oma komponentide teeki värskendada." diff --git a/packages/visual-editor/locales/platform/fi/visual-editor.json b/packages/visual-editor/locales/platform/fi/visual-editor.json index e4720b391..6205e30d9 100644 --- a/packages/visual-editor/locales/platform/fi/visual-editor.json +++ b/packages/visual-editor/locales/platform/fi/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Sulje valikko", "closesAtTime": "Suljetaan {{time}}", "closesAtTimeWeek": "Suljetaan klo {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Tietoja paikasta [[name]]", + "articleName": "Artikkelin nimi", + "associateAgent": "Apulaisagentti", + "bannerText": "Bannerin teksti", + "businessName": "Yrityksen nimi", + "button": "Painike", + "callToAction": "Toimintakehotus", + "category": "Luokka", + "contactMe": "Ota minuun yhteyttä", + "credentials": "Valtuustiedot", + "directoryRoot": "Hakemiston juuri", + "eventImage": "Tapahtuman kuva", + "eventTitle": "Tapahtuman otsikko", + "featuredProducts": "Suositellut tuotteet", + "featuredPromotion": "Suositeltu kampanja", + "featuredTestimonials": "Suositellut suosittelut", + "findALocation": "Etsi sijainti", + "firstLast": "Ensimmäinen Viimeinen", + "followUs": "Seuraa meitä", + "footerLabel": "Alatunnisteen etiketti", + "footerLink": "Alatunnisteen linkki", + "frequentlyAskedQuestions": "Usein kysytyt kysymykset", + "gallery": "Galleria", + "geomodifier": "Geomodifier", + "getDirections": "Hanki reittiohjeet", + "header": "Otsikko", + "headerLink": "Otsikkolinkki", + "hours": "Tuntia", + "information": "Tiedot", + "insights": "Näkemyksiä", + "learnMore": "Lisätietoja", + "logo": "Logo", + "meetOurTeam": "Tutustu tiimiimme", + "name": "Nimi", + "nearbyLocations": "Läheiset paikat", + "phone": "Puhelin", + "price": "123,00 €", + "productName": "Tuotteen nimi", + "professionalName": "Ammattilaisen nimi", + "professionalTitle": "Ammattinimike", + "readMore": "Lue lisää", + "services": "Palvelut", + "servicesOffered": "Tarjotut palvelut", + "subtitle": "Alaotsikko", + "text": "Teksti", + "upcomingEvents": "Tulevat tapahtumat", + "visitProfile": "Vieraile profiilissa" + }, "componentErrorBoundary": { "error": "Virhe", "message": "Tätä osiota ei voi renderöidä. Yritä päivittää komponenttikirjastosi." diff --git a/packages/visual-editor/locales/platform/fr/visual-editor.json b/packages/visual-editor/locales/platform/fr/visual-editor.json index 748426c06..0c598ebb3 100644 --- a/packages/visual-editor/locales/platform/fr/visual-editor.json +++ b/packages/visual-editor/locales/platform/fr/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Fermer le menu", "closesAtTime": "Ferme à {{time}}", "closesAtTimeWeek": "Ferme à {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "À propos de [[name]]", + "articleName": "Nom de l'article", + "associateAgent": "Agent associé", + "bannerText": "Texte de la bannière", + "businessName": "Nom de l'entreprise", + "button": "Bouton", + "callToAction": "Appel à l'action", + "category": "Catégorie", + "contactMe": "Contactez-moi", + "credentials": "Informations d'identification", + "directoryRoot": "Racine du répertoire", + "eventImage": "Image de l'événement", + "eventTitle": "Titre de l'événement", + "featuredProducts": "Produits en vedette", + "featuredPromotion": "Promotion en vedette", + "featuredTestimonials": "Témoignages en vedette", + "findALocation": "Trouver un emplacement", + "firstLast": "Premier Dernier", + "followUs": "Suivez-nous", + "footerLabel": "Étiquette de pied de page", + "footerLink": "Lien de pied de page", + "frequentlyAskedQuestions": "Foire aux questions", + "gallery": "Galerie", + "geomodifier": "Géomodificateur", + "getDirections": "Obtenir un itinéraire", + "header": "En-tête", + "headerLink": "Lien d'en-tête", + "hours": "Heures", + "information": "Information", + "insights": "Connaissances", + "learnMore": "En savoir plus", + "logo": "Logo", + "meetOurTeam": "Rencontrez notre équipe", + "name": "Nom", + "nearbyLocations": "Emplacements à proximité", + "phone": "Téléphone", + "price": "123,00 €", + "productName": "Nom du produit", + "professionalName": "Nom professionnel", + "professionalTitle": "Titre professionnel", + "readMore": "En savoir plus", + "services": "Services", + "servicesOffered": "Services offerts", + "subtitle": "Sous-titre", + "text": "Texte", + "upcomingEvents": "Événements à venir", + "visitProfile": "Visiter le profil" + }, "componentErrorBoundary": { "error": "Erreur", "message": "Impossible de restituer cette section. Essayez de mettre à jour votre bibliothèque de composants." diff --git a/packages/visual-editor/locales/platform/hr/visual-editor.json b/packages/visual-editor/locales/platform/hr/visual-editor.json index fbe18d81c..259542128 100644 --- a/packages/visual-editor/locales/platform/hr/visual-editor.json +++ b/packages/visual-editor/locales/platform/hr/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Zatvori izbornik", "closesAtTime": "Zatvara se u {{time}}", "closesAtTimeWeek": "Zatvara se u {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "O [[name]]", + "articleName": "Naziv artikla", + "associateAgent": "Pridruženi agent", + "bannerText": "Tekst natpisa", + "businessName": "Naziv tvrtke", + "button": "Gumb", + "callToAction": "Poziv na akciju", + "category": "Kategorija", + "contactMe": "Kontaktirajte me", + "credentials": "Vjerodajnice", + "directoryRoot": "Korijen imenika", + "eventImage": "Slika događaja", + "eventTitle": "Naslov događaja", + "featuredProducts": "Istaknuti proizvodi", + "featuredPromotion": "Istaknuta promocija", + "featuredTestimonials": "Istaknuta svjedočanstva", + "findALocation": "Pronađite lokaciju", + "firstLast": "Prvi Zadnji", + "followUs": "Pratite nas", + "footerLabel": "Oznaka podnožja", + "footerLink": "Veza podnožja", + "frequentlyAskedQuestions": "Često postavljana pitanja", + "gallery": "Galerija", + "geomodifier": "Geomodifier", + "getDirections": "Dobiti upute", + "header": "Zaglavlje", + "headerLink": "Veza zaglavlja", + "hours": "Sati", + "information": "Informacija", + "insights": "Uvidi", + "learnMore": "Saznajte više", + "logo": "Logo", + "meetOurTeam": "Upoznajte naš tim", + "name": "Ime", + "nearbyLocations": "Lokacije u blizini", + "phone": "Telefon", + "price": "123,00 €", + "productName": "Naziv proizvoda", + "professionalName": "Profesionalni naziv", + "professionalTitle": "Stručno zvanje", + "readMore": "Pročitaj više", + "services": "Usluge", + "servicesOffered": "Ponuđene usluge", + "subtitle": "Podnaslov", + "text": "Tekst", + "upcomingEvents": "Nadolazeći događaji", + "visitProfile": "Posjetite profil" + }, "componentErrorBoundary": { "error": "Greška", "message": "Nije moguće prikazati ovaj odjeljak. Pokušajte ažurirati biblioteku komponenti." diff --git a/packages/visual-editor/locales/platform/hu/visual-editor.json b/packages/visual-editor/locales/platform/hu/visual-editor.json index 5f757be15..f4abe3fce 100644 --- a/packages/visual-editor/locales/platform/hu/visual-editor.json +++ b/packages/visual-editor/locales/platform/hu/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Zárja be a menüt", "closesAtTime": "Zárás: {{time}}", "closesAtTimeWeek": "Zárás: {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Körülbelül [[name]]", + "articleName": "Cikk neve", + "associateAgent": "társult ügynök", + "bannerText": "Banner szöveg", + "businessName": "Vállalkozás neve", + "button": "Gomb", + "callToAction": "Felhívás cselekvésre", + "category": "Kategória", + "contactMe": "Lépjen kapcsolatba velem", + "credentials": "Hitelesítő adatok", + "directoryRoot": "Címtárgyökér", + "eventImage": "Esemény képe", + "eventTitle": "Esemény címe", + "featuredProducts": "Kiemelt termékek", + "featuredPromotion": "Kiemelt promóció", + "featuredTestimonials": "Kiemelt ajánlások", + "findALocation": "Hely keresése", + "firstLast": "Első Utolsó", + "followUs": "Kövess minket", + "footerLabel": "Lábléc címke", + "footerLink": "Lábléc hivatkozás", + "frequentlyAskedQuestions": "Gyakran Ismételt Kérdések", + "gallery": "Galéria", + "geomodifier": "Geomodifikátor", + "getDirections": "Útvonalterv", + "header": "Fejléc", + "headerLink": "Fejléc hivatkozás", + "hours": "Órák", + "information": "Információ", + "insights": "Betekintés", + "learnMore": "További információ", + "logo": "Logó", + "meetOurTeam": "Ismerje meg csapatunkat", + "name": "Név", + "nearbyLocations": "Közeli helyek", + "phone": "Telefon", + "price": "123 euró", + "productName": "Termék neve", + "professionalName": "Szakmai név", + "professionalTitle": "Szakmai cím", + "readMore": "Olvasson tovább", + "services": "Szolgáltatások", + "servicesOffered": "Ajánlott szolgáltatások", + "subtitle": "Felirat", + "text": "Szöveg", + "upcomingEvents": "Közelgő események", + "visitProfile": "Látogassa meg a Profilt" + }, "componentErrorBoundary": { "error": "Hiba", "message": "Ez a szakasz nem jeleníthető meg. Próbálja meg frissíteni az összetevőkönyvtárat." diff --git a/packages/visual-editor/locales/platform/it/visual-editor.json b/packages/visual-editor/locales/platform/it/visual-editor.json index 0fe8150cf..cd1087be7 100644 --- a/packages/visual-editor/locales/platform/it/visual-editor.json +++ b/packages/visual-editor/locales/platform/it/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Chiudi menu", "closesAtTime": "Chiude alle {{time}}", "closesAtTimeWeek": "Chiude alle {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Informazioni su [[name]]", + "articleName": "Nome dell'articolo", + "associateAgent": "Agente associato", + "bannerText": "Testo della bandiera", + "businessName": "Nome dell'azienda", + "button": "Pulsante", + "callToAction": "Invito all'azione", + "category": "Categoria", + "contactMe": "Contattami", + "credentials": "Credenziali", + "directoryRoot": "Radice della directory", + "eventImage": "Immagine dell'evento", + "eventTitle": "Titolo dell'evento", + "featuredProducts": "Prodotti in evidenza", + "featuredPromotion": "Promozione in primo piano", + "featuredTestimonials": "Testimonianze in primo piano", + "findALocation": "Trova una posizione", + "firstLast": "Primo Ultimo", + "followUs": "Seguici", + "footerLabel": "Etichetta piè di pagina", + "footerLink": "Collegamento a piè di pagina", + "frequentlyAskedQuestions": "Domande frequenti", + "gallery": "Galleria", + "geomodifier": "Geomodificatore", + "getDirections": "Ottieni indicazioni stradali", + "header": "Intestazione", + "headerLink": "Collegamento dell'intestazione", + "hours": "Ore", + "information": "Informazioni", + "insights": "Approfondimenti", + "learnMore": "Saperne di più", + "logo": "Logo", + "meetOurTeam": "Incontra il nostro team", + "name": "Nome", + "nearbyLocations": "Località vicine", + "phone": "Telefono", + "price": "123,00 €", + "productName": "Nome del prodotto", + "professionalName": "Nome professionale", + "professionalTitle": "Titolo professionale", + "readMore": "Per saperne di più", + "services": "Servizi", + "servicesOffered": "Servizi offerti", + "subtitle": "Sottotitolo", + "text": "Testo", + "upcomingEvents": "Prossimi eventi", + "visitProfile": "Visita il profilo" + }, "componentErrorBoundary": { "error": "Errore", "message": "Impossibile eseguire il rendering di questa sezione. Prova ad aggiornare la libreria dei componenti." diff --git a/packages/visual-editor/locales/platform/ja/visual-editor.json b/packages/visual-editor/locales/platform/ja/visual-editor.json index a70f3647d..b9b41ba82 100644 --- a/packages/visual-editor/locales/platform/ja/visual-editor.json +++ b/packages/visual-editor/locales/platform/ja/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "メニューを閉じます", "closesAtTime": "{{time}}に閉まります", "closesAtTimeWeek": "{{time}} {{dayOfWeek}} に閉店", + "componentDefaults": { + "aboutName": "[[name]] について", + "articleName": "記事名", + "associateAgent": "アソシエイトエージェント", + "bannerText": "バナーテキスト", + "businessName": "商号", + "button": "ボタン", + "callToAction": "行動喚起", + "category": "カテゴリ", + "contactMe": "連絡してください", + "credentials": "資格", + "directoryRoot": "ディレクトリルート", + "eventImage": "イベント画像", + "eventTitle": "イベントタイトル", + "featuredProducts": "注目の製品", + "featuredPromotion": "注目のプロモーション", + "featuredTestimonials": "注目のお客様の声", + "findALocation": "場所を探す", + "firstLast": "姓名", + "followUs": "フォローしてください", + "footerLabel": "フッターラベル", + "footerLink": "フッターリンク", + "frequentlyAskedQuestions": "よくある質問", + "gallery": "ギャラリー", + "geomodifier": "ジオモディファイアー", + "getDirections": "道順を調べる", + "header": "ヘッダー", + "headerLink": "ヘッダーリンク", + "hours": "営業時間", + "information": "情報", + "insights": "洞察", + "learnMore": "もっと詳しく知る", + "logo": "ロゴ", + "meetOurTeam": "私たちのチームのご紹介", + "name": "名前", + "nearbyLocations": "近くの場所", + "phone": "電話", + "price": "¥123", + "productName": "製品名", + "professionalName": "専門職名", + "professionalTitle": "専門職の称号", + "readMore": "続きを読む", + "services": "サービス", + "servicesOffered": "提供されるサービス", + "subtitle": "小見出し", + "text": "文章", + "upcomingEvents": "今後のイベント", + "visitProfile": "プロフィールにアクセス" + }, "componentErrorBoundary": { "error": "エラー", "message": "このセクションをレンダリングできません。コンポーネント ライブラリを更新してみてください。" diff --git a/packages/visual-editor/locales/platform/lt/visual-editor.json b/packages/visual-editor/locales/platform/lt/visual-editor.json index 70f1ec77c..ec0b9a479 100644 --- a/packages/visual-editor/locales/platform/lt/visual-editor.json +++ b/packages/visual-editor/locales/platform/lt/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Uždaryti meniu", "closesAtTime": "Uždaroma {{time}}", "closesAtTimeWeek": "Uždaroma {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Apie [[name]]", + "articleName": "Straipsnio pavadinimas", + "associateAgent": "Asocijuotasis agentas", + "bannerText": "Reklaminio skydelio tekstas", + "businessName": "Įmonės pavadinimas", + "button": "Mygtukas", + "callToAction": "Raginimas veikti", + "category": "Kategorija", + "contactMe": "Susisiekite su manimi", + "credentials": "Įgaliojimai", + "directoryRoot": "Katalogo šaknis", + "eventImage": "Įvykio vaizdas", + "eventTitle": "Renginio pavadinimas", + "featuredProducts": "Teminiai produktai", + "featuredPromotion": "Teminė reklama", + "featuredTestimonials": "Teminiai atsiliepimai", + "findALocation": "Raskite vietą", + "firstLast": "Pirmas Paskutinis", + "followUs": "Sekite mus", + "footerLabel": "Poraštės etiketė", + "footerLink": "Poraštės nuoroda", + "frequentlyAskedQuestions": "Dažnai užduodami klausimai", + "gallery": "Galerija", + "geomodifier": "Geomodifikatorius", + "getDirections": "Gaukite nuorodas", + "header": "Antraštė", + "headerLink": "Antraštės nuoroda", + "hours": "Valandos", + "information": "Informacija", + "insights": "Įžvalgos", + "learnMore": "Sužinokite daugiau", + "logo": "Logotipas", + "meetOurTeam": "Susipažinkite su mūsų komanda", + "name": "Vardas", + "nearbyLocations": "Netoliese esančios vietos", + "phone": "Telefonas", + "price": "123,00 USD", + "productName": "Produkto pavadinimas", + "professionalName": "Profesionalus vardas", + "professionalTitle": "Profesinis titulas", + "readMore": "Skaityti daugiau", + "services": "Paslaugos", + "servicesOffered": "Siūlomos paslaugos", + "subtitle": "Subtitrai", + "text": "Tekstas", + "upcomingEvents": "Būsimi įvykiai", + "visitProfile": "Apsilankykite profilyje" + }, "componentErrorBoundary": { "error": "Klaida", "message": "Nepavyko pateikti šios skilties. Pabandykite atnaujinti komponentų biblioteką." diff --git a/packages/visual-editor/locales/platform/lv/visual-editor.json b/packages/visual-editor/locales/platform/lv/visual-editor.json index c8a2d2d27..21cc21ce5 100644 --- a/packages/visual-editor/locales/platform/lv/visual-editor.json +++ b/packages/visual-editor/locales/platform/lv/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Aizvērt ēdienkarti", "closesAtTime": "Tiek slēgts plkst. {{time}}", "closesAtTimeWeek": "Tiek slēgts plkst. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Aptuveni [[name]]", + "articleName": "Raksta nosaukums", + "associateAgent": "Asociētais aģents", + "bannerText": "Reklāmkaroga teksts", + "businessName": "Uzņēmuma nosaukums", + "button": "Poga", + "callToAction": "Aicinājums uz darbību", + "category": "Kategorija", + "contactMe": "Sazinieties ar mani", + "credentials": "Akreditācijas dati", + "directoryRoot": "Direktorija sakne", + "eventImage": "Pasākuma attēls", + "eventTitle": "Pasākuma nosaukums", + "featuredProducts": "Piedāvātie produkti", + "featuredPromotion": "Piedāvātā akcija", + "featuredTestimonials": "Piedāvātās atsauksmes", + "findALocation": "Atrodiet atrašanās vietu", + "firstLast": "Pirmais Pēdējais", + "followUs": "Sekojiet mums", + "footerLabel": "Kājenes etiķete", + "footerLink": "Kājenes saite", + "frequentlyAskedQuestions": "Bieži uzdotie jautājumi", + "gallery": "Galerija", + "geomodifier": "Ģeomodifikators", + "getDirections": "Saņemiet norādes", + "header": "Virsraksts", + "headerLink": "Galvenes saite", + "hours": "Stundas", + "information": "Informācija", + "insights": "Ieskats", + "learnMore": "Uzziniet vairāk", + "logo": "Logotips", + "meetOurTeam": "Iepazīstieties ar mūsu komandu", + "name": "Vārds", + "nearbyLocations": "Atrašanās vietas tuvumā", + "phone": "Tālrunis", + "price": "123,00 USD", + "productName": "Produkta nosaukums", + "professionalName": "Profesionālais vārds", + "professionalTitle": "Profesionālais tituls", + "readMore": "Lasīt vairāk", + "services": "Pakalpojumi", + "servicesOffered": "Piedāvātie pakalpojumi", + "subtitle": "Apakšvirsraksts", + "text": "Teksts", + "upcomingEvents": "Gaidāmie notikumi", + "visitProfile": "Apmeklējiet profilu" + }, "componentErrorBoundary": { "error": "Kļūda", "message": "Nevar atveidot šo sadaļu. Mēģiniet atjaunināt savu komponentu bibliotēku." diff --git a/packages/visual-editor/locales/platform/nb/visual-editor.json b/packages/visual-editor/locales/platform/nb/visual-editor.json index 6034a9639..e49b9adb0 100644 --- a/packages/visual-editor/locales/platform/nb/visual-editor.json +++ b/packages/visual-editor/locales/platform/nb/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Lukk meny", "closesAtTime": "Stenger kl. {{time}}", "closesAtTimeWeek": "Stenger kl. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Om [[name]]", + "articleName": "Artikkelnavn", + "associateAgent": "Tilknyttet agent", + "bannerText": "Bannertekst", + "businessName": "Bedriftsnavn", + "button": "Knapp", + "callToAction": "Ring til handling", + "category": "Kategori", + "contactMe": "Kontakt meg", + "credentials": "Legitimasjon", + "directoryRoot": "Katalogrot", + "eventImage": "Hendelsesbilde", + "eventTitle": "Begivenhetstittel", + "featuredProducts": "Utvalgte produkter", + "featuredPromotion": "Utvalgt kampanje", + "featuredTestimonials": "Utvalgte attester", + "findALocation": "Finn en plassering", + "firstLast": "Første Siste", + "followUs": "Følg oss", + "footerLabel": "Bunntekstetikett", + "footerLink": "Bunntekstlenke", + "frequentlyAskedQuestions": "Ofte stilte spørsmål", + "gallery": "Galleri", + "geomodifier": "Geomodifikator", + "getDirections": "Få veibeskrivelse", + "header": "Overskrift", + "headerLink": "Overskriftskobling", + "hours": "Timer", + "information": "Informasjon", + "insights": "Innsikt", + "learnMore": "Lær mer", + "logo": "Logo", + "meetOurTeam": "Møt teamet vårt", + "name": "Navn", + "nearbyLocations": "Steder i nærheten", + "phone": "Telefon", + "price": "123,00 kr", + "productName": "Produktnavn", + "professionalName": "Profesjonelt navn", + "professionalTitle": "Yrkestittel", + "readMore": "Les mer", + "services": "Tjenester", + "servicesOffered": "Tjenester som tilbys", + "subtitle": "Undertekst", + "text": "Tekst", + "upcomingEvents": "Kommende arrangementer", + "visitProfile": "Besøk profil" + }, "componentErrorBoundary": { "error": "Feil", "message": "Kan ikke gjengi denne delen. Prøv å oppdatere komponentbiblioteket." diff --git a/packages/visual-editor/locales/platform/nl/visual-editor.json b/packages/visual-editor/locales/platform/nl/visual-editor.json index 13252691f..a483e0ba3 100644 --- a/packages/visual-editor/locales/platform/nl/visual-editor.json +++ b/packages/visual-editor/locales/platform/nl/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Sluit het menu", "closesAtTime": "Sluit om {{time}}", "closesAtTimeWeek": "Sluit om {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Over [[name]]", + "articleName": "Artikelnaam", + "associateAgent": "Associate-agent", + "bannerText": "Bannertekst", + "businessName": "Bedrijfsnaam", + "button": "Knop", + "callToAction": "Oproep tot actie", + "category": "Categorie", + "contactMe": "Neem contact met mij op", + "credentials": "Referenties", + "directoryRoot": "Directorywortel", + "eventImage": "Evenement afbeelding", + "eventTitle": "Titel van evenement", + "featuredProducts": "Uitgelichte producten", + "featuredPromotion": "Uitgelichte promotie", + "featuredTestimonials": "Uitgelichte getuigenissen", + "findALocation": "Vind een locatie", + "firstLast": "Eerste Laatste", + "followUs": "Volg ons", + "footerLabel": "Voettekstlabel", + "footerLink": "Voettekstlink", + "frequentlyAskedQuestions": "Veelgestelde vragen", + "gallery": "Galerij", + "geomodifier": "Geomodificator", + "getDirections": "Routebeschrijving opvragen", + "header": "Koptekst", + "headerLink": "Koplink", + "hours": "Uren", + "information": "Informatie", + "insights": "Inzichten", + "learnMore": "Meer informatie", + "logo": "Logo", + "meetOurTeam": "Maak kennis met ons team", + "name": "Naam", + "nearbyLocations": "Locaties in de buurt", + "phone": "Telefoon", + "price": "123,00 €", + "productName": "Productnaam", + "professionalName": "Professionele naam", + "professionalTitle": "Professionele titel", + "readMore": "Lees meer", + "services": "Diensten", + "servicesOffered": "Aangeboden diensten", + "subtitle": "Ondertitel", + "text": "Tekst", + "upcomingEvents": "Aankomende evenementen", + "visitProfile": "Bezoek profiel" + }, "componentErrorBoundary": { "error": "Fout", "message": "Kan deze sectie niet weergeven. Probeer uw componentenbibliotheek bij te werken." diff --git a/packages/visual-editor/locales/platform/pl/visual-editor.json b/packages/visual-editor/locales/platform/pl/visual-editor.json index 5bfab7ea2..5c21e74f2 100644 --- a/packages/visual-editor/locales/platform/pl/visual-editor.json +++ b/packages/visual-editor/locales/platform/pl/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Zamknij menu", "closesAtTime": "Zamyka się o {{time}}", "closesAtTimeWeek": "Zamyka się o {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Informacje o [[name]]", + "articleName": "Nazwa artykułu", + "associateAgent": "Agent stowarzyszony", + "bannerText": "Tekst banera", + "businessName": "Nazwa firmy", + "button": "Przycisk", + "callToAction": "Wezwanie do działania", + "category": "Kategoria", + "contactMe": "Skontaktuj się ze mną", + "credentials": "Referencje", + "directoryRoot": "Katalog główny", + "eventImage": "Obraz wydarzenia", + "eventTitle": "Tytuł wydarzenia", + "featuredProducts": "Polecane produkty", + "featuredPromotion": "Wyróżniona promocja", + "featuredTestimonials": "Wyróżnione referencje", + "findALocation": "Znajdź lokalizację", + "firstLast": "Pierwszy Ostatni", + "followUs": "Śledź nas", + "footerLabel": "Etykieta stopki", + "footerLink": "Link do stopki", + "frequentlyAskedQuestions": "Często zadawane pytania", + "gallery": "Galeria", + "geomodifier": "Geomodyfikator", + "getDirections": "Uzyskaj wskazówki", + "header": "Nagłówek", + "headerLink": "Link do nagłówka", + "hours": "Godziny", + "information": "Informacja", + "insights": "Spostrzeżenia", + "learnMore": "Dowiedz się więcej", + "logo": "Logo", + "meetOurTeam": "Poznaj nasz zespół", + "name": "Nazwa", + "nearbyLocations": "Pobliskie lokalizacje", + "phone": "Telefon", + "price": "123,00 zł", + "productName": "Nazwa produktu", + "professionalName": "Nazwa zawodowa", + "professionalTitle": "Tytuł zawodowy", + "readMore": "Przeczytaj więcej", + "services": "Usługi", + "servicesOffered": "Oferowane usługi", + "subtitle": "Podtytuł", + "text": "Tekst", + "upcomingEvents": "Nadchodzące wydarzenia", + "visitProfile": "Odwiedź profil" + }, "componentErrorBoundary": { "error": "Błąd", "message": "Nie można wyrenderować tej sekcji. Spróbuj zaktualizować bibliotekę komponentów." diff --git a/packages/visual-editor/locales/platform/pt/visual-editor.json b/packages/visual-editor/locales/platform/pt/visual-editor.json index c7cdf414d..f1a7d5bce 100644 --- a/packages/visual-editor/locales/platform/pt/visual-editor.json +++ b/packages/visual-editor/locales/platform/pt/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Feche o menu", "closesAtTime": "Fecha às {{time}}", "closesAtTimeWeek": "Fecha às {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Sobre [[name]]", + "articleName": "Nome do artigo", + "associateAgent": "Agente Associado", + "bannerText": "Texto do banner", + "businessName": "Nome comercial", + "button": "Botão", + "callToAction": "Chamada para ação", + "category": "Categoria", + "contactMe": "Entre em contato comigo", + "credentials": "Credenciais", + "directoryRoot": "Raiz do diretório", + "eventImage": "Imagem do Evento", + "eventTitle": "Título do Evento", + "featuredProducts": "Produtos em destaque", + "featuredPromotion": "Promoção em destaque", + "featuredTestimonials": "Depoimentos em destaque", + "findALocation": "Encontre um local", + "firstLast": "Primeiro Último", + "followUs": "Siga-nos", + "footerLabel": "Etiqueta de rodapé", + "footerLink": "Link do rodapé", + "frequentlyAskedQuestions": "Perguntas frequentes", + "gallery": "Galeria", + "geomodifier": "Geomodificador", + "getDirections": "Obter direções", + "header": "Cabeçalho", + "headerLink": "Link do cabeçalho", + "hours": "Horas", + "information": "Informação", + "insights": "Percepções", + "learnMore": "Saber mais", + "logo": "Logotipo", + "meetOurTeam": "Conheça nossa equipe", + "name": "Nome", + "nearbyLocations": "Locais próximos", + "phone": "Telefone", + "price": "R$ 123,00", + "productName": "Nome do produto", + "professionalName": "Nome Profissional", + "professionalTitle": "Título Profissional", + "readMore": "Leia mais", + "services": "Serviços", + "servicesOffered": "Serviços oferecidos", + "subtitle": "Legenda", + "text": "Texto", + "upcomingEvents": "Próximos eventos", + "visitProfile": "Visitar perfil" + }, "componentErrorBoundary": { "error": "Erro", "message": "Não é possível renderizar esta seção. Tente atualizar sua biblioteca de componentes." diff --git a/packages/visual-editor/locales/platform/ro/visual-editor.json b/packages/visual-editor/locales/platform/ro/visual-editor.json index c65d95147..1eec79383 100644 --- a/packages/visual-editor/locales/platform/ro/visual-editor.json +++ b/packages/visual-editor/locales/platform/ro/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Închideți meniul", "closesAtTime": "Se închide la {{time}}", "closesAtTimeWeek": "Se închide la {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Despre [[name]]", + "articleName": "Nume articol", + "associateAgent": "Agent asociat", + "bannerText": "Text banner", + "businessName": "Numele companiei", + "button": "Buton", + "callToAction": "Apel la acțiune", + "category": "Categorie", + "contactMe": "Contactați-mă", + "credentials": "Acreditări", + "directoryRoot": "Rădăcină director", + "eventImage": "Imaginea evenimentului", + "eventTitle": "Titlul evenimentului", + "featuredProducts": "Produse recomandate", + "featuredPromotion": "Promoție recomandată", + "featuredTestimonials": "Mărturii recomandate", + "findALocation": "Găsiți o locație", + "firstLast": "Primul Ultimul", + "followUs": "Urmați-ne", + "footerLabel": "Etichetă de subsol", + "footerLink": "Link de subsol", + "frequentlyAskedQuestions": "Întrebări frecvente", + "gallery": "Galerie", + "geomodifier": "Geomodificator", + "getDirections": "Obțineți indicații", + "header": "Antet", + "headerLink": "Link antet", + "hours": "Ore", + "information": "Informaţii", + "insights": "Perspective", + "learnMore": "Află mai multe", + "logo": "Logo", + "meetOurTeam": "Faceți cunoștință cu echipa noastră", + "name": "Nume", + "nearbyLocations": "Locații din apropiere", + "phone": "Telefon", + "price": "123,00 RON", + "productName": "Numele produsului", + "professionalName": "Nume profesional", + "professionalTitle": "Titlul profesional", + "readMore": "Citiți mai mult", + "services": "Servicii", + "servicesOffered": "Servicii oferite", + "subtitle": "Subtitlu", + "text": "Text", + "upcomingEvents": "Evenimente viitoare", + "visitProfile": "Vizitați profil" + }, "componentErrorBoundary": { "error": "Eroare", "message": "Nu se poate reda această secțiune. Încercați să vă actualizați biblioteca de componente." diff --git a/packages/visual-editor/locales/platform/sk/visual-editor.json b/packages/visual-editor/locales/platform/sk/visual-editor.json index 2d2536dd7..e5d64dcdf 100644 --- a/packages/visual-editor/locales/platform/sk/visual-editor.json +++ b/packages/visual-editor/locales/platform/sk/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Zavrieť menu", "closesAtTime": "Zatvára sa o {{time}}", "closesAtTimeWeek": "Zatvára sa o {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "O [[name]]", + "articleName": "Názov článku", + "associateAgent": "Pridružený agent", + "bannerText": "Text bannera", + "businessName": "Obchodné meno", + "button": "Tlačidlo", + "callToAction": "Výzva na akciu", + "category": "Kategória", + "contactMe": "Kontaktujte ma", + "credentials": "Poverenia", + "directoryRoot": "Koreň adresára", + "eventImage": "Obrázok udalosti", + "eventTitle": "Názov udalosti", + "featuredProducts": "Odporúčané produkty", + "featuredPromotion": "Odporúčaná propagácia", + "featuredTestimonials": "Odporúčané referencie", + "findALocation": "Nájdite miesto", + "firstLast": "Prvý posledný", + "followUs": "Sledujte nás", + "footerLabel": "Štítok päty", + "footerLink": "Odkaz v päte", + "frequentlyAskedQuestions": "Často kladené otázky", + "gallery": "Galéria", + "geomodifier": "Geomodifikátor", + "getDirections": "Získajte trasu", + "header": "Hlavička", + "headerLink": "Odkaz na hlavičku", + "hours": "Hodiny", + "information": "Informácie", + "insights": "Insights", + "learnMore": "Zistite viac", + "logo": "Logo", + "meetOurTeam": "Spoznajte náš tím", + "name": "Meno", + "nearbyLocations": "Polohy v okolí", + "phone": "Telefón", + "price": "123,00 dolárov", + "productName": "Názov produktu", + "professionalName": "Profesionálne meno", + "professionalTitle": "Profesionálny titul", + "readMore": "Prečítajte si viac", + "services": "Služby", + "servicesOffered": "Ponúkané služby", + "subtitle": "Podnadpis", + "text": "Text", + "upcomingEvents": "Nadchádzajúce udalosti", + "visitProfile": "Navštívte profil" + }, "componentErrorBoundary": { "error": "Chyba", "message": "Túto sekciu nie je možné vykresliť. Skúste aktualizovať knižnicu komponentov." diff --git a/packages/visual-editor/locales/platform/sv/visual-editor.json b/packages/visual-editor/locales/platform/sv/visual-editor.json index c92786c96..28c7a79bb 100644 --- a/packages/visual-editor/locales/platform/sv/visual-editor.json +++ b/packages/visual-editor/locales/platform/sv/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Stänga meny", "closesAtTime": "Stänger kl. {{time}}", "closesAtTimeWeek": "Stänger kl. {{time}} {{dayOfWeek}}", + "componentDefaults": { + "aboutName": "Om [[name]]", + "articleName": "Artikelnamn", + "associateAgent": "Associerad agent", + "bannerText": "Bannertext", + "businessName": "Företagsnamn", + "button": "Knapp", + "callToAction": "Uppmaning till handling", + "category": "Kategori", + "contactMe": "Kontakta mig", + "credentials": "Referenser", + "directoryRoot": "Katalogrot", + "eventImage": "Händelsebild", + "eventTitle": "Händelsens titel", + "featuredProducts": "Utvalda produkter", + "featuredPromotion": "Utvald kampanj", + "featuredTestimonials": "Utvalda vittnesmål", + "findALocation": "Hitta en plats", + "firstLast": "Första Sista", + "followUs": "Följ oss", + "footerLabel": "Sidfotsetikett", + "footerLink": "Sidfotlänkar", + "frequentlyAskedQuestions": "Vanliga frågor", + "gallery": "Galleri", + "geomodifier": "Geomodifierare", + "getDirections": "Få vägbeskrivningar", + "header": "Rubrik", + "headerLink": "Rubriklänk", + "hours": "Timmar", + "information": "Information", + "insights": "Insikter", + "learnMore": "Läs mer", + "logo": "Logotyp", + "meetOurTeam": "Möt vårt team", + "name": "Namn", + "nearbyLocations": "Närliggande platser", + "phone": "Telefon", + "price": "123,00 SEK", + "productName": "Produktnamn", + "professionalName": "Professionellt namn", + "professionalTitle": "Yrkestitel", + "readMore": "Läs mer", + "services": "Tjänster", + "servicesOffered": "Tjänster som erbjuds", + "subtitle": "Underrubrik", + "text": "Text", + "upcomingEvents": "Kommande evenemang", + "visitProfile": "Besök profil" + }, "componentErrorBoundary": { "error": "Fel", "message": "Det går inte att återge detta avsnitt. Testa att uppdatera ditt komponentbibliotek." diff --git a/packages/visual-editor/locales/platform/tr/visual-editor.json b/packages/visual-editor/locales/platform/tr/visual-editor.json index 90100d88a..c5c984e73 100644 --- a/packages/visual-editor/locales/platform/tr/visual-editor.json +++ b/packages/visual-editor/locales/platform/tr/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "Kapat Menüsü", "closesAtTime": "{{time}} itibarıyla kapanıyor", "closesAtTimeWeek": "{{time}} {{dayOfWeek}} itibarıyla kapanıyor", + "componentDefaults": { + "aboutName": "[[name]] Hakkında", + "articleName": "Makale Adı", + "associateAgent": "Yardımcı Temsilci", + "bannerText": "Banner Metni", + "businessName": "İşletme Adı", + "button": "Düğme", + "callToAction": "Eylem Çağrısı", + "category": "Kategori", + "contactMe": "Bana Ulaşın", + "credentials": "Kimlik bilgileri", + "directoryRoot": "Dizin Kökü", + "eventImage": "Etkinlik Resmi", + "eventTitle": "Etkinlik Başlığı", + "featuredProducts": "Öne Çıkan Ürünler", + "featuredPromotion": "Öne Çıkan Promosyon", + "featuredTestimonials": "Öne Çıkan Görüşler", + "findALocation": "Konum Bul", + "firstLast": "İlk Son", + "followUs": "Bizi takip edin", + "footerLabel": "Alt Bilgi Etiketi", + "footerLink": "Alt Bilgi Bağlantısı", + "frequentlyAskedQuestions": "Sıkça Sorulan Sorular", + "gallery": "Galeri", + "geomodifier": "Geomodifier", + "getDirections": "Yol Tarifi Al", + "header": "Başlık", + "headerLink": "Başlık Bağlantısı", + "hours": "Saat", + "information": "Bilgi", + "insights": "Analizler", + "learnMore": "Daha fazla bilgi edin", + "logo": "Logo", + "meetOurTeam": "Ekibimizle Tanışın", + "name": "İsim", + "nearbyLocations": "Yakın Yerler", + "phone": "Telefon", + "price": "₺123", + "productName": "Ürün Adı", + "professionalName": "Meslek Adı", + "professionalTitle": "Mesleki Ünvan", + "readMore": "Devamını oku", + "services": "Hizmetler", + "servicesOffered": "Sunulan Hizmetler", + "subtitle": "Altyazı", + "text": "Metin", + "upcomingEvents": "Yaklaşan Etkinlikler", + "visitProfile": "Profili Ziyaret Et" + }, "componentErrorBoundary": { "error": "Hata", "message": "Bu bölüm oluşturulamıyor. Bileşen kitaplığınızı güncellemeyi deneyin." diff --git a/packages/visual-editor/locales/platform/zh-TW/visual-editor.json b/packages/visual-editor/locales/platform/zh-TW/visual-editor.json index b382cdae4..b780fac11 100644 --- a/packages/visual-editor/locales/platform/zh-TW/visual-editor.json +++ b/packages/visual-editor/locales/platform/zh-TW/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "關閉菜單", "closesAtTime": "於 {{time}} 關閉", "closesAtTimeWeek": "於 {{time}} {{dayOfWeek}} 關閉", + "componentDefaults": { + "aboutName": "關於 [[name]]", + "articleName": "文章名稱", + "associateAgent": "助理代理", + "bannerText": "橫幅文字", + "businessName": "公司名稱", + "button": "按鈕", + "callToAction": "號召性用語", + "category": "類別", + "contactMe": "聯絡我", + "credentials": "證書", + "directoryRoot": "目錄根", + "eventImage": "活動圖片", + "eventTitle": "活動標題", + "featuredProducts": "特色產品", + "featuredPromotion": "特色促銷", + "featuredTestimonials": "特色推薦", + "findALocation": "尋找地點", + "firstLast": "名 姓", + "followUs": "跟著我們", + "footerLabel": "頁尾標籤", + "footerLink": "頁尾連結", + "frequentlyAskedQuestions": "常見問題解答", + "gallery": "畫廊", + "geomodifier": "地理修改器", + "getDirections": "獲取路線", + "header": "標頭", + "headerLink": "標題連結", + "hours": "時間", + "information": "資訊", + "insights": "見解", + "learnMore": "了解更多", + "logo": "標識", + "meetOurTeam": "認識我們的團隊", + "name": "姓名", + "nearbyLocations": "附近地點", + "phone": "電話", + "price": "NT$123.00", + "productName": "產品名稱", + "professionalName": "專業名稱", + "professionalTitle": "職稱", + "readMore": "閱讀更多", + "services": "服務", + "servicesOffered": "提供的服務", + "subtitle": "副標題", + "text": "文字", + "upcomingEvents": "即將舉行的活動", + "visitProfile": "訪問簡介" + }, "componentErrorBoundary": { "error": "錯誤", "message": "無法渲染此部分。嘗試更新您的組件庫。" diff --git a/packages/visual-editor/locales/platform/zh/visual-editor.json b/packages/visual-editor/locales/platform/zh/visual-editor.json index 79da6a401..7887140ee 100644 --- a/packages/visual-editor/locales/platform/zh/visual-editor.json +++ b/packages/visual-editor/locales/platform/zh/visual-editor.json @@ -46,6 +46,55 @@ "closeMenu": "关闭菜单", "closesAtTime": "于 {{time}} 关闭", "closesAtTimeWeek": "于 {{time}} {{dayOfWeek}} 关闭", + "componentDefaults": { + "aboutName": "关于 [[name]]", + "articleName": "文章名称", + "associateAgent": "助理代理", + "bannerText": "横幅文字", + "businessName": "公司名称", + "button": "按钮", + "callToAction": "号召性用语", + "category": "类别", + "contactMe": "联系我", + "credentials": "证书", + "directoryRoot": "目录根", + "eventImage": "活动图片", + "eventTitle": "活动标题", + "featuredProducts": "特色产品", + "featuredPromotion": "特色促销", + "featuredTestimonials": "特色推荐", + "findALocation": "寻找地点", + "firstLast": "第一个 最后一个", + "followUs": "关注我们", + "footerLabel": "页脚标签", + "footerLink": "页脚链接", + "frequentlyAskedQuestions": "常见问题解答", + "gallery": "画廊", + "geomodifier": "地理修改器", + "getDirections": "获取路线", + "header": "标头", + "headerLink": "标题链接", + "hours": "时间", + "information": "信息", + "insights": "见解", + "learnMore": "了解更多", + "logo": "标识", + "meetOurTeam": "认识我们的团队", + "name": "姓名", + "nearbyLocations": "附近地点", + "phone": "电话", + "price": "$123.00", + "productName": "产品名称", + "professionalName": "专业名称", + "professionalTitle": "职称", + "readMore": "阅读更多", + "services": "服务", + "servicesOffered": "提供的服务", + "subtitle": "副标题", + "text": "文本", + "upcomingEvents": "即将举行的活动", + "visitProfile": "访问简介" + }, "componentErrorBoundary": { "error": "错误", "message": "无法渲染此部分。尝试更新您的组件库。" diff --git a/packages/visual-editor/scripts/generateTranslations.ts b/packages/visual-editor/scripts/generateTranslations.ts index 2bf98164b..1026cfd2d 100644 --- a/packages/visual-editor/scripts/generateTranslations.ts +++ b/packages/visual-editor/scripts/generateTranslations.ts @@ -12,7 +12,7 @@ import { * Fills missing platform locale values using Google Translate. * * Behavior: - * - Reads English source strings from locales/platform/en/visual-editor.json. + * - Reads English source strings from `locales/platform/en/visual-editor.json`. * - Translates only missing/empty keys in non-English platform locale files. * - Adds contextual hints to ambiguous keys and removes them after translation. * - Preserves nested object JSON shape on disk. @@ -35,11 +35,11 @@ interface MaskedVariable { original: string; } -interface TranslationTarget { +type TranslationTarget = { key: string; english: string; sourceKey: string; -} +}; type GoogleTranslationSegment = [translatedText: string, ...rest: unknown[]]; type GoogleTranslateResponse = [GoogleTranslationSegment[], ...rest: unknown[]]; @@ -51,13 +51,11 @@ type GoogleTranslateResponse = [GoogleTranslationSegment[], ...rest: unknown[]]; const getTypeArg = (): TranslationType => { const index = process.argv.findIndex((arg) => arg === "--type"); const raw = index >= 0 ? process.argv[index + 1] : "platform"; - if (raw !== "platform") { throw new Error( `Unsupported --type "${raw}". This script only supports "--type platform".` ); } - return "platform"; }; @@ -346,6 +344,7 @@ const translateFile = async (type: TranslationType): Promise => { if (context) { translated = removeEmbeddedContext(translated); } + translated = unmaskInterpolationVariables(translated, variables); cache.set(key.trim(), translated); diff --git a/packages/visual-editor/src/components/Locator.tsx b/packages/visual-editor/src/components/Locator.tsx index 35fd8b885..5fc7d1adb 100644 --- a/packages/visual-editor/src/components/Locator.tsx +++ b/packages/visual-editor/src/components/Locator.tsx @@ -59,6 +59,7 @@ import { toMeters, toMiles, } from "../utils/i18n/distance.ts"; +import { defaultText } from "../utils/i18n/defaultContent.ts"; import { msg } from "../utils/i18n/platform.ts"; import { resolveComponentData } from "../utils/resolveComponentData.tsx"; import { @@ -88,7 +89,6 @@ const DEFAULT_MAP_CENTER: [number, number] = [-74.005371, 40.741611]; // New Yor const DEFAULT_RADIUS = 25; const HOURS_FIELD = "builtin.hours"; const INITIAL_LOCATION_KEY = "initialLocation"; -const DEFAULT_TITLE = "Find a Location"; const translateDistanceUnit = ( t: (key: string, options?: Record) => string, @@ -603,10 +603,7 @@ export const LocatorComponent: ComponentConfig<{ props: LocatorProps }> = { showDistanceOptions: false, }, pageHeading: { - title: { - en: DEFAULT_TITLE, - hasLocalizedValue: "true", - }, + title: defaultText("componentDefaults.findALocation", "Find a Location"), }, resultCard: DEFAULT_LOCATOR_RESULT_CARD_PROPS, }, diff --git a/packages/visual-editor/src/components/contentBlocks/BodyText.tsx b/packages/visual-editor/src/components/contentBlocks/BodyText.tsx index 1103a53a4..9a5a4a514 100644 --- a/packages/visual-editor/src/components/contentBlocks/BodyText.tsx +++ b/packages/visual-editor/src/components/contentBlocks/BodyText.tsx @@ -12,6 +12,7 @@ import { TranslatableRichText } from "../../types/types.ts"; import { useBackground } from "../../hooks/useBackground.tsx"; import { resolveDataFromParent } from "../../editor/ParentData.tsx"; import { BackgroundStyle } from "../../index.ts"; +import { defaultRichText } from "../../utils/i18n/defaultContent.ts"; export type BodyTextProps = { data: { @@ -114,10 +115,7 @@ export const BodyText: ComponentConfig<{ props: BodyTextProps }> = { data: { text: { field: "", - constantValue: { - en: "Text", - hasLocalizedValue: "true", - }, + constantValue: defaultRichText("componentDefaults.text", "Text"), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/contentBlocks/CtaWrapper.tsx b/packages/visual-editor/src/components/contentBlocks/CtaWrapper.tsx index 50a5feef8..030a42906 100644 --- a/packages/visual-editor/src/components/contentBlocks/CtaWrapper.tsx +++ b/packages/visual-editor/src/components/contentBlocks/CtaWrapper.tsx @@ -24,6 +24,7 @@ import { ctaTypeOptions, getCTAType, } from "../../internal/puck/constant-value-fields/EnhancedCallToAction.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface CTAWrapperProps { data: { @@ -297,17 +298,11 @@ export const CTAWrapper: ComponentConfig<{ props: CTAWrapperProps }> = { }, selectedType: "textAndLink", }, - buttonText: { - en: "Button", - hasLocalizedValue: "true", - }, + buttonText: defaultText("componentDefaults.button", "Button"), customId: "", customClass: "", dataAttributes: [], - ariaLabel: { - en: "Button", - hasLocalizedValue: "true", - }, + ariaLabel: defaultText("componentDefaults.button", "Button"), }, styles: { variant: "primary", diff --git a/packages/visual-editor/src/components/contentBlocks/HeadingText.tsx b/packages/visual-editor/src/components/contentBlocks/HeadingText.tsx index 1a73bbd7c..31d40d126 100644 --- a/packages/visual-editor/src/components/contentBlocks/HeadingText.tsx +++ b/packages/visual-editor/src/components/contentBlocks/HeadingText.tsx @@ -15,6 +15,7 @@ import { } from "../../utils/themeConfigOptions.ts"; import { resolveDataFromParent } from "../../editor/ParentData.tsx"; import { useTranslation } from "react-i18next"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export type HeadingTextProps = { /** The heading text value */ @@ -131,10 +132,7 @@ export const HeadingText: ComponentConfig<{ props: HeadingTextProps }> = { data: { text: { field: "", - constantValue: { - en: "Text", - hasLocalizedValue: "true", - }, + constantValue: defaultText("componentDefaults.text", "Text"), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/contentBlocks/Phone.tsx b/packages/visual-editor/src/components/contentBlocks/Phone.tsx index a101e67d4..65840d40a 100644 --- a/packages/visual-editor/src/components/contentBlocks/Phone.tsx +++ b/packages/visual-editor/src/components/contentBlocks/Phone.tsx @@ -10,6 +10,7 @@ import { YextField } from "../../editor/YextField.tsx"; import { TranslatableString } from "../../types/types.ts"; import { backgroundColors } from "../../utils/themeConfigOptions.ts"; import { resolveDataFromParent } from "../../editor/ParentData.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; /** The props for the Phone component */ export interface PhoneProps { @@ -81,10 +82,7 @@ export const defaultPhoneDataProps: PhoneProps["data"] = { field: "mainPhone", constantValue: "", }, - label: { - en: "Phone", - hasLocalizedValue: "true", - }, + label: defaultText("componentDefaults.phone", "Phone"), }; export const PhoneFields: Fields = { diff --git a/packages/visual-editor/src/components/contentBlocks/Text.tsx b/packages/visual-editor/src/components/contentBlocks/Text.tsx index 4f40a4726..60a5f081f 100644 --- a/packages/visual-editor/src/components/contentBlocks/Text.tsx +++ b/packages/visual-editor/src/components/contentBlocks/Text.tsx @@ -13,6 +13,7 @@ import { resolveDataFromParent } from "../../editor/ParentData.tsx"; import { BackgroundStyle } from "../../utils/themeConfigOptions.ts"; import { normalizeThemeColor } from "../../utils/normalizeThemeColor.ts"; import { themeManagerCn } from "../../utils/cn.ts"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export type TextProps = { data: { @@ -136,10 +137,7 @@ export const Text: ComponentConfig<{ props: TextProps }> = { data: { text: { field: "", - constantValue: { - en: "Text", - hasLocalizedValue: "true", - }, + constantValue: defaultText("componentDefaults.text", "Text"), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/contentBlocks/image/Image.tsx b/packages/visual-editor/src/components/contentBlocks/image/Image.tsx index 2e5728e63..d012bfd72 100644 --- a/packages/visual-editor/src/components/contentBlocks/image/Image.tsx +++ b/packages/visual-editor/src/components/contentBlocks/image/Image.tsx @@ -152,7 +152,7 @@ const ImageWrapperComponent: PuckComponent = (props) => { (typeof imageUrl === "string" && imageUrl.trim() === ""); const inputLink = resolveComponentData( - data.link ?? { en: DEFAULT_LINK, hasLocalizedValue: "true" as const }, + data.link ?? DEFAULT_LINK, i18n.language, streamDocument ); @@ -238,7 +238,7 @@ export const imageDefaultProps = { }, constantValueEnabled: true, }, - link: { en: DEFAULT_LINK, hasLocalizedValue: "true" as const }, + link: DEFAULT_LINK, }, styles: { aspectRatio: 1.78, diff --git a/packages/visual-editor/src/components/directory/Directory.tsx b/packages/visual-editor/src/components/directory/Directory.tsx index abf4dcf4b..e2a81a5a5 100644 --- a/packages/visual-editor/src/components/directory/Directory.tsx +++ b/packages/visual-editor/src/components/directory/Directory.tsx @@ -13,6 +13,7 @@ import { ComponentConfig, Fields, PuckComponent, Slot } from "@puckeditor/core"; import { AnalyticsScopeProvider } from "@yext/pages-components"; import { DirectoryList } from "./DirectoryWrapper.tsx"; import { isDirectoryGrid } from "../../utils/directory/utils.ts"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface DirectoryStyles { /** @@ -127,10 +128,7 @@ export const Directory: ComponentConfig<{ props: DirectoryProps }> = { props: { data: { text: { - constantValue: { - en: "", - hasLocalizedValue: "true", - }, + constantValue: "", constantValueEnabled: false, field: "name", }, @@ -145,10 +143,7 @@ export const Directory: ComponentConfig<{ props: DirectoryProps }> = { props: { data: { text: { - constantValue: { - en: "", - hasLocalizedValue: "true", - }, + constantValue: "", constantValueEnabled: true, field: "name", }, @@ -162,10 +157,10 @@ export const Directory: ComponentConfig<{ props: DirectoryProps }> = { type: "BreadcrumbsSlot", props: { data: { - directoryRoot: { - en: "Directory Root", - hasLocalizedValue: "true", - }, + directoryRoot: defaultText( + "componentDefaults.directoryRoot", + "Directory Root" + ), }, styles: { backgroundColor: backgroundColors.background1.value, diff --git a/packages/visual-editor/src/components/footer/CopyrightMessageSlot.tsx b/packages/visual-editor/src/components/footer/CopyrightMessageSlot.tsx index fd8cdce2c..7b04a08d0 100644 --- a/packages/visual-editor/src/components/footer/CopyrightMessageSlot.tsx +++ b/packages/visual-editor/src/components/footer/CopyrightMessageSlot.tsx @@ -56,10 +56,7 @@ const CopyrightMessageSlotInternal: PuckComponent = ( export const defaultCopyrightMessageSlotProps: CopyrightMessageSlotProps = { data: { - text: { - en: "", - hasLocalizedValue: "true", - }, + text: "", }, }; diff --git a/packages/visual-editor/src/components/footer/ExpandedFooter.tsx b/packages/visual-editor/src/components/footer/ExpandedFooter.tsx index 33e1f2304..dd6f7adbd 100644 --- a/packages/visual-editor/src/components/footer/ExpandedFooter.tsx +++ b/packages/visual-editor/src/components/footer/ExpandedFooter.tsx @@ -10,16 +10,14 @@ import { Background } from "../atoms/background.tsx"; import { PageSection, PageSectionProps } from "../atoms/pageSection.tsx"; import { themeManagerCn } from "../../utils/cn.ts"; import { defaultCopyrightMessageSlotProps } from "./CopyrightMessageSlot.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; const PLACEHOLDER_LOGO_IMAGE: string = "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg"; export const defaultLink = { linkType: "URL" as const, - label: { - en: "Footer Link", - hasLocalizedValue: "true" as const, - }, + label: defaultText("componentDefaults.footerLink", "Footer Link"), link: "#", openInNewTab: false, }; @@ -322,7 +320,7 @@ export const ExpandedFooter: ComponentConfig<{ props: ExpandedFooterProps }> = { url: PLACEHOLDER_LOGO_IMAGE, height: 100, width: 100, - alternateText: { en: "Logo", hasLocalizedValue: "true" }, + alternateText: defaultText("componentDefaults.logo", "Logo"), }, constantValueEnabled: true, }, @@ -383,19 +381,31 @@ export const ExpandedFooter: ComponentConfig<{ props: ExpandedFooterProps }> = { data: { sections: [ { - label: { en: "Footer Label", hasLocalizedValue: "true" }, + label: defaultText( + "componentDefaults.footerLabel", + "Footer Label" + ), links: defaultLinks, }, { - label: { en: "Footer Label", hasLocalizedValue: "true" }, + label: defaultText( + "componentDefaults.footerLabel", + "Footer Label" + ), links: defaultLinks, }, { - label: { en: "Footer Label", hasLocalizedValue: "true" }, + label: defaultText( + "componentDefaults.footerLabel", + "Footer Label" + ), links: defaultLinks, }, { - label: { en: "Footer Label", hasLocalizedValue: "true" }, + label: defaultText( + "componentDefaults.footerLabel", + "Footer Label" + ), links: defaultLinks, }, ], diff --git a/packages/visual-editor/src/components/footer/FooterExpandedLinkSectionSlot.tsx b/packages/visual-editor/src/components/footer/FooterExpandedLinkSectionSlot.tsx index a2e7b1dc6..e0a8d28a6 100644 --- a/packages/visual-editor/src/components/footer/FooterExpandedLinkSectionSlot.tsx +++ b/packages/visual-editor/src/components/footer/FooterExpandedLinkSectionSlot.tsx @@ -12,6 +12,7 @@ import { i18nComponentsInstance } from "../../utils/i18n/components.ts"; import { useBackground } from "../../hooks/useBackground.tsx"; import { useTranslation } from "react-i18next"; import { defaultLink, defaultLinks } from "./ExpandedFooter.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface FooterExpandedLinkSectionSlotProps { data: { @@ -79,7 +80,10 @@ const defaultFooterExpandedLinkSectionProps: FooterExpandedLinkSectionSlotProps data: { label: { field: "", - constantValue: { en: "Footer Label", hasLocalizedValue: "true" }, + constantValue: defaultText( + "componentDefaults.footerLabel", + "Footer Label" + ), constantValueEnabled: true, }, links: defaultLinks, diff --git a/packages/visual-editor/src/components/footer/FooterExpandedLinksWrapper.tsx b/packages/visual-editor/src/components/footer/FooterExpandedLinksWrapper.tsx index 026735fb0..f7133d117 100644 --- a/packages/visual-editor/src/components/footer/FooterExpandedLinksWrapper.tsx +++ b/packages/visual-editor/src/components/footer/FooterExpandedLinksWrapper.tsx @@ -11,9 +11,10 @@ import { useBackground } from "../../hooks/useBackground.tsx"; import { Body } from "../atoms/body.tsx"; import { useTranslation } from "react-i18next"; import { defaultLink, defaultLinks } from "./ExpandedFooter.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; const defaultSection = { - label: { en: "Footer Label", hasLocalizedValue: "true" as const }, + label: defaultText("componentDefaults.footerLabel", "Footer Label"), links: defaultLinks, }; diff --git a/packages/visual-editor/src/components/footer/FooterLogoSlot.tsx b/packages/visual-editor/src/components/footer/FooterLogoSlot.tsx index 88b362f8c..1fea7fe5b 100644 --- a/packages/visual-editor/src/components/footer/FooterLogoSlot.tsx +++ b/packages/visual-editor/src/components/footer/FooterLogoSlot.tsx @@ -12,6 +12,7 @@ import { useTranslation } from "react-i18next"; import { ImageStylingFields } from "../contentBlocks/image/styling.ts"; import { ComplexImageType, ImageType } from "@yext/pages-components"; import { getImageUrl } from "../contentBlocks/image/Image.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface FooterLogoSlotProps { data: { @@ -120,7 +121,7 @@ export const FooterLogoSlot: ComponentConfig<{ props: FooterLogoSlotProps }> = { url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", height: 100, width: 100, - alternateText: { en: "Logo", hasLocalizedValue: "true" }, + alternateText: defaultText("componentDefaults.logo", "Logo"), }, constantValueEnabled: true, }, diff --git a/packages/visual-editor/src/components/footer/SecondaryFooterSlot.tsx b/packages/visual-editor/src/components/footer/SecondaryFooterSlot.tsx index c0cee2cf1..cc3ffb252 100644 --- a/packages/visual-editor/src/components/footer/SecondaryFooterSlot.tsx +++ b/packages/visual-editor/src/components/footer/SecondaryFooterSlot.tsx @@ -5,13 +5,11 @@ import { msg, pt } from "../../utils/i18n/platform.ts"; import { BackgroundStyle } from "../../utils/themeConfigOptions.ts"; import { PageSection, PageSectionProps } from "../atoms/pageSection.tsx"; import { defaultCopyrightMessageSlotProps } from "./CopyrightMessageSlot.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; const defaultLink = { linkType: "URL" as const, - label: { - en: "Footer Link", - hasLocalizedValue: "true" as const, - }, + label: defaultText("componentDefaults.footerLink", "Footer Link"), link: "#", openInNewTab: false, }; diff --git a/packages/visual-editor/src/components/header/HeaderLinks.tsx b/packages/visual-editor/src/components/header/HeaderLinks.tsx index c19af2566..d777b21fc 100644 --- a/packages/visual-editor/src/components/header/HeaderLinks.tsx +++ b/packages/visual-editor/src/components/header/HeaderLinks.tsx @@ -26,6 +26,7 @@ import { import { getHeaderViewport } from "./viewport.ts"; import { BackgroundStyle } from "../../utils/themeConfigOptions.ts"; import { BodyProps } from "../atoms/body.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export type HeaderLinksProps = { data: { @@ -63,7 +64,7 @@ export type HeaderLinksProps = { const defaultLink: TranslatableCTA = { linkType: "URL", - label: { en: "Header Link", hasLocalizedValue: "true" }, + label: defaultText("componentDefaults.headerLink", "Header Link"), link: "#", openInNewTab: false, }; diff --git a/packages/visual-editor/src/components/header/PrimaryHeaderSlot.tsx b/packages/visual-editor/src/components/header/PrimaryHeaderSlot.tsx index d1ef34b57..b708fb048 100644 --- a/packages/visual-editor/src/components/header/PrimaryHeaderSlot.tsx +++ b/packages/visual-editor/src/components/header/PrimaryHeaderSlot.tsx @@ -30,6 +30,7 @@ import { } from "./ExpandedHeaderMenuContext.tsx"; import { getHeaderViewport } from "./viewport.ts"; import { SlidePanel } from "./SlidePanel.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; const HAMBURGER_RESERVE_PX = 48; @@ -424,12 +425,15 @@ export const defaultPrimaryHeaderProps: PrimaryHeaderSlotProps = { data: { show: true, actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: { en: "Call to Action", hasLocalizedValue: "true" }, - link: { en: "#", hasLocalizedValue: "true" }, + label: defaultText( + "componentDefaults.callToAction", + "Call to Action" + ), + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -451,12 +455,15 @@ export const defaultPrimaryHeaderProps: PrimaryHeaderSlotProps = { data: { show: true, actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: { en: "Call to Action", hasLocalizedValue: "true" }, - link: { en: "#", hasLocalizedValue: "true" }, + label: defaultText( + "componentDefaults.callToAction", + "Call to Action" + ), + link: "#", linkType: "URL", ctaType: "textAndLink", }, diff --git a/packages/visual-editor/src/components/pageSections/AboutSection/AboutSection.tsx b/packages/visual-editor/src/components/pageSections/AboutSection/AboutSection.tsx index 7acfd919d..dc499dcba 100644 --- a/packages/visual-editor/src/components/pageSections/AboutSection/AboutSection.tsx +++ b/packages/visual-editor/src/components/pageSections/AboutSection/AboutSection.tsx @@ -25,13 +25,11 @@ import { defaultAboutSectionProps, } from "./AboutSectionDetailsColumn.tsx"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; const placeholderText = { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1},{"type":"linebreak","version":1},{"type":"linebreak","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1},{"type":"linebreak","version":1},{"type":"linebreak","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1},{"type":"linebreak","version":1},{"type":"linebreak","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1},{"type":"linebreak","version":1},{"type":"linebreak","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1},{"type":"linebreak","version":1},{"type":"linebreak","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1},{"type":"linebreak","version":1},{"type":"linebreak","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.

', }; export type AboutSectionProps = { @@ -202,10 +200,10 @@ export const AboutSection: ComponentConfig<{ props: AboutSectionProps }> = { props: { data: { text: { - constantValue: { - en: "About [[name]]", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.aboutName", + "About [[name]]" + ), constantValueEnabled: true, field: "", }, @@ -242,10 +240,10 @@ export const AboutSection: ComponentConfig<{ props: AboutSectionProps }> = { { header: { field: "", - constantValue: { - en: "Hours", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.hours", + "Hours" + ), constantValueEnabled: true, }, content: { @@ -256,10 +254,10 @@ export const AboutSection: ComponentConfig<{ props: AboutSectionProps }> = { { header: { field: "", - constantValue: { - en: "Services Offered", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.servicesOffered", + "Services Offered" + ), constantValueEnabled: true, }, content: { @@ -276,10 +274,10 @@ export const AboutSection: ComponentConfig<{ props: AboutSectionProps }> = { { header: { field: "", - constantValue: { - en: "Follow Us", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.followUs", + "Follow Us" + ), constantValueEnabled: true, }, content: { diff --git a/packages/visual-editor/src/components/pageSections/AboutSection/AboutSectionDetailsColumn.tsx b/packages/visual-editor/src/components/pageSections/AboutSection/AboutSectionDetailsColumn.tsx index 819de2029..fd290375c 100644 --- a/packages/visual-editor/src/components/pageSections/AboutSection/AboutSectionDetailsColumn.tsx +++ b/packages/visual-editor/src/components/pageSections/AboutSection/AboutSectionDetailsColumn.tsx @@ -52,6 +52,7 @@ import { hoursTableFields, HoursTable, } from "../../contentBlocks/HoursTable.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export type AboutSectionDetailsColumnProps = { sections: DetailSection[]; @@ -137,10 +138,7 @@ export const defaultAboutSectionProps: Omit = constantValue: "", constantValueEnabled: false, }, - label: { - en: "Phone", - hasLocalizedValue: "true", - }, + label: defaultText("componentDefaults.phone", "Phone"), }, styles: { phoneFormat: "domestic", @@ -301,7 +299,7 @@ const aboutSectionDetailsColumnFields: Fields = defaultItemProps: { header: { field: "", - constantValue: { en: "Header", hasLocalizedValue: "true" }, + constantValue: defaultText("componentDefaults.header", "Header"), constantValueEnabled: true, }, content: { diff --git a/packages/visual-editor/src/components/pageSections/Banner.tsx b/packages/visual-editor/src/components/pageSections/Banner.tsx index 5ddf8d0eb..3ba8a9b9f 100644 --- a/packages/visual-editor/src/components/pageSections/Banner.tsx +++ b/packages/visual-editor/src/components/pageSections/Banner.tsx @@ -10,7 +10,6 @@ import { EntityField } from "../../editor/EntityField.tsx"; import { TranslatableRichText } from "../../types/types.ts"; import { msg, pt } from "../../utils/i18n/platform.ts"; import { Body } from "../atoms/body.tsx"; -import { getDefaultRTF } from "../../editor/TranslatableRichTextField.tsx"; import { ComponentConfig, Fields, PuckComponent } from "@puckeditor/core"; import { backgroundColors, @@ -20,6 +19,7 @@ import { CircleSlash2 } from "lucide-react"; import { useTemplateMetadata } from "../../internal/hooks/useMessageReceivers.ts"; import { resolveYextEntityField } from "../../utils/resolveYextEntityField.ts"; import { ComponentErrorBoundary } from "../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultRichText } from "../../utils/i18n/defaultContent.ts"; export interface BannerData { /** @@ -230,10 +230,10 @@ export const defaultBannerProps: BannerSectionProps = { data: { text: { field: "", - constantValue: { - en: getDefaultRTF("Banner Text"), - hasLocalizedValue: "true", - }, + constantValue: defaultRichText( + "componentDefaults.bannerText", + "Banner Text" + ), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/pageSections/Breadcrumbs.tsx b/packages/visual-editor/src/components/pageSections/Breadcrumbs.tsx index ef9003a8e..8493634c1 100644 --- a/packages/visual-editor/src/components/pageSections/Breadcrumbs.tsx +++ b/packages/visual-editor/src/components/pageSections/Breadcrumbs.tsx @@ -15,6 +15,7 @@ import { ComponentConfig, Fields } from "@puckeditor/core"; import { AnalyticsScopeProvider } from "@yext/pages-components"; import { ComponentErrorBoundary } from "../../internal/components/ComponentErrorBoundary.tsx"; import { resolveBreadcrumbs } from "../../utils/urls/resolveBreadcrumbs.ts"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface BreadcrumbsData { /** @@ -184,10 +185,10 @@ export const BreadcrumbsSection: ComponentConfig<{ fields: breadcrumbsSectionFields, defaultProps: { data: { - directoryRoot: { - en: "Directory Root", - hasLocalizedValue: "true", - }, + directoryRoot: defaultText( + "componentDefaults.directoryRoot", + "Directory Root" + ), }, styles: { backgroundColor: backgroundColors.background1.value, diff --git a/packages/visual-editor/src/components/pageSections/CoreInfoSection.tsx b/packages/visual-editor/src/components/pageSections/CoreInfoSection.tsx index cd590861c..fd1da9a5f 100644 --- a/packages/visual-editor/src/components/pageSections/CoreInfoSection.tsx +++ b/packages/visual-editor/src/components/pageSections/CoreInfoSection.tsx @@ -23,6 +23,7 @@ import { resolvePhoneNumbers, } from "../contentBlocks/PhoneList.tsx"; import { ComponentErrorBoundary } from "../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface CoreInfoStyles { /** @@ -201,10 +202,10 @@ export const CoreInfoSection: ComponentConfig<{ props: CoreInfoSectionProps }> = props: { data: { text: { - constantValue: { - en: "Information", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.information", + "Information" + ), constantValueEnabled: true, field: "", }, @@ -246,10 +247,7 @@ export const CoreInfoSection: ComponentConfig<{ props: CoreInfoSectionProps }> = field: "mainPhone", constantValue: "", }, - label: { - en: "Phone", - hasLocalizedValue: "true", - }, + label: defaultText("componentDefaults.phone", "Phone"), }, ], }, @@ -282,10 +280,10 @@ export const CoreInfoSection: ComponentConfig<{ props: CoreInfoSectionProps }> = props: { data: { text: { - constantValue: { - en: "Hours", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.hours", + "Hours" + ), constantValueEnabled: true, field: "", }, @@ -319,10 +317,10 @@ export const CoreInfoSection: ComponentConfig<{ props: CoreInfoSectionProps }> = props: { data: { text: { - constantValue: { - en: "Services", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.services", + "Services" + ), constantValueEnabled: true, field: "", }, diff --git a/packages/visual-editor/src/components/pageSections/EventSection/EventCard.tsx b/packages/visual-editor/src/components/pageSections/EventSection/EventCard.tsx index 4dc959f79..0981639f9 100644 --- a/packages/visual-editor/src/components/pageSections/EventSection/EventCard.tsx +++ b/packages/visual-editor/src/components/pageSections/EventSection/EventCard.tsx @@ -25,11 +25,12 @@ import { ImgSizesByBreakpoint } from "../../atoms/image.tsx"; import { resolveYextEntityField } from "../../../utils/resolveYextEntityField.ts"; import { i18nComponentsInstance } from "../../../utils/i18n/components.ts"; import { resolveComponentData } from "../../../utils/resolveComponentData.tsx"; -import { getDefaultRTF } from "../../../editor/TranslatableRichTextField.tsx"; import { useCardContext } from "../../../hooks/useCardContext.tsx"; import { useGetCardSlots } from "../../../hooks/useGetCardSlots.tsx"; import { getRandomPlaceholderImageObject } from "../../../utils/imagePlaceholders.ts"; import { syncParentStyles } from "../../../utils/cardSlots/syncParentStyles.ts"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; +import { getDefaultRTF } from "../../../editor/TranslatableRichTextField.tsx"; const defaultEvent = { image: { @@ -37,16 +38,13 @@ const defaultEvent = { height: 360, width: 640, }, - title: { en: "Event Title", hasLocalizedValue: "true" }, + title: defaultText("componentDefaults.eventTitle", "Event Title"), dateTime: "2022-12-12T14:00:00", - description: { - en: getDefaultRTF( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - ), - hasLocalizedValue: "true", - }, + description: getDefaultRTF( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + ), cta: { - label: { en: "Learn More", hasLocalizedValue: "true" }, + label: defaultText("componentDefaults.learnMore", "Learn More"), link: "#", linkType: "URL", ctaType: "textAndLink", @@ -85,7 +83,10 @@ export const defaultEventCardSlotData = ( }), width: 640, height: 360, - alternateText: "Event Image", + alternateText: defaultText( + "componentDefaults.eventImage", + "Event Image" + ), }, constantValueEnabled: true, }, @@ -169,7 +170,7 @@ export const defaultEventCardSlotData = ( ...(id && { id: `${id}-cta` }), data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: defaultEvent.cta, diff --git a/packages/visual-editor/src/components/pageSections/EventSection/EventSection.tsx b/packages/visual-editor/src/components/pageSections/EventSection/EventSection.tsx index dc6c77437..e9b1aa597 100644 --- a/packages/visual-editor/src/components/pageSections/EventSection/EventSection.tsx +++ b/packages/visual-editor/src/components/pageSections/EventSection/EventSection.tsx @@ -13,6 +13,7 @@ import { defaultEventCardSlotData } from "./EventCard.tsx"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; import { EventCardsWrapperProps } from "./EventCardsWrapper.tsx"; import { forwardHeadingLevel } from "../../../utils/cardSlots/forwardHeadingLevel.ts"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface EventSectionProps { /** @@ -135,10 +136,10 @@ export const EventSection: ComponentConfig<{ props: EventSectionProps }> = { props: { data: { text: { - constantValue: { - en: "Upcoming Events", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.upcomingEvents", + "Upcoming Events" + ), constantValueEnabled: true, field: "", }, diff --git a/packages/visual-editor/src/components/pageSections/FAQsSection/FAQCard.tsx b/packages/visual-editor/src/components/pageSections/FAQsSection/FAQCard.tsx index d3b2ac4d8..b0a5819ed 100644 --- a/packages/visual-editor/src/components/pageSections/FAQsSection/FAQCard.tsx +++ b/packages/visual-editor/src/components/pageSections/FAQsSection/FAQCard.tsx @@ -26,16 +26,10 @@ import { useGetCardSlots } from "../../../hooks/useGetCardSlots.tsx"; import { BackgroundStyle } from "../../../utils/themeConfigOptions.ts"; const defaultFAQ = { - question: { - en: "Question Lorem ipsum dolor sit amet?", - hasLocalizedValue: "true", - }, - answer: { - en: getDefaultRTF( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." - ), - hasLocalizedValue: "true", - }, + question: "Question Lorem ipsum dolor sit amet?", + answer: getDefaultRTF( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + ), } satisfies FAQStruct; export const defaultFAQCardData = ( diff --git a/packages/visual-editor/src/components/pageSections/FAQsSection/FAQsSection.tsx b/packages/visual-editor/src/components/pageSections/FAQsSection/FAQsSection.tsx index 925dbe903..805d6d3d1 100644 --- a/packages/visual-editor/src/components/pageSections/FAQsSection/FAQsSection.tsx +++ b/packages/visual-editor/src/components/pageSections/FAQsSection/FAQsSection.tsx @@ -25,6 +25,7 @@ import { AnalyticsScopeProvider } from "@yext/pages-components"; import { defaultFAQCardData, FAQCardProps } from "./FAQCard.tsx"; import { CardContextProvider } from "../../../hooks/useCardContext.tsx"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface FAQStyles { /** @@ -160,10 +161,10 @@ export const FAQSection: ComponentConfig<{ props: FAQSectionProps }> = { props: { data: { text: { - constantValue: { - en: "Frequently Asked Questions", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.frequentlyAskedQuestions", + "Frequently Asked Questions" + ), constantValueEnabled: true, field: "", }, diff --git a/packages/visual-editor/src/components/pageSections/HeroSection.tsx b/packages/visual-editor/src/components/pageSections/HeroSection.tsx index eda70100a..4ae73bfa6 100644 --- a/packages/visual-editor/src/components/pageSections/HeroSection.tsx +++ b/packages/visual-editor/src/components/pageSections/HeroSection.tsx @@ -31,6 +31,7 @@ import { SpotlightHero } from "./heroVariants/SpotlightHero.js"; import { ImmersiveHero } from "./heroVariants/ImmersiveHero.js"; import { getRandomPlaceholderImageObject } from "../../utils/imagePlaceholders.ts"; import { ComponentErrorBoundary } from "../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface HeroData { backgroundImage: YextEntityField< @@ -406,10 +407,10 @@ export const HeroSection: ComponentConfig<{ props: HeroSectionProps }> = { props: { data: { text: { - constantValue: { - en: "Business Name", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.businessName", + "Business Name" + ), constantValueEnabled: true, field: "", }, @@ -424,10 +425,10 @@ export const HeroSection: ComponentConfig<{ props: HeroSectionProps }> = { props: { data: { text: { - constantValue: { - en: "Geomodifier", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.geomodifier", + "Geomodifier" + ), constantValueEnabled: true, field: "", }, @@ -485,18 +486,15 @@ export const HeroSection: ComponentConfig<{ props: HeroSectionProps }> = { props: { data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: { - en: "Call To Action", - hasLocalizedValue: "true", - }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + label: defaultText( + "componentDefaults.callToAction", + "Call to Action" + ), + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -516,18 +514,15 @@ export const HeroSection: ComponentConfig<{ props: HeroSectionProps }> = { props: { data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: { - en: "Learn More", - hasLocalizedValue: "true", - }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + label: defaultText( + "componentDefaults.learnMore", + "Learn More" + ), + link: "#", linkType: "URL", ctaType: "textAndLink", }, diff --git a/packages/visual-editor/src/components/pageSections/InsightSection/InsightCard.tsx b/packages/visual-editor/src/components/pageSections/InsightSection/InsightCard.tsx index abd39df99..a69272160 100644 --- a/packages/visual-editor/src/components/pageSections/InsightSection/InsightCard.tsx +++ b/packages/visual-editor/src/components/pageSections/InsightSection/InsightCard.tsx @@ -27,6 +27,7 @@ import { Slot, } from "@puckeditor/core"; import { syncParentStyles } from "../../../utils/cardSlots/syncParentStyles.ts"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; const defaultInsight = { image: { @@ -34,20 +35,14 @@ const defaultInsight = { width: 640, height: 360, }, - name: { en: "Article Name", hasLocalizedValue: "true" }, - category: { - en: "Category", - hasLocalizedValue: "true", - }, - description: { - en: getDefaultRTF( - "Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters" - ), - hasLocalizedValue: "true", - }, + name: defaultText("componentDefaults.articleName", "Article Name"), + category: defaultText("componentDefaults.category", "Category"), + description: getDefaultRTF( + "Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters" + ), publishTime: "2022-08-02T14:00:00", cta: { - label: { en: "Read More", hasLocalizedValue: "true" }, + label: defaultText("componentDefaults.readMore", "Read More"), link: "#", linkType: "URL", ctaType: "textAndLink", @@ -189,7 +184,7 @@ export const defaultInsightCardSlotData = ( ...(id && { id: `${id}-cta` }), data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: defaultInsight.cta, diff --git a/packages/visual-editor/src/components/pageSections/InsightSection/InsightSection.tsx b/packages/visual-editor/src/components/pageSections/InsightSection/InsightSection.tsx index e22a1fb9a..9e8fac480 100644 --- a/packages/visual-editor/src/components/pageSections/InsightSection/InsightSection.tsx +++ b/packages/visual-editor/src/components/pageSections/InsightSection/InsightSection.tsx @@ -14,6 +14,7 @@ import { forwardHeadingLevel } from "../../../utils/cardSlots/forwardHeadingLeve import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; import { defaultInsightCardSlotData } from "./InsightCard.tsx"; import { InsightCardsWrapperProps } from "./InsightCardsWrapper.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface InsightSectionProps { /** @@ -136,10 +137,10 @@ export const InsightSection: ComponentConfig<{ props: InsightSectionProps }> = { data: { text: { field: "", - constantValue: { - en: "Insights", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.insights", + "Insights" + ), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/pageSections/NearbyLocations/NearbyLocations.tsx b/packages/visual-editor/src/components/pageSections/NearbyLocations/NearbyLocations.tsx index e6e59b34e..64eecedb1 100644 --- a/packages/visual-editor/src/components/pageSections/NearbyLocations/NearbyLocations.tsx +++ b/packages/visual-editor/src/components/pageSections/NearbyLocations/NearbyLocations.tsx @@ -19,6 +19,7 @@ import { HeadingTextProps } from "../../contentBlocks/HeadingText.tsx"; import { AnalyticsScopeProvider } from "@yext/pages-components"; import { defaultNearbyLocationsCardsProps } from "./NearbyLocationsCardsWrapper.tsx"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface NearbyLocationsSectionProps { /** @@ -204,10 +205,10 @@ export const NearbyLocationsSection: ComponentConfig<{ data: { text: { field: "", - constantValue: { - en: "Nearby Locations", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.nearbyLocations", + "Nearby Locations" + ), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/pageSections/PhotoGallerySection/PhotoGallerySection.tsx b/packages/visual-editor/src/components/pageSections/PhotoGallerySection/PhotoGallerySection.tsx index 7fb06c175..990dde468 100644 --- a/packages/visual-editor/src/components/pageSections/PhotoGallerySection/PhotoGallerySection.tsx +++ b/packages/visual-editor/src/components/pageSections/PhotoGallerySection/PhotoGallerySection.tsx @@ -20,6 +20,7 @@ import { AssetImageType } from "../../../types/images.ts"; import { PhotoGalleryWrapperProps } from "./PhotoGalleryWrapper.tsx"; import { getRandomPlaceholderImageObject } from "../../../utils/imagePlaceholders.ts"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; // Generate 3 random placeholder images for the gallery export const PLACEHOLDER: AssetImageType = { @@ -164,10 +165,10 @@ export const PhotoGallerySection: ComponentConfig<{ data: { text: { field: "", - constantValue: { - en: "Gallery", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.gallery", + "Gallery" + ), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/pageSections/ProductSection/ProductCard.tsx b/packages/visual-editor/src/components/pageSections/ProductSection/ProductCard.tsx index cc7ce271f..1ea6a5fa9 100644 --- a/packages/visual-editor/src/components/pageSections/ProductSection/ProductCard.tsx +++ b/packages/visual-editor/src/components/pageSections/ProductSection/ProductCard.tsx @@ -31,6 +31,7 @@ import { getRandomPlaceholderImageObject } from "../../../utils/imagePlaceholder import { TextProps } from "../../contentBlocks/Text.tsx"; import { ProductSectionVariant } from "./ProductSection.tsx"; import { syncParentStyles } from "../../../utils/cardSlots/syncParentStyles.ts"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; const defaultProduct = { image: { @@ -38,23 +39,14 @@ const defaultProduct = { height: 360, width: 640, }, - brow: { - en: "Category", - hasLocalizedValue: "true", - }, - name: { en: "Product Name", hasLocalizedValue: "true" }, - price: { - en: "$123.00", - hasLocalizedValue: "true", - }, - description: { - en: getDefaultRTF( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - ), - hasLocalizedValue: "true", - }, + brow: defaultText("componentDefaults.category", "Category"), + name: defaultText("componentDefaults.productName", "Product Name"), + price: defaultText("componentDefaults.price", "$123.00"), + description: getDefaultRTF( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + ), cta: { - label: { en: "Learn More", hasLocalizedValue: "true" }, + label: defaultText("componentDefaults.learnMore", "Learn More"), link: "#", linkType: "URL", ctaType: "textAndLink", @@ -185,7 +177,7 @@ export const defaultProductCardSlotData = ( ...(id && { id: `${id}-cta` }), data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: defaultProduct.cta, diff --git a/packages/visual-editor/src/components/pageSections/ProductSection/ProductSection.tsx b/packages/visual-editor/src/components/pageSections/ProductSection/ProductSection.tsx index b6d819f9d..57136d92c 100644 --- a/packages/visual-editor/src/components/pageSections/ProductSection/ProductSection.tsx +++ b/packages/visual-editor/src/components/pageSections/ProductSection/ProductSection.tsx @@ -20,6 +20,7 @@ import { defaultProductCardSlotData } from "./ProductCard.tsx"; import { ProductCardsWrapperProps } from "./ProductCardsWrapper.tsx"; import { forwardHeadingLevel } from "../../../utils/cardSlots/forwardHeadingLevel.ts"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export type ProductSectionVariant = "immersive" | "classic" | "minimal"; export type ProductSectionImageConstrain = "fill" | "fixed"; @@ -163,10 +164,10 @@ export const ProductSection: ComponentConfig<{ props: ProductSectionProps }> = { data: { text: { field: "", - constantValue: { - en: "Featured Products", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.featuredProducts", + "Featured Products" + ), constantValueEnabled: true, }, }, diff --git a/packages/visual-editor/src/components/pageSections/ProfessionalHeroSection.tsx b/packages/visual-editor/src/components/pageSections/ProfessionalHeroSection.tsx index bfbcb3174..dd021c791 100644 --- a/packages/visual-editor/src/components/pageSections/ProfessionalHeroSection.tsx +++ b/packages/visual-editor/src/components/pageSections/ProfessionalHeroSection.tsx @@ -24,6 +24,7 @@ import { resolveComponentData } from "../../utils/resolveComponentData.tsx"; import { AnalyticsScopeProvider } from "@yext/pages-components"; import { getRandomPlaceholderImageObject } from "../../utils/imagePlaceholders.ts"; import { ComponentErrorBoundary } from "../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../utils/i18n/defaultContent.ts"; export interface ProfessionalHeroStyles { /** @@ -560,10 +561,10 @@ export const ProfessionalHeroSection: ComponentConfig<{ data: { text: { field: "", - constantValue: { - en: "Business Name", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.businessName", + "Business Name" + ), constantValueEnabled: true, }, }, @@ -580,10 +581,10 @@ export const ProfessionalHeroSection: ComponentConfig<{ data: { text: { field: "", - constantValue: { - en: "Credentials", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.credentials", + "Credentials" + ), constantValueEnabled: true, }, }, @@ -600,10 +601,10 @@ export const ProfessionalHeroSection: ComponentConfig<{ props: { data: { text: { - constantValue: { - en: "Professional Name", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.professionalName", + "Professional Name" + ), constantValueEnabled: true, field: "name", }, @@ -618,10 +619,10 @@ export const ProfessionalHeroSection: ComponentConfig<{ props: { data: { text: { - constantValue: { - en: "Professional Title", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.professionalTitle", + "Professional Title" + ), constantValueEnabled: true, field: "", }, @@ -640,10 +641,10 @@ export const ProfessionalHeroSection: ComponentConfig<{ props: { data: { text: { - constantValue: { - en: "Subtitle", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.subtitle", + "Subtitle" + ), constantValueEnabled: true, field: "", }, @@ -682,18 +683,15 @@ export const ProfessionalHeroSection: ComponentConfig<{ props: { data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: { - en: "Contact Me", - hasLocalizedValue: "true", - }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + label: defaultText( + "componentDefaults.contactMe", + "Contact Me" + ), + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -712,18 +710,15 @@ export const ProfessionalHeroSection: ComponentConfig<{ props: { data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: { - en: "Learn More", - hasLocalizedValue: "true", - }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + label: defaultText( + "componentDefaults.learnMore", + "Learn More" + ), + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -747,10 +742,7 @@ export const ProfessionalHeroSection: ComponentConfig<{ field: "mainPhone", constantValue: "", }, - label: { - en: "Phone", - hasLocalizedValue: "true", - }, + label: defaultText("componentDefaults.phone", "Phone"), }, ], }, diff --git a/packages/visual-editor/src/components/pageSections/PromoSection/PromoSection.tsx b/packages/visual-editor/src/components/pageSections/PromoSection/PromoSection.tsx index 052c15c45..15804b8eb 100644 --- a/packages/visual-editor/src/components/pageSections/PromoSection/PromoSection.tsx +++ b/packages/visual-editor/src/components/pageSections/PromoSection/PromoSection.tsx @@ -38,6 +38,7 @@ import { CompactPromo } from "./CompactPromo.tsx"; import { useTranslation } from "react-i18next"; import { PromoEmptyState } from "./PromoEmptyState.tsx"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface PromoData { /** @@ -352,10 +353,10 @@ export const PromoSection: ComponentConfig<{ props: PromoSectionProps }> = { data: { text: { field: "", - constantValue: { - en: "Featured Promotion", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.featuredPromotion", + "Featured Promotion" + ), constantValueEnabled: true, }, }, @@ -370,12 +371,9 @@ export const PromoSection: ComponentConfig<{ props: PromoSectionProps }> = { data: { text: { field: "", - constantValue: { - en: getDefaultRTF( - "Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 100 characters" - ), - hasLocalizedValue: "true", - }, + constantValue: getDefaultRTF( + "Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 100 characters" + ), constantValueEnabled: true, }, }, @@ -429,11 +427,14 @@ export const PromoSection: ComponentConfig<{ props: PromoSectionProps }> = { props: { data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: { - label: "Learn More", + label: defaultText( + "componentDefaults.learnMore", + "Learn More" + ), link: "#", linkType: "URL", ctaType: "textAndLink", diff --git a/packages/visual-editor/src/components/pageSections/TeamSection/TeamCard.tsx b/packages/visual-editor/src/components/pageSections/TeamSection/TeamCard.tsx index 27ad63884..48ec34668 100644 --- a/packages/visual-editor/src/components/pageSections/TeamSection/TeamCard.tsx +++ b/packages/visual-editor/src/components/pageSections/TeamSection/TeamCard.tsx @@ -28,14 +28,18 @@ import { useCardContext } from "../../../hooks/useCardContext.tsx"; import { useGetCardSlots } from "../../../hooks/useGetCardSlots.tsx"; import { TextProps } from "../../contentBlocks/Text.tsx"; import { syncParentStyles } from "../../../utils/cardSlots/syncParentStyles.ts"; +import { + defaultRichText, + defaultText, +} from "../../../utils/i18n/defaultContent.ts"; const defaultPerson = { - name: { en: "First Last", hasLocalizedValue: "true" }, - title: { en: "Associate Agent", hasLocalizedValue: "true" }, + name: defaultText("componentDefaults.firstLast", "First Last"), + title: defaultRichText("componentDefaults.associateAgent", "Associate Agent"), phoneNumber: "+12027706619", email: "jkelley@[company].com", cta: { - label: { en: "Visit Profile", hasLocalizedValue: "true" }, + label: defaultText("componentDefaults.visitProfile", "Visit Profile"), link: "#", linkType: "URL", ctaType: "textAndLink", @@ -135,10 +139,7 @@ export const defaultTeamCardSlotData = ( constantValue: defaultPerson.phoneNumber, constantValueEnabled: true, }, - label: { - en: "", - hasLocalizedValue: "true", - }, + label: "", }, ], }, @@ -176,7 +177,7 @@ export const defaultTeamCardSlotData = ( ...(id && { id: `${id}-cta` }), data: { actionType: "link", - buttonText: { en: "Button", hasLocalizedValue: "true" }, + buttonText: defaultText("componentDefaults.button", "Button"), entityField: { field: "", constantValue: defaultPerson.cta, diff --git a/packages/visual-editor/src/components/pageSections/TeamSection/TeamSection.tsx b/packages/visual-editor/src/components/pageSections/TeamSection/TeamSection.tsx index 129994ead..58e9a262d 100644 --- a/packages/visual-editor/src/components/pageSections/TeamSection/TeamSection.tsx +++ b/packages/visual-editor/src/components/pageSections/TeamSection/TeamSection.tsx @@ -14,6 +14,7 @@ import { defaultTeamCardSlotData } from "./TeamCard.tsx"; import { TeamCardsWrapperProps } from "./TeamCardsWrapper.tsx"; import { forwardHeadingLevel } from "../../../utils/cardSlots/forwardHeadingLevel.ts"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface TeamSectionProps { /** @@ -136,10 +137,10 @@ export const TeamSection: ComponentConfig<{ props: TeamSectionProps }> = { props: { data: { text: { - constantValue: { - en: "Meet Our Team", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.meetOurTeam", + "Meet Our Team" + ), constantValueEnabled: true, field: "", }, diff --git a/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialCard.tsx b/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialCard.tsx index addcc2e0c..0dfb50f50 100644 --- a/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialCard.tsx +++ b/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialCard.tsx @@ -20,20 +20,18 @@ import { BodyTextProps } from "../../contentBlocks/BodyText.tsx"; import { deepMerge } from "../../../utils/themeResolver.ts"; import { resolveYextEntityField } from "../../../utils/resolveYextEntityField.ts"; import { i18nComponentsInstance } from "../../../utils/i18n/components.ts"; -import { getDefaultRTF } from "../../../editor/TranslatableRichTextField.tsx"; import { TimestampProps } from "../../contentBlocks/Timestamp.tsx"; import { useCardContext } from "../../../hooks/useCardContext.tsx"; import { useGetCardSlots } from "../../../hooks/useGetCardSlots.tsx"; import { syncParentStyles } from "../../../utils/cardSlots/syncParentStyles.ts"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; +import { getDefaultRTF } from "../../../editor/TranslatableRichTextField.tsx"; const defaultTestimonial = { - description: { - en: getDefaultRTF( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." - ), - hasLocalizedValue: "true", - }, - contributorName: { en: "Name", hasLocalizedValue: "true" }, + description: getDefaultRTF( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + ), + contributorName: defaultText("componentDefaults.name", "Name"), contributionDate: "2022-08-02T14:00:00", } satisfies TestimonialStruct; diff --git a/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialSection.tsx b/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialSection.tsx index 41dcd145c..d3cc4dcd9 100644 --- a/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialSection.tsx +++ b/packages/visual-editor/src/components/pageSections/TestimonialSection/TestimonialSection.tsx @@ -14,6 +14,7 @@ import { defaultTestimonialCardSlotData } from "./TestimonialCard.tsx"; import { TestimonialCardsWrapperProps } from "./TestimonialCardsWrapper.tsx"; import { forwardHeadingLevel } from "../../../utils/cardSlots/forwardHeadingLevel.ts"; import { ComponentErrorBoundary } from "../../../internal/components/ComponentErrorBoundary.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export interface TestimonialSectionProps { /** @@ -140,10 +141,10 @@ export const TestimonialSection: ComponentConfig<{ props: { data: { text: { - constantValue: { - en: "Featured Testimonials", - hasLocalizedValue: "true", - }, + constantValue: defaultText( + "componentDefaults.featuredTestimonials", + "Featured Testimonials" + ), constantValueEnabled: true, field: "", }, diff --git a/packages/visual-editor/src/components/pageSections/VideoSection.tsx b/packages/visual-editor/src/components/pageSections/VideoSection.tsx index d0a74088a..71e0006c5 100644 --- a/packages/visual-editor/src/components/pageSections/VideoSection.tsx +++ b/packages/visual-editor/src/components/pageSections/VideoSection.tsx @@ -98,10 +98,7 @@ export const VideoSection: ComponentConfig<{ props: { data: { text: { - constantValue: { - en: "", - hasLocalizedValue: "true", - }, + constantValue: "", constantValueEnabled: true, field: "", }, diff --git a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with data.png b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with data.png index 319f0d4b9..513c73775 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with data.png and b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with data.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with no data.png b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with no data.png index 3c1363ac2..a3ef9045f 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with no data.png and b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[desktop] default props with no data.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with data.png b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with data.png index c2fef34d0..3a0928ade 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with data.png and b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with data.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with no data.png b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with no data.png index d232ee8cb..92d0a4091 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with no data.png and b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[mobile] default props with no data.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with data.png b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with data.png index b3a9bc5d8..184503d27 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with data.png and b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with data.png differ diff --git a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with no data.png b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with no data.png index bbbd2da3d..cc380fbd2 100644 Binary files a/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with no data.png and b/packages/visual-editor/src/components/testing/screenshots/HeroSection/[tablet] default props with no data.png differ diff --git a/packages/visual-editor/src/docs/ai/components.d.ts b/packages/visual-editor/src/docs/ai/components.d.ts index cfc4ff4b0..8a6aa0c19 100644 --- a/packages/visual-editor/src/docs/ai/components.d.ts +++ b/packages/visual-editor/src/docs/ai/components.d.ts @@ -1,8 +1,8 @@ import { - Config, Data, DefaultComponentProps, DefaultRootProps, + Config, Field, ComponentConfig, CustomField, diff --git a/packages/visual-editor/src/editor/Editor.tsx b/packages/visual-editor/src/editor/Editor.tsx index 2812915bd..896b3a33a 100644 --- a/packages/visual-editor/src/editor/Editor.tsx +++ b/packages/visual-editor/src/editor/Editor.tsx @@ -3,7 +3,7 @@ import React, { ErrorInfo, useEffect, useState } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { LoadingScreen } from "../internal/puck/components/LoadingScreen.tsx"; import { Toaster } from "../internal/puck/ui/Toaster.tsx"; -import { type Config } from "@puckeditor/core"; +import { type Config, type Data } from "@puckeditor/core"; import { useEntityFields } from "../hooks/useEntityFields.tsx"; import { DevLogger } from "../utils/devLogger.ts"; import { ThemeConfig } from "../utils/themeResolver.ts"; @@ -32,6 +32,13 @@ import { import { migrate } from "../utils/migrate.ts"; import { migrationRegistry } from "../components/migrations/migrationRegistry.ts"; import { ErrorProvider } from "../contexts/ErrorContext.tsx"; +import { processTemplateLayoutData } from "../utils/i18n/defaultLayoutTranslations.ts"; +import { + getLoadedComponentTranslations, + loadComponentTranslationsForLocales, +} from "../utils/i18n/components.ts"; +import { useComponentTranslationsVersion } from "../utils/i18n/useComponentTranslationsVersion.ts"; +import { getPageSetLocales } from "../utils/pageSetLocales.ts"; const devLogger = new DevLogger(); @@ -202,20 +209,79 @@ export const Editor = ({ if (themeConfig === defaultThemeConfig && templateMetadata?.customFonts) { finalThemeConfig = createDefaultThemeConfig(templateMetadata?.customFonts); } - const migratedData = !isLoading - ? migrate(layoutData!, migrationRegistry, puckConfig, document) - : undefined; + + const [processedLayoutData, setProcessedLayoutData] = useState(); + const templateId = templateMetadata?.templateId ?? ""; + const componentTranslationsVersion = useComponentTranslationsVersion(); + + useEffect(() => { + if (isLoading || !layoutData || !puckConfig || !templateId) { + setProcessedLayoutData(undefined); + return; + } + + let isCurrent = true; + + const processLayoutData = async () => { + try { + const scopedLocales = getPageSetLocales(document); + await loadComponentTranslationsForLocales(scopedLocales); + + const resolvedLayoutData = await processTemplateLayoutData({ + layoutData, + processedLayout: migrate( + layoutData, + migrationRegistry, + puckConfig, + document + ), + templateId, + targets: scopedLocales.map((locale) => ({ + locale, + translations: getLoadedComponentTranslations(locale), + })), + }); + + if (!isCurrent) { + return; + } + + setProcessedLayoutData(resolvedLayoutData); + } catch (error) { + console.error("Failed to process template layout data:", error); + if (isCurrent) { + setProcessedLayoutData(undefined); + } + } + }; + + processLayoutData(); + + return () => { + isCurrent = false; + }; + }, [ + componentTranslationsVersion, + document?.locale, + document?._pageset, + isLoading, + layoutData, + puckConfig, + templateId, + ]); + + const editorReady = !isLoading && !processedLayoutData; return ( } onError={logError}> - {!isLoading ? ( + {editorReady ? ( templateMetadata?.isThemeMode || forceThemeMode ? ( (0); const { i18n } = usePlatformTranslation(); const streamDocument = useDocument(); + const scopedLocales = React.useMemo( + () => getPageSetLocales(streamDocument), + [streamDocument] + ); const { errorCount, errorSources, errorDetails } = useErrorContext(); + const componentTranslationsVersion = useComponentTranslationsVersion(); /** * When the Puck history changes save it to localStorage and send a message @@ -234,7 +244,7 @@ export const InternalLayoutEditor = ({ render: () => <>, }; - return { + const translatedConfig: Config = { categories: puckConfig.categories, components: translatedComponents, root: { @@ -267,7 +277,17 @@ export const InternalLayoutEditor = ({ }, }, } as Config; - }, [puckConfig, i18n.language]); + + for (const locale of scopedLocales) { + localizeConfigDefaultsForLocale( + translatedConfig, + locale, + getLoadedComponentTranslations(locale) + ); + } + + return translatedConfig; + }, [componentTranslationsVersion, scopedLocales, puckConfig, i18n.language]); // Resolve all data and slots when the document changes // Implemented as an override so that the getPuck hook is available @@ -283,25 +303,44 @@ export const InternalLayoutEditor = ({ const resolvedData = await resolveAllData(appState.data, config, { streamDocument, }); + const localeAwareData = await processTemplateLayoutData({ + layoutData: appState.data, + processedLayout: resolvedData, + templateId: templateMetadata.templateId ?? "", + targets: scopedLocales.map((locale) => ({ + locale, + translations: getLoadedComponentTranslations(locale), + })), + }); - devLogger.logData("RESOLVED_LAYOUT_DATA", resolvedData); + devLogger.logData("RESOLVED_LAYOUT_DATA", localeAwareData); - if (isDeepEqual(appState.data, resolvedData)) { + if (isDeepEqual(appState.data, localeAwareData)) { devLogger.log( "reloadDataOnDocumentChange - no layout changes detected" ); return; } - dispatch({ type: "setData", data: resolvedData }); + dispatch({ type: "setData", data: localeAwareData }); }; resolveData(); - }, [streamDocument]); + }, [ + componentTranslationsVersion, + scopedLocales, + streamDocument, + templateMetadata.templateId, + ]); return <>{props.children}; }, - [streamDocument] + [ + componentTranslationsVersion, + scopedLocales, + streamDocument, + templateMetadata.templateId, + ] ); const puckOverride = React.useCallback( diff --git a/packages/visual-editor/src/internal/puck/constant-value-fields/EnhancedCallToAction.tsx b/packages/visual-editor/src/internal/puck/constant-value-fields/EnhancedCallToAction.tsx index 85263c1aa..3b3399839 100644 --- a/packages/visual-editor/src/internal/puck/constant-value-fields/EnhancedCallToAction.tsx +++ b/packages/visual-editor/src/internal/puck/constant-value-fields/EnhancedCallToAction.tsx @@ -8,6 +8,7 @@ import { TranslatableStringField } from "../../../editor/TranslatableStringField import { linkTypeOptions } from "./CallToAction.tsx"; import { useMemo } from "react"; import { YextEntityField } from "../../../editor/YextEntityFieldSelector.tsx"; +import { defaultText } from "../../../utils/i18n/defaultContent.ts"; export const ctaTypeOptions = () => { return [ @@ -81,17 +82,18 @@ export const ENHANCED_CTA_CONSTANT_CONFIG: CustomField const updatedValue = { ...value, ctaType: newValue }; // Set defaults based on CTA type if (newValue === "presetImage") { - updatedValue.label = { en: "", hasLocalizedValue: "true" }; + updatedValue.label = ""; } else if (newValue === "getDirections") { - updatedValue.label = updatedValue?.label || { - en: "Get Directions", - hasLocalizedValue: "true", - }; + updatedValue.label = + updatedValue?.label || + defaultText( + "componentDefaults.getDirections", + "Get Directions" + ); } else if (newValue === "textAndLink") { - updatedValue.label = updatedValue?.label || { - en: "Learn More", - hasLocalizedValue: "true", - }; + updatedValue.label = + updatedValue?.label || + defaultText("componentDefaults.learnMore", "Learn More"); updatedValue.link = updatedValue?.link || "#"; updatedValue.linkType = updatedValue?.linkType || "URL"; } diff --git a/packages/visual-editor/src/types/types.ts b/packages/visual-editor/src/types/types.ts index ea11ae038..d2bcdf746 100644 --- a/packages/visual-editor/src/types/types.ts +++ b/packages/visual-editor/src/types/types.ts @@ -211,7 +211,7 @@ export type PersonStruct = { }; /** Represents a translatable string. The key is the locale (en, es, fr), and the value is the localized string. */ -type LocalizedValues = { +export type LocalizedValues = { hasLocalizedValue: "true"; } & Record; diff --git a/packages/visual-editor/src/utils/i18n/componentDefaultResolver.test.ts b/packages/visual-editor/src/utils/i18n/componentDefaultResolver.test.ts new file mode 100644 index 000000000..7ab469c91 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/componentDefaultResolver.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, it } from "vitest"; +import { getDefaultRTF } from "../../editor/TranslatableRichTextField.tsx"; +import { getTranslations } from "./getTranslations.ts"; +import { + getComponentDefaultsFromTranslations, + normalizeComponentDefaultLocale, + resolveLocalizedComponentDefaultValue, +} from "./componentDefaultResolver.ts"; + +describe("componentDefaultResolver", () => { + it("normalizes and validates component default locales", () => { + expect(normalizeComponentDefaultLocale("fr-CA")).toBe("fr-CA"); + expect(normalizeComponentDefaultLocale("")).toBeUndefined(); + expect(normalizeComponentDefaultLocale("zz")).toBeUndefined(); + }); + + it("extracts flattened component defaults from translations", async () => { + const translations = await getTranslations("fr", "components"); + const defaults = getComponentDefaultsFromTranslations(translations); + expect(defaults["componentDefaults.button"]).toBe("Bouton"); + expect(defaults["componentDefaults.bannerText"]).toBe( + "Texte de la bannière" + ); + }); + + it("resolves localized text using provided component defaults", async () => { + const translations = await getTranslations("fr", "components"); + const defaults = getComponentDefaultsFromTranslations(translations); + expect(resolveLocalizedComponentDefaultValue("Button", defaults)).toBe( + "Bouton" + ); + }); + + it("resolves recognized rich text defaults", async () => { + const translations = await getTranslations("fr", "components"); + const defaults = getComponentDefaultsFromTranslations(translations); + + const localized = resolveLocalizedComponentDefaultValue( + getDefaultRTF("Banner Text"), + defaults + ); + + if (!localized || typeof localized === "string") { + throw new Error("Expected localized rich text object."); + } + + expect(localized.html).toContain("Texte de la bannière"); + expect(localized.json).toContain("Texte de la bannière"); + }); + + it("returns undefined when localized defaults are missing", () => { + expect(resolveLocalizedComponentDefaultValue("Button", {})).toBeUndefined(); + }); + + it("skips rich text defaults with unsupported html shape", async () => { + const translations = await getTranslations("fr", "components"); + const defaults = getComponentDefaultsFromTranslations(translations); + + expect( + resolveLocalizedComponentDefaultValue( + { + html: "

Banner Text

", + json: "{}", + }, + defaults + ) + ).toBeUndefined(); + }); +}); diff --git a/packages/visual-editor/src/utils/i18n/componentDefaultResolver.ts b/packages/visual-editor/src/utils/i18n/componentDefaultResolver.ts new file mode 100644 index 000000000..5ea5a0164 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/componentDefaultResolver.ts @@ -0,0 +1,171 @@ +import type { RichText } from "../../types/types.ts"; +import { getDefaultRTF } from "../../editor/TranslatableRichTextField.tsx"; +import { normalizeLocale } from "../normalizeLocale.ts"; +import { resolveTranslationLocale } from "./resolveTranslationLocale.ts"; +import { isRichText } from "../plainText.ts"; +import { locales as supportedLocales } from "./locales.ts"; +import componentDefaultsEnTranslations from "../../../locales/components/en/visual-editor.json" with { type: "json" }; +import { FlatTranslations, isJsonObject, JsonObject } from "./jsonUtils.ts"; + +const KNOWN_DEFAULT_RICH_TEXT_REGEX = /(.*?)<\/span>/i; +const COMPONENT_DEFAULTS_NAMESPACE = "componentDefaults"; +const supportedTranslationLocales = new Set(supportedLocales); + +// Flattens nested objects into dot-delimited keys, including only string leaf values. +// Based on packages/visual-editor/src/utils/i18n/jsonUtils.ts flatten function. +const flattenStringLeafNodes = ( + obj: JsonObject, + prefix = "" +): FlatTranslations => { + const result: FlatTranslations = {}; + + for (const key of Object.keys(obj)) { + const value = obj[key]; + const fullKey = prefix ? `${prefix}.${key}` : key; + + if (isJsonObject(value)) { + Object.assign(result, flattenStringLeafNodes(value, fullKey)); + continue; + } + + if (typeof value === "string") { + result[fullKey] = value; + } + } + + return result; +}; + +/** + * Extracts and flattens `componentDefaults` values from a translation payload. + */ +export const getComponentDefaultsFromTranslations = ( + translations: JsonObject | undefined +): FlatTranslations => { + if (!isJsonObject(translations)) { + return {}; + } + + const namespaceValue = translations[COMPONENT_DEFAULTS_NAMESPACE]; + if (!isJsonObject(namespaceValue)) { + return {}; + } + + return flattenStringLeafNodes(namespaceValue, COMPONENT_DEFAULTS_NAMESPACE); +}; + +const enValueToKeys = (() => { + const enDefaults = getComponentDefaultsFromTranslations( + componentDefaultsEnTranslations + ); + const index = new Map(); + + for (const [key, value] of Object.entries(enDefaults)) { + const existingKeys = index.get(value) ?? []; + existingKeys.push(key); + index.set(value, existingKeys); + } + + return index; +})(); + +/** + * Normalizes and validates a locale for component default translation lookup. + * + * Returns undefined when the input is blank, non-string, or resolves to an + * unsupported translation locale. + */ +export const normalizeComponentDefaultLocale = ( + locale: string +): string | undefined => { + const normalizedLocale = normalizeLocale(locale).trim(); + if (!normalizedLocale) { + return; + } + + const resolvedLocale = resolveTranslationLocale(normalizedLocale); + if (!supportedTranslationLocales.has(resolvedLocale)) { + return; + } + + return normalizedLocale; +}; + +/** + * Resolves a localized default string for an English source value. + * + * A single English string can map to multiple default keys; resolution is + * skipped when any key is missing in the target locale or mapped values differ. + */ +const resolveDeterministicLocalizedText = ( + enValue: string, + localizedComponentDefaults: Record +): string | undefined => { + const keys = enValueToKeys.get(enValue); + if (!keys || keys.length === 0) { + return; + } + + const values: string[] = []; + + for (const key of keys) { + const value = localizedComponentDefaults[key]; + if (value === undefined) { + return; + } + values.push(value); + } + + if (new Set(values).size !== 1) { + return; + } + + return values[0]; +}; + +/** + * Extracts text from known default rich text HTML. + * + * Only `...` wrappers are supported. + */ +const extractKnownDefaultRichTextText = ( + value: unknown +): string | undefined => { + if (!isRichText(value)) { + return; + } + + const match = value.html?.match(KNOWN_DEFAULT_RICH_TEXT_REGEX); + if (!match) { + return; + } + + return match[1]; +}; + +/** + * Resolves an injectable localized value for an English default using the + * provided locale translation payload. + */ +export const resolveLocalizedComponentDefaultValue = ( + enValue: unknown, + localizedComponentDefaults: Record +): string | RichText | undefined => { + if (typeof enValue === "string") { + return resolveDeterministicLocalizedText( + enValue, + localizedComponentDefaults + ); + } + + const enRichTextText = extractKnownDefaultRichTextText(enValue); + if (!enRichTextText) { + return; + } + + const localizedText = resolveDeterministicLocalizedText( + enRichTextText, + localizedComponentDefaults + ); + return localizedText === undefined ? undefined : getDefaultRTF(localizedText); +}; diff --git a/packages/visual-editor/src/utils/i18n/components.ts b/packages/visual-editor/src/utils/i18n/components.ts index 35f98f2c1..7d9d80faa 100644 --- a/packages/visual-editor/src/utils/i18n/components.ts +++ b/packages/visual-editor/src/utils/i18n/components.ts @@ -2,7 +2,11 @@ import i18next from "i18next"; import { initReactI18next } from "react-i18next"; import { getTranslations } from "./getTranslations.ts"; import { StreamDocument } from "../types/StreamDocument.ts"; -import { normalizeLocalesInObject } from "../normalizeLocale.ts"; +import { + normalizeLocale, + normalizeLocalesInObject, +} from "../normalizeLocale.ts"; +import { normalizeLocales } from "../pageSetLocales.ts"; const NAMESPACE = "visual-editor"; @@ -69,3 +73,40 @@ export const loadComponentTranslations = async ( ); } }; + +/** + * Loads component translations for multiple locales. + * + * Locales are normalized and de-duplicated before loading. + */ +export const loadComponentTranslationsForLocales = async ( + locales: string[], + translationsByLocale?: Record> +): Promise => { + const normalizedLocales = Array.from( + new Set(normalizeLocales(locales).map((locale) => normalizeLocale(locale))) + ); + + if (normalizedLocales.length === 0) { + return; + } + + await Promise.all( + normalizedLocales.map((locale) => + loadComponentTranslations(locale, translationsByLocale?.[locale]) + ) + ); +}; + +/** + * Returns component translations currently loaded into the i18n instance for a locale. + */ +export const getLoadedComponentTranslations = ( + locale: string | undefined +): any => { + if (!locale || !i18nComponentsInstance.hasResourceBundle(locale, NAMESPACE)) { + return; + } + + return i18nComponentsInstance.getResourceBundle(locale, NAMESPACE); +}; diff --git a/packages/visual-editor/src/utils/i18n/defaultContent.test.ts b/packages/visual-editor/src/utils/i18n/defaultContent.test.ts new file mode 100644 index 000000000..7b0c45c68 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/defaultContent.test.ts @@ -0,0 +1,61 @@ +import { describe, expect, it } from "vitest"; +import { defaultRichText, defaultText } from "./defaultContent.ts"; +import { TranslatableRichText, TranslatableString } from "../../types/types.ts"; + +type LocalizedStringMap = { hasLocalizedValue: "true" } & Record< + string, + string +>; + +type LocalizedRichTextMap = { + hasLocalizedValue: "true"; +} & Record; + +describe("defaultContent", () => { + it("builds a translatable string seeded only with en", () => { + const value = defaultText("componentDefaults.text", "Text"); + const localizedValue = value as Exclude & + LocalizedStringMap; + + expect(typeof value).toBe("object"); + expect(localizedValue.hasLocalizedValue).toBe("true"); + expect(localizedValue.en).toBe("Text"); + expect(localizedValue.fr).toBeUndefined(); + }); + + it("builds rich text defaults with en html", () => { + const value = defaultRichText( + "componentDefaults.bannerText", + "Banner Text" + ); + const localizedValue = value as Exclude & + LocalizedRichTextMap; + + expect(localizedValue.hasLocalizedValue).toBe("true"); + const enValue = localizedValue.en; + if (typeof enValue === "string") { + throw new Error("Expected rich text object for en value."); + } + expect(enValue.html).toContain("Banner Text"); + expect(enValue.json).toContain("Banner Text"); + expect(localizedValue.fr).toBeUndefined(); + }); + + it("preserves provided en rich text object", () => { + const boldDefault = { + html: "

Banner Text

", + json: '{"root":{}}', + }; + const value = defaultRichText("componentDefaults.bannerText", boldDefault); + const localizedValue = value as Exclude & + LocalizedRichTextMap; + const enValue = localizedValue.en; + + if (typeof enValue === "string") { + throw new Error("Expected rich text object for en value."); + } + + expect(enValue.html).toContain("Banner Text"); + expect(enValue.json).toContain('{"root":{}}'); + }); +}); diff --git a/packages/visual-editor/src/utils/i18n/defaultContent.ts b/packages/visual-editor/src/utils/i18n/defaultContent.ts new file mode 100644 index 000000000..5920047ef --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/defaultContent.ts @@ -0,0 +1,58 @@ +import { getDefaultRTF } from "../../editor/TranslatableRichTextField.tsx"; +import { + LocalizedValues, + RichText, + TranslatableRichText, + TranslatableString, +} from "../../types/types.ts"; + +/** + * Builds a translatable string seeded with an English default. + * + * Additional locales are injected later by per-locale default translation + * processing in editor/template layout pipelines. + * + * @param key - Dot-delimited key in the locale defaults registry. + * @param enDefault - English fallback when no `en` registry value exists. + */ +export const defaultText = ( + _key: string, + enDefault: string +): TranslatableString => { + const localizedDefaults: LocalizedValues = { + hasLocalizedValue: "true", + en: enDefault, + }; + + return localizedDefaults; +}; + +/** + * Builds a translatable rich text value seeded with an English default. + * + * Additional locales are injected later by per-locale default translation + * processing in editor/template layout pipelines. + * + * @param key - Dot-delimited key in the locale defaults registry. + * @param enDefault - English fallback when no `en` registry value exists. + */ +export const defaultRichText = ( + _key: string, + enDefault: string | RichText +): TranslatableRichText => { + let baseRichText: RichText; + if (typeof enDefault === "string") { + baseRichText = getDefaultRTF(enDefault); + } else { + baseRichText = enDefault; + } + const localizedDefaults: { + hasLocalizedValue: "true"; + [key: string]: RichText | "true"; + } = { + hasLocalizedValue: "true", + en: baseRichText, + }; + + return localizedDefaults as TranslatableRichText; +}; diff --git a/packages/visual-editor/src/utils/i18n/defaultLayoutTranslations.test.ts b/packages/visual-editor/src/utils/i18n/defaultLayoutTranslations.test.ts new file mode 100644 index 000000000..059e5f493 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/defaultLayoutTranslations.test.ts @@ -0,0 +1,407 @@ +import { describe, expect, it } from "vitest"; +import { defaultLayoutData } from "../../vite-plugin/defaultLayoutData.ts"; +import { processTemplateLayoutData } from "./defaultLayoutTranslations.ts"; +import { getDefaultRTF } from "../../editor/TranslatableRichTextField.tsx"; +import { getTranslations } from "./getTranslations.ts"; +import type { Data } from "@puckeditor/core"; + +type TestLayout = Record; + +const buildLayoutDataWithSkippedLocales = (locales: unknown): Data => + asData({ + root: { + props: { + skipDefaultTranslations: locales, + }, + }, + content: [], + }); + +const buildLabelLayout = ( + labelOverrides: Record = {} +): TestLayout => ({ + root: { + props: { + label: { + hasLocalizedValue: "true", + en: "Button", + ...labelOverrides, + }, + }, + }, +}); + +const asData = (value: unknown): Data => value as Data; + +const getComponentDefaultText = async ( + locale: string, + key: string +): Promise => { + const translations = (await getTranslations(locale, "components")) as Record< + string, + any + >; + return translations.componentDefaults[key]; +}; + +describe("defaultLayoutTranslations", () => { + it("seeds skipDefaultTranslations for all default layouts", () => { + const mainLayout = JSON.parse(defaultLayoutData.main); + const directoryLayout = JSON.parse(defaultLayoutData.directory); + const locatorLayout = JSON.parse(defaultLayoutData.locator); + + expect(mainLayout.root.props.skipDefaultTranslations).toEqual(["en"]); + expect(directoryLayout.root.props.skipDefaultTranslations).toEqual(["en"]); + expect(locatorLayout.root.props.skipDefaultTranslations).toEqual(["en"]); + }); + + it("does not inject when skipDefaultTranslations marker is missing", async () => { + const layoutData = asData({ root: { props: {} }, content: [] }); + const processedLayout = asData(buildLabelLayout()); + const targetTranslations = await getTranslations("fr", "components"); + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr", + targetTranslations, + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBeUndefined(); + expect((processed as TestLayout).root.props.skipDefaultTranslations).toBe( + undefined + ); + }); + + it("injects rich text locale when marker exists and target locale is valid", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData({ + root: { + props: { + body: { + hasLocalizedValue: "true", + en: getDefaultRTF("Banner Text"), + }, + }, + }, + }); + const targetTranslations = await getTranslations("fr", "components"); + + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr", + targetTranslations, + processedLayout, + }); + + const expectedText = await getComponentDefaultText("fr", "bannerText"); + const frBody = ( + (processed as TestLayout).root.props.body as Record + ).fr; + expect(frBody).toBeDefined(); + expect(frBody.html).toContain(expectedText); + expect(frBody.json).toContain(expectedText); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr"]); + }); + + it("injects regional locales using stripped-locale defaults", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData(buildLabelLayout()); + const targetTranslations = await getTranslations("fr-CA", "components"); + + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr-CA", + targetTranslations, + processedLayout, + }); + + expect((processed as TestLayout).root.props.label["fr-CA"]).toBe( + await getComponentDefaultText("fr", "button") + ); + expect((processed as TestLayout).root.props.label.fr).toBeUndefined(); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr-CA"]); + }); + + it("injects multiple locale targets in one pass", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData(buildLabelLayout()); + const frTranslations = await getTranslations("fr", "components"); + const esTranslations = await getTranslations("es", "components"); + + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targets: [ + { + locale: "fr", + translations: frTranslations as Record, + }, + { + locale: "es", + translations: esTranslations as Record, + }, + ], + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBe( + await getComponentDefaultText("fr", "button") + ); + expect((processed as TestLayout).root.props.label.es).toBe( + await getComponentDefaultText("es", "button") + ); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr", "es"]); + }); + + it("does not overwrite existing locale values in multi-target mode", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData( + buildLabelLayout({ + fr: "Custom Label", + }) + ); + const frTranslations = await getTranslations("fr", "components"); + const esTranslations = await getTranslations("es", "components"); + + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targets: [ + { + locale: "fr", + translations: frTranslations as Record, + }, + { + locale: "es", + translations: esTranslations as Record, + }, + ], + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBe("Custom Label"); + expect((processed as TestLayout).root.props.label.es).toBe( + await getComponentDefaultText("es", "button") + ); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr", "es"]); + }); + + it("de-dupes marker updates when duplicate locale targets are passed", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData(buildLabelLayout()); + const frTranslations = await getTranslations("fr", "components"); + + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targets: [ + { + locale: "fr", + translations: frTranslations as Record, + }, + { + locale: "fr", + translations: frTranslations as Record, + }, + ], + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBe( + await getComponentDefaultText("fr", "button") + ); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr"]); + }); + + it("skips injection when target locale is missing", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData({ + ...buildLabelLayout(), + root: { + props: { + ...buildLabelLayout().root.props, + skipDefaultTranslations: ["en"], + }, + }, + }); + + const targetTranslations = await getTranslations("fr", "components"); + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetTranslations, + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBeUndefined(); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en"]); + }); + + it("skips injection when target locale is unsupported", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData({ + ...buildLabelLayout(), + root: { + props: { + ...buildLabelLayout().root.props, + skipDefaultTranslations: ["en"], + }, + }, + }); + const targetTranslations = await getTranslations("fr", "components"); + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "zz", + targetTranslations, + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.zz).toBeUndefined(); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en"]); + }); + + it("skips injection when locale is already tracked in marker", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en", "fr"]); + const processedLayout = asData({ + ...buildLabelLayout(), + root: { + props: { + ...buildLabelLayout().root.props, + skipDefaultTranslations: ["en", "fr"], + }, + }, + }); + const targetTranslations = await getTranslations("fr", "components"); + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr", + targetTranslations, + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBeUndefined(); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr"]); + }); + + it("still marks locale as skipped when rich text shape is not recognized", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData({ + root: { + props: { + body: { + hasLocalizedValue: "true", + en: { + html: "

Banner Text

", + json: "{}", + }, + }, + }, + }, + }); + + const targetTranslations = await getTranslations("fr", "components"); + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr", + targetTranslations, + processedLayout, + }); + + expect( + ((processed as TestLayout).root.props.body as Record).fr + ).toBeUndefined(); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr"]); + }); + + it("supports direct processedLayout input", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData(buildLabelLayout()); + const targetTranslations = await getTranslations("fr", "components"); + const processedPromise = processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr", + targetTranslations, + processedLayout, + }); + + expect(processedPromise).toBeInstanceOf(Promise); + const processed = await processedPromise; + expect(processed).toBe(processedLayout); + expect((processed as TestLayout).root.props.label.fr).toBe( + await getComponentDefaultText("fr", "button") + ); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en", "fr"]); + }); + + it("is a no-op for unknown template ids", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData(buildLabelLayout()); + const targetTranslations = await getTranslations("fr", "components"); + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "unknown-template", + targetLocale: "fr", + targetTranslations, + processedLayout, + }); + + expect(processed).toBe(processedLayout); + expect((processed as TestLayout).root.props.label.fr).toBeUndefined(); + expect((processed as TestLayout).root.props.skipDefaultTranslations).toBe( + undefined + ); + }); + + it("skips injection when target translations are missing", async () => { + const layoutData = buildLayoutDataWithSkippedLocales(["en"]); + const processedLayout = asData({ + ...buildLabelLayout(), + root: { + props: { + ...buildLabelLayout().root.props, + skipDefaultTranslations: ["en"], + }, + }, + }); + + const processed = await processTemplateLayoutData({ + layoutData, + templateId: "main", + targetLocale: "fr", + targetTranslations: undefined, + processedLayout, + }); + + expect((processed as TestLayout).root.props.label.fr).toBeUndefined(); + expect( + (processed as TestLayout).root.props.skipDefaultTranslations + ).toEqual(["en"]); + }); +}); diff --git a/packages/visual-editor/src/utils/i18n/defaultLayoutTranslations.ts b/packages/visual-editor/src/utils/i18n/defaultLayoutTranslations.ts new file mode 100644 index 000000000..3bbb902b8 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/defaultLayoutTranslations.ts @@ -0,0 +1,157 @@ +import type { Data, DefaultComponentProps } from "@puckeditor/core"; +import { defaultLayoutData } from "../../vite-plugin/defaultLayoutData.ts"; +import { normalizeLocales } from "../pageSetLocales.ts"; +import { + getComponentDefaultsFromTranslations, + normalizeComponentDefaultLocale, +} from "./componentDefaultResolver.ts"; +import { injectMissingLocalizedValuesRecursively } from "./injectMissingLocalizedValues.ts"; +import { RootProps } from "../migrate.ts"; + +const SKIP_DEFAULT_TRANSLATIONS_KEY = "skipDefaultTranslations"; + +type SkipDefaultTranslationsState = { + hasMarker: boolean; + locales: string[]; +}; + +/** + * Reads the persisted skip marker state from layout root props. + * + * This reads `root.props.skipDefaultTranslations` and returns an object with: + * - `hasMarker`: whether the key exists at all + * - `locales`: normalized locale values currently tracked in the marker + * + */ +const getSkippedDefaultTranslationsState = ( + layout: Data +): SkipDefaultTranslationsState => { + if (!layout.root || !layout.root.props) { + return { hasMarker: false, locales: [] }; + } + + const rootProps = layout.root.props; + return { + hasMarker: Object.prototype.hasOwnProperty.call( + rootProps, + SKIP_DEFAULT_TRANSLATIONS_KEY + ), + locales: normalizeLocales(rootProps[SKIP_DEFAULT_TRANSLATIONS_KEY]), + }; +}; + +/** + * Persists `skipDefaultTranslations` onto `layout.root.props`. + * + * The marker is written only when root props exist. + */ +const writeSkippedDefaultTranslations = ( + layout: Data, + locales: string[] +) => { + if (!layout.root || !layout.root.props) { + return; + } + + layout.root.props[SKIP_DEFAULT_TRANSLATIONS_KEY] = normalizeLocales(locales); +}; + +type ProcessTemplateLayoutDataOptions< + TLayout extends Data, +> = { + layoutData: Data; + processedLayout: TLayout; + templateId: string; + targetLocale?: string; + targetTranslations?: Record; + targets?: Array<{ + locale: string; + translations?: Record; + }>; +}; + +/** + * Runs template layout processing and conditionally injects default translations + * based on the `root.props.skipDefaultTranslations` marker. + * + * @param options.layoutData - layout before migration/resolution. + * @param options.processedLayout - processed layout (for example after migration + * and resolve). + * @param options.templateId - `main`, `directory`, or `locator` + * @param options.targetLocale - locale to inject + * @param options.targetTranslations - locale translations for `targetLocale`. + * @param options.targets - optional batch locale/translation targets to inject + * in. When present, single-target options are ignored. + * + * @returns promise of processed layout with injected default translations + */ +export const processTemplateLayoutData = async < + TLayout extends Data, +>({ + layoutData, + processedLayout, + templateId, + targetLocale, + targetTranslations, + targets, +}: ProcessTemplateLayoutDataOptions): Promise => { + if (!Object.prototype.hasOwnProperty.call(defaultLayoutData, templateId)) { + return processedLayout; + } + + const { hasMarker, locales: skippedDefaultTranslations } = + getSkippedDefaultTranslationsState(layoutData); + if (!hasMarker) { + return processedLayout; + } + + const localeTargets = + targets && targets.length > 0 + ? targets + : targetLocale + ? [{ locale: targetLocale, translations: targetTranslations }] + : []; + + if (localeTargets.length === 0) { + return processedLayout; + } + + const nextSkippedLocales = [...skippedDefaultTranslations]; + let didInjectAnyLocale = false; + + for (const target of localeTargets) { + const normalizedTargetLocale = normalizeComponentDefaultLocale( + target.locale + ); + if ( + !normalizedTargetLocale || + nextSkippedLocales.includes(normalizedTargetLocale) + ) { + continue; + } + + const localizedComponentDefaults = getComponentDefaultsFromTranslations( + target.translations + ); + if (Object.keys(localizedComponentDefaults).length === 0) { + continue; + } + + injectMissingLocalizedValuesRecursively( + processedLayout, + normalizedTargetLocale, + localizedComponentDefaults + ); + + nextSkippedLocales.push(normalizedTargetLocale); + didInjectAnyLocale = true; + } + + if (!didInjectAnyLocale) { + return processedLayout; + } + + writeSkippedDefaultTranslations(processedLayout, nextSkippedLocales); + + return processedLayout; +}; diff --git a/packages/visual-editor/src/utils/i18n/getTranslations.ts b/packages/visual-editor/src/utils/i18n/getTranslations.ts index b8e13d36c..94d35a988 100644 --- a/packages/visual-editor/src/utils/i18n/getTranslations.ts +++ b/packages/visual-editor/src/utils/i18n/getTranslations.ts @@ -1,4 +1,4 @@ -const supportedRegionalLocales = ["en-GB", "zh-TW"]; +import { resolveTranslationLocale } from "./resolveTranslationLocale.ts"; /** * Dynamically imports the translation file for the given locale. @@ -12,13 +12,7 @@ export const getTranslations = async ( return {}; } - let strippedLocale = locale; - if (!supportedRegionalLocales.includes(locale)) { - strippedLocale = locale.split("-")[0]; - } - if (locale.includes("zh-Hant")) { - strippedLocale = "zh-TW"; - } + const strippedLocale = resolveTranslationLocale(locale); try { const module = await import( diff --git a/packages/visual-editor/src/utils/i18n/index.ts b/packages/visual-editor/src/utils/i18n/index.ts index ce6931d79..21cc7d387 100644 --- a/packages/visual-editor/src/utils/i18n/index.ts +++ b/packages/visual-editor/src/utils/i18n/index.ts @@ -6,3 +6,5 @@ export { pt, } from "./platform.ts"; export { getPreferredDistanceUnit, toKilometers } from "./distance.ts"; +export { defaultText, defaultRichText } from "./defaultContent.ts"; +export { processTemplateLayoutData } from "./defaultLayoutTranslations.ts"; diff --git a/packages/visual-editor/src/utils/i18n/injectMissingLocalizedValues.ts b/packages/visual-editor/src/utils/i18n/injectMissingLocalizedValues.ts new file mode 100644 index 000000000..87d05cab8 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/injectMissingLocalizedValues.ts @@ -0,0 +1,60 @@ +import type { RichText } from "../../types/types.ts"; +import { resolveLocalizedComponentDefaultValue } from "./componentDefaultResolver.ts"; +import { isJsonObject } from "./jsonUtils.ts"; + +export type LocalizedObject = { + hasLocalizedValue: "true"; + [key: string]: unknown; +}; + +const isLocalizedObject = (value: unknown): value is LocalizedObject => { + return isJsonObject(value) && value.hasLocalizedValue === "true"; +}; + +/** + * Recursively traverses a node and injects a missing locale value on + * `{ hasLocalizedValue: "true" }` objects when a deterministic default exists. + * + * This mutates the input object in place. + */ +export const injectMissingLocalizedValuesRecursively = ( + node: unknown, + locale: string, + localizedComponentDefaults: Record +): void => { + if (Array.isArray(node)) { + node.forEach((item) => + injectMissingLocalizedValuesRecursively( + item, + locale, + localizedComponentDefaults + ) + ); + return; + } + + if (!isJsonObject(node)) { + return; + } + + if (isLocalizedObject(node)) { + if (!(locale in node)) { + const localizedValue = resolveLocalizedComponentDefaultValue( + node.en, + localizedComponentDefaults + ); + if (localizedValue !== undefined) { + node[locale] = localizedValue as string | RichText; + } + } + return; + } + + for (const value of Object.values(node)) { + injectMissingLocalizedValuesRecursively( + value, + locale, + localizedComponentDefaults + ); + } +}; diff --git a/packages/visual-editor/src/utils/i18n/jsonUtils.ts b/packages/visual-editor/src/utils/i18n/jsonUtils.ts index 3cb9fd4dd..f25fff387 100644 --- a/packages/visual-editor/src/utils/i18n/jsonUtils.ts +++ b/packages/visual-editor/src/utils/i18n/jsonUtils.ts @@ -4,6 +4,10 @@ import path from "path"; export type FlatTranslations = Record; export type JsonObject = Record; +export const isJsonObject = (value: unknown): value is JsonObject => { + return typeof value === "object" && value !== null && !Array.isArray(value); +}; + /** * Loads JSON from disk. Missing files return {} by default. * Invalid JSON throws with file context. diff --git a/packages/visual-editor/src/utils/i18n/localizeConfigDefaults.test.ts b/packages/visual-editor/src/utils/i18n/localizeConfigDefaults.test.ts new file mode 100644 index 000000000..2e6874033 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/localizeConfigDefaults.test.ts @@ -0,0 +1,132 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { Config } from "@puckeditor/core"; +import { localizeConfigDefaultsForLocale } from "./localizeConfigDefaults.ts"; +import { getTranslations } from "./getTranslations.ts"; + +const buildConfig = (): Config => + ({ + components: { + Example: { + label: "Example", + fields: { + items: { + type: "array", + defaultItemProps: { + label: { + hasLocalizedValue: "true", + en: "Button", + }, + }, + }, + }, + defaultProps: { + title: { + hasLocalizedValue: "true", + en: "Button", + }, + }, + render: () => ({}) as any, + }, + }, + root: { + fields: {}, + defaultProps: { + rootTitle: { + hasLocalizedValue: "true", + en: "Button", + }, + }, + }, + }) as unknown as Config; + +describe("localizeConfigDefaultsForLocale", () => { + let frTranslations: Record; + let esTranslations: Record; + + beforeEach(async () => { + frTranslations = (await getTranslations("fr", "components")) as Record< + string, + unknown + >; + esTranslations = (await getTranslations("es", "components")) as Record< + string, + unknown + >; + }); + + it("injects missing locale values in component and root defaultProps", () => { + const config = buildConfig(); + const localized = localizeConfigDefaultsForLocale( + config, + "fr", + frTranslations + ); + + expect(localized).toBe(config); + expect((localized.components.Example.defaultProps as any).title.fr).toBe( + "Bouton" + ); + expect((localized.root?.defaultProps as any).rootTitle.fr).toBe("Bouton"); + expect((config.components.Example.defaultProps as any).title.fr).toBe( + "Bouton" + ); + }); + + it("injects missing locale values in nested field defaultItemProps", () => { + const config = buildConfig(); + const localized = localizeConfigDefaultsForLocale( + config, + "fr", + frTranslations + ); + const localizedFieldDefaults = (localized.components.Example.fields as any) + .items.defaultItemProps.label; + + expect(localizedFieldDefaults.fr).toBe("Bouton"); + expect(localizedFieldDefaults.en).toBe("Button"); + }); + + it("preserves existing locale values", () => { + const config = buildConfig(); + (config.components.Example.defaultProps as any).title.fr = "Custom Label"; + + const localized = localizeConfigDefaultsForLocale( + config, + "fr", + frTranslations + ); + + expect((localized.components.Example.defaultProps as any).title.fr).toBe( + "Custom Label" + ); + }); + + it("returns config unchanged when translations are unavailable", () => { + const config = buildConfig(); + const localized = localizeConfigDefaultsForLocale(config, "fr", undefined); + expect(localized).toBe(config); + }); + + it("supports repeated per-locale localization without overwriting", () => { + const config = buildConfig(); + const localizedFr = localizeConfigDefaultsForLocale( + config, + "fr", + frTranslations + ); + const localizedEs = localizeConfigDefaultsForLocale( + localizedFr, + "es", + esTranslations + ); + + expect((localizedEs.components.Example.defaultProps as any).title.fr).toBe( + "Bouton" + ); + expect((localizedEs.components.Example.defaultProps as any).title.es).toBe( + "Botón" + ); + expect((localizedEs.root?.defaultProps as any).rootTitle.fr).toBe("Bouton"); + expect((localizedEs.root?.defaultProps as any).rootTitle.es).toBe("Botón"); + }); +}); diff --git a/packages/visual-editor/src/utils/i18n/localizeConfigDefaults.ts b/packages/visual-editor/src/utils/i18n/localizeConfigDefaults.ts new file mode 100644 index 000000000..6fb31bc34 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/localizeConfigDefaults.ts @@ -0,0 +1,64 @@ +import { Config } from "@puckeditor/core"; +import { + getComponentDefaultsFromTranslations, + normalizeComponentDefaultLocale, +} from "./componentDefaultResolver.ts"; +import { injectMissingLocalizedValuesRecursively } from "./injectMissingLocalizedValues.ts"; +import { JsonObject } from "./jsonUtils.ts"; + +/** + * Injects localized default values into config for one locale. + * + * This mutates `config` in place. Only `defaultProps` and field definitions + * (`fields`) are localized. Existing locale values are preserved. + */ +export const localizeConfigDefaultsForLocale = ( + config: Config, + locale: string, + targetTranslations: JsonObject | undefined +): Config => { + const normalizedLocale = normalizeComponentDefaultLocale(locale); + if (!normalizedLocale) { + return config; + } + + const localizedComponentDefaults = + getComponentDefaultsFromTranslations(targetTranslations); + if (Object.keys(localizedComponentDefaults).length === 0) { + return config; + } + + for (const component of Object.values(config.components)) { + if (component.defaultProps) { + injectMissingLocalizedValuesRecursively( + component.defaultProps, + normalizedLocale, + localizedComponentDefaults + ); + } + if (component.fields) { + injectMissingLocalizedValuesRecursively( + component.fields, + normalizedLocale, + localizedComponentDefaults + ); + } + } + + if (config.root?.defaultProps) { + injectMissingLocalizedValuesRecursively( + config.root.defaultProps, + normalizedLocale, + localizedComponentDefaults + ); + } + if (config.root?.fields) { + injectMissingLocalizedValuesRecursively( + config.root.fields, + normalizedLocale, + localizedComponentDefaults + ); + } + + return config; +}; diff --git a/packages/visual-editor/src/utils/i18n/resolveTranslationLocale.test.ts b/packages/visual-editor/src/utils/i18n/resolveTranslationLocale.test.ts new file mode 100644 index 000000000..ba7bb1741 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/resolveTranslationLocale.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from "vitest"; +import { resolveTranslationLocale } from "./resolveTranslationLocale.ts"; + +describe("resolveTranslationLocale", () => { + it("preserves supported regional locales", () => { + expect(resolveTranslationLocale("en-GB")).toBe("en-GB"); + expect(resolveTranslationLocale("zh-TW")).toBe("zh-TW"); + }); + + it("maps zh-Hant locales to zh-TW", () => { + expect(resolveTranslationLocale("zh-Hant")).toBe("zh-TW"); + expect(resolveTranslationLocale("zh-Hant-HK")).toBe("zh-TW"); + }); + + it("falls back to base locale for unsupported regional locales", () => { + expect(resolveTranslationLocale("es-MX")).toBe("es"); + expect(resolveTranslationLocale("fr-CA")).toBe("fr"); + }); +}); diff --git a/packages/visual-editor/src/utils/i18n/resolveTranslationLocale.ts b/packages/visual-editor/src/utils/i18n/resolveTranslationLocale.ts new file mode 100644 index 000000000..d098561d1 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/resolveTranslationLocale.ts @@ -0,0 +1,27 @@ +const supportedRegionalLocales = new Set(["en-GB", "zh-TW"]); + +/** + * Maps an input locale to the locale folder used by translation assets. + * Examples: + * - "es-MX" => "es" + * - "en-GB" => "en-GB" + * - "zh-Hant-HK" => "zh-TW" + * + * @param locale - Input locale from platform or document context. + * @returns Locale code that maps to an existing translations directory. + */ +export const resolveTranslationLocale = (locale: string): string => { + if (!locale) { + throw new Error("Locale is required to resolve translation locale."); + } + + if (locale.startsWith("zh-Hant")) { + return "zh-TW"; + } + + if (supportedRegionalLocales.has(locale)) { + return locale; + } + + return locale.split("-")[0]; +}; diff --git a/packages/visual-editor/src/utils/i18n/useComponentTranslationsVersion.ts b/packages/visual-editor/src/utils/i18n/useComponentTranslationsVersion.ts new file mode 100644 index 000000000..0d6616fa8 --- /dev/null +++ b/packages/visual-editor/src/utils/i18n/useComponentTranslationsVersion.ts @@ -0,0 +1,30 @@ +import { useEffect, useState } from "react"; +import { i18nComponentsInstance } from "./components.ts"; + +/** + * Monotonic version that increments when component translation resources change. + * + * Consumers can use this in memo/effect dependency arrays to recompute locale- + * dependent defaults once component i18n bundles are loaded. + */ +export const useComponentTranslationsVersion = (): number => { + const [version, setVersion] = useState(0); + + useEffect(() => { + const handleTranslationsChange = () => { + setVersion((current) => current + 1); + }; + + i18nComponentsInstance.on("loaded", handleTranslationsChange); + i18nComponentsInstance.on("languageChanged", handleTranslationsChange); + i18nComponentsInstance.store?.on?.("added", handleTranslationsChange); + + return () => { + i18nComponentsInstance.off("loaded", handleTranslationsChange); + i18nComponentsInstance.off("languageChanged", handleTranslationsChange); + i18nComponentsInstance.store?.off?.("added", handleTranslationsChange); + }; + }, []); + + return version; +}; diff --git a/packages/visual-editor/src/utils/migrate.ts b/packages/visual-editor/src/utils/migrate.ts index 4e324d05d..80c934ae6 100644 --- a/packages/visual-editor/src/utils/migrate.ts +++ b/packages/visual-editor/src/utils/migrate.ts @@ -36,9 +36,12 @@ export type Migration = }; export type MigrationRegistry = Migration[]; -interface RootProps extends DefaultRootProps { +export interface RootProps extends DefaultRootProps { props?: { + // Version number to track which migrations have been applied version?: number; + // Locales for which default translations should be skipped + skipDefaultTranslations?: string[]; }; } diff --git a/packages/visual-editor/src/utils/pageSetLocales.ts b/packages/visual-editor/src/utils/pageSetLocales.ts index e7032c30c..b974a2d67 100644 --- a/packages/visual-editor/src/utils/pageSetLocales.ts +++ b/packages/visual-editor/src/utils/pageSetLocales.ts @@ -2,7 +2,7 @@ import { StreamDocument } from "./types/StreamDocument.ts"; export const DEFAULT_LOCALE = "en"; -const normalizeLocales = (locales: string[] | undefined): string[] => { +export const normalizeLocales = (locales: string[] | undefined): string[] => { if (!locales || locales.length === 0) { return []; } diff --git a/packages/visual-editor/src/utils/resolveComponentData.test.tsx b/packages/visual-editor/src/utils/resolveComponentData.test.tsx index ae7c18e45..4a4fa1226 100644 --- a/packages/visual-editor/src/utils/resolveComponentData.test.tsx +++ b/packages/visual-editor/src/utils/resolveComponentData.test.tsx @@ -274,14 +274,6 @@ describe("resolveComponentData", () => { }; expect(resolveComponentData(data, "fr", mockDocument)).toBe(""); }); - - it("handles a null value from the document gracefully", () => { - const field: YextEntityField = { - constantValue: null, - field: "c_nullField", - }; - expect(resolveComponentData(field, "en", mockDocument)).toBeNull(); - }); }); it("handles a direct string value by returning it", () => { @@ -366,4 +358,12 @@ describe("resolveComponentData plain text output", () => { }) ).toBe(""); }); + + it("handles a null value from the document gracefully", () => { + const field: YextEntityField = { + constantValue: null, + field: "c_nullField", + }; + expect(resolveComponentData(field, "en", mockDocument)).toBeNull(); + }); }); diff --git a/packages/visual-editor/src/vite-plugin/defaultLayoutData.ts b/packages/visual-editor/src/vite-plugin/defaultLayoutData.ts index 32d4edb39..9092b5aad 100644 --- a/packages/visual-editor/src/vite-plugin/defaultLayoutData.ts +++ b/packages/visual-editor/src/vite-plugin/defaultLayoutData.ts @@ -2,6 +2,7 @@ const mainDefaultLayout = { root: { props: { version: 63, + skipDefaultTranslations: ["en"], title: { field: "name", constantValue: "", @@ -44,12 +45,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", - height: 100, - width: 100, - }, + url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", + height: 100, + width: 100, }, constantValueEnabled: true, }, @@ -128,10 +126,7 @@ const mainDefaultLayout = { en: "Call to Action", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -165,10 +160,7 @@ const mainDefaultLayout = { en: "Call to Action", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -354,7 +346,7 @@ const mainDefaultLayout = { constantValue: { en: { json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Banner Text","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Banner Text

', + html: '

Banner Text

', }, hasLocalizedValue: "true", }, @@ -402,12 +394,9 @@ const mainDefaultLayout = { backgroundImage: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&width=640&height=360&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&width=640&height=360&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -505,12 +494,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&width=640&height=360&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&width=640&height=360&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -547,13 +533,10 @@ const mainDefaultLayout = { field: "", constantValue: { label: { - en: "Call To Action", - hasLocalizedValue: "true", - }, - link: { - en: "#", + en: "Call to Action", hasLocalizedValue: "true", }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -593,10 +576,7 @@ const mainDefaultLayout = { en: "Learn More", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -877,11 +857,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 100 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 100 characters

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 100 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 100 characters

', }, constantValueEnabled: true, }, @@ -910,12 +887,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -959,10 +933,7 @@ const mainDefaultLayout = { hasLocalizedValue: "true", en: "Learn More", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -1073,12 +1044,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1504548840739-580b10ae7715?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1504548840739-580b10ae7715?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -1105,7 +1073,7 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: "Product Title", + en: "Product Name", hasLocalizedValue: "true", }, constantValueEnabled: true, @@ -1127,11 +1095,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', }, constantValueEnabled: true, }, @@ -1164,10 +1129,7 @@ const mainDefaultLayout = { field: "", constantValue: { label: "Learn More", - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -1191,7 +1153,7 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: "Category, Pricing, etc", + en: "Category", hasLocalizedValue: "true", }, constantValueEnabled: true, @@ -1260,12 +1222,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -1292,7 +1251,7 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: "Product Title", + en: "Product Name", hasLocalizedValue: "true", }, constantValueEnabled: true, @@ -1314,11 +1273,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', }, constantValueEnabled: true, }, @@ -1351,10 +1307,7 @@ const mainDefaultLayout = { field: "", constantValue: { label: "Learn More", - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -1447,12 +1400,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -1479,7 +1429,7 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: "Product Title", + en: "Product Name", hasLocalizedValue: "true", }, constantValueEnabled: true, @@ -1501,11 +1451,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', }, constantValueEnabled: true, }, @@ -1538,10 +1485,7 @@ const mainDefaultLayout = { field: "", constantValue: { label: "Learn More", - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -1705,10 +1649,8 @@ const mainDefaultLayout = { data: { text: { field: "", - constantValue: { - en: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", - hasLocalizedValue: "true", - }, + constantValue: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", constantValueEnabled: true, }, }, @@ -1793,10 +1735,9 @@ const mainDefaultLayout = { data: { text: { field: "", - constantValue: { - en: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", - hasLocalizedValue: "true", - }, + constantValue: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", + constantValueEnabled: true, }, }, @@ -1881,10 +1822,8 @@ const mainDefaultLayout = { data: { text: { field: "", - constantValue: { - en: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", - hasLocalizedValue: "true", - }, + constantValue: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", constantValueEnabled: true, }, }, @@ -2024,20 +1963,14 @@ const mainDefaultLayout = { data: { question: { constantValueEnabled: true, - constantValue: { - en: "Question Lorem ipsum dolor sit amet?", - hasLocalizedValue: "true", - }, + constantValue: "Question Lorem ipsum dolor sit amet?", field: "", }, answer: { constantValueEnabled: true, constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

', }, field: "", }, @@ -2056,20 +1989,14 @@ const mainDefaultLayout = { data: { question: { constantValueEnabled: true, - constantValue: { - en: "Question Lorem ipsum dolor sit amet?", - hasLocalizedValue: "true", - }, + constantValue: "Question Lorem ipsum dolor sit amet?", field: "", }, answer: { constantValueEnabled: true, constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

', }, field: "", }, @@ -2088,20 +2015,14 @@ const mainDefaultLayout = { data: { question: { constantValueEnabled: true, - constantValue: { - en: "Question Lorem ipsum dolor sit amet?", - hasLocalizedValue: "true", - }, + constantValue: "Question Lorem ipsum dolor sit amet?", field: "", }, answer: { constantValueEnabled: true, constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

', }, field: "", }, @@ -2199,12 +2120,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://a.mktgcdn.com/p/EQRaOZG5zFlcbEHYaH16EV6WmkzV8kd6vMd73Myg4AA/196x196.jpg", - height: 80, - width: 80, - }, + url: "https://a.mktgcdn.com/p/EQRaOZG5zFlcbEHYaH16EV6WmkzV8kd6vMd73Myg4AA/196x196.jpg", + height: 80, + width: 80, }, constantValueEnabled: true, }, @@ -2339,10 +2257,7 @@ const mainDefaultLayout = { en: "Visit Profile", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -2389,12 +2304,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://a.mktgcdn.com/p/EQRaOZG5zFlcbEHYaH16EV6WmkzV8kd6vMd73Myg4AA/196x196.jpg", - height: 80, - width: 80, - }, + url: "https://a.mktgcdn.com/p/EQRaOZG5zFlcbEHYaH16EV6WmkzV8kd6vMd73Myg4AA/196x196.jpg", + height: 80, + width: 80, }, constantValueEnabled: true, }, @@ -2529,10 +2441,7 @@ const mainDefaultLayout = { en: "Visit Profile", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -2579,12 +2488,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://a.mktgcdn.com/p/EQRaOZG5zFlcbEHYaH16EV6WmkzV8kd6vMd73Myg4AA/196x196.jpg", - height: 80, - width: 80, - }, + url: "https://a.mktgcdn.com/p/EQRaOZG5zFlcbEHYaH16EV6WmkzV8kd6vMd73Myg4AA/196x196.jpg", + height: 80, + width: 80, }, constantValueEnabled: true, }, @@ -2719,10 +2625,7 @@ const mainDefaultLayout = { en: "Visit Profile", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -2847,12 +2750,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -2922,11 +2822,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters

', }, constantValueEnabled: true, }, @@ -2986,10 +2883,7 @@ const mainDefaultLayout = { en: "Read More", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -3031,12 +2925,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -3106,11 +2997,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters

', }, constantValueEnabled: true, }, @@ -3170,10 +3058,7 @@ const mainDefaultLayout = { en: "Read More", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -3215,12 +3100,9 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1504548840739-580b10ae7715?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - }, + url: "https://images.unsplash.com/photo-1504548840739-580b10ae7715?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, }, constantValueEnabled: true, }, @@ -3290,11 +3172,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo.Lorem ipsum dolor sit amet, consectetur adipiscing. Maecenas finibus placerat justo. 300 characters

', }, constantValueEnabled: true, }, @@ -3354,10 +3233,7 @@ const mainDefaultLayout = { en: "Read More", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -3565,12 +3441,12 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1504548840739-580b10ae7715?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - alternateText: "Event Image", + url: "https://images.unsplash.com/photo-1504548840739-580b10ae7715?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, + alternateText: { + en: "Event Image", + hasLocalizedValue: "true", }, }, constantValueEnabled: true, @@ -3644,11 +3520,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', }, constantValueEnabled: true, }, @@ -3687,10 +3560,7 @@ const mainDefaultLayout = { hasLocalizedValue: "true", en: "Learn More", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -3737,12 +3607,12 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - alternateText: "Event Image", + url: "https://images.unsplash.com/photo-1502252430442-aac78f397426?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, + alternateText: { + en: "Event Image", + hasLocalizedValue: "true", }, }, constantValueEnabled: true, @@ -3816,11 +3686,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', }, constantValueEnabled: true, }, @@ -3859,10 +3726,7 @@ const mainDefaultLayout = { hasLocalizedValue: "true", en: "Learn More", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -3909,12 +3773,12 @@ const mainDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", - height: 360, - width: 640, - alternateText: "Event Image", + url: "https://images.unsplash.com/photo-1755745360285-0633c972b0fd?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&height=360&width=640&fit=max", + height: 360, + width: 640, + alternateText: { + en: "Event Image", + hasLocalizedValue: "true", }, }, constantValueEnabled: true, @@ -3988,11 +3852,8 @@ const mainDefaultLayout = { text: { field: "", constantValue: { - en: { - json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', - html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', - }, - hasLocalizedValue: "true", + json: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}', + html: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

', }, constantValueEnabled: true, }, @@ -4031,10 +3892,7 @@ const mainDefaultLayout = { hasLocalizedValue: "true", en: "Learn More", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -4163,22 +4021,13 @@ const mainDefaultLayout = { image: { field: "", constantValue: { + url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", height: 100, width: 100, alternateText: { en: "Logo", hasLocalizedValue: "true", }, - hasLocalizedValue: "true", - en: { - url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", - height: 100, - width: 100, - alternateText: { - en: "Logo", - hasLocalizedValue: "true", - }, - }, }, constantValueEnabled: true, }, @@ -4235,10 +4084,7 @@ const mainDefaultLayout = { en: "Footer Link", hasLocalizedValue: "true", }, - link: { - hasLocalizedValue: "true", - en: "#", - }, + link: "#", }, { linkType: "URL", @@ -4246,10 +4092,7 @@ const mainDefaultLayout = { en: "Footer Link", hasLocalizedValue: "true", }, - link: { - hasLocalizedValue: "true", - en: "#", - }, + link: "#", }, { linkType: "URL", @@ -4257,10 +4100,7 @@ const mainDefaultLayout = { en: "Footer Link", hasLocalizedValue: "true", }, - link: { - hasLocalizedValue: "true", - en: "#", - }, + link: "#", }, { linkType: "URL", @@ -4268,10 +4108,7 @@ const mainDefaultLayout = { en: "Footer Link", hasLocalizedValue: "true", }, - link: { - hasLocalizedValue: "true", - en: "#", - }, + link: "#", }, { linkType: "URL", @@ -4279,10 +4116,7 @@ const mainDefaultLayout = { en: "Footer Link", hasLocalizedValue: "true", }, - link: { - hasLocalizedValue: "true", - en: "#", - }, + link: "#", }, ], }, @@ -4613,6 +4447,7 @@ const directoryDefaultLayout = { root: { props: { version: 63, + skipDefaultTranslations: ["en"], title: { field: "", constantValue: { en: "PLACEHOLDER", hasLocalizedValue: "true" }, @@ -4656,12 +4491,9 @@ const directoryDefaultLayout = { image: { field: "", constantValue: { - hasLocalizedValue: "true", - en: { - url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", - height: 100, - width: 100, - }, + url: "https://a.mktgcdn.com/p/wa83C1O1lvtxHI9cGqEdP2HILyUzbD0jvtzwWpOAJfE/196x196.jpg", + height: 100, + width: 100, }, constantValueEnabled: true, }, @@ -4740,10 +4572,7 @@ const directoryDefaultLayout = { en: "Call to Action", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -4777,10 +4606,7 @@ const directoryDefaultLayout = { en: "Call to Action", hasLocalizedValue: "true", }, - link: { - en: "#", - hasLocalizedValue: "true", - }, + link: "#", linkType: "URL", ctaType: "textAndLink", }, @@ -5458,6 +5284,7 @@ const locatorDefaultLayout = { root: { props: { version: 63, + skipDefaultTranslations: ["en"], title: { field: "", constantValue: { en: "Find Locations", hasLocalizedValue: "true" }, diff --git a/packages/visual-editor/src/vite-plugin/templates/directory.tsx b/packages/visual-editor/src/vite-plugin/templates/directory.tsx index 95eafde60..749ac035f 100644 --- a/packages/visual-editor/src/vite-plugin/templates/directory.tsx +++ b/packages/visual-editor/src/vite-plugin/templates/directory.tsx @@ -23,6 +23,7 @@ import { defaultThemeConfig, directoryConfig, getSchema, + processTemplateLayoutData, injectTranslations, getCanonicalUrl, resolveUrlTemplate, @@ -102,18 +103,26 @@ export const getPath: GetPath = ({ export const transformProps: TransformProps = async (props) => { const { document } = props; - + const layoutData = JSON.parse(document.__.layout); const migratedData = migrate( - JSON.parse(document.__.layout), + layoutData, migrationRegistry, directoryConfig, document ); - const resolvedPuckData = await resolveAllData(migratedData, directoryConfig, { + const translations = await injectTranslations(document); + const resolvedData = await resolveAllData(migratedData, directoryConfig, { streamDocument: document, }); + const resolvedPuckData = await processTemplateLayoutData({ + layoutData, + processedLayout: resolvedData, + templateId: "directory", + targetLocale: document.locale, + targetTranslations: translations, + }); + document.__.layout = JSON.stringify(resolvedPuckData); - const translations = await injectTranslations(document); return { ...props, document, translations }; }; diff --git a/packages/visual-editor/src/vite-plugin/templates/locator.tsx b/packages/visual-editor/src/vite-plugin/templates/locator.tsx index ba358420e..40e9c4fff 100644 --- a/packages/visual-editor/src/vite-plugin/templates/locator.tsx +++ b/packages/visual-editor/src/vite-plugin/templates/locator.tsx @@ -21,6 +21,7 @@ import { defaultThemeConfig, locatorConfig, getSchema, + processTemplateLayoutData, injectTranslations, getCanonicalUrl, migrate, @@ -103,19 +104,26 @@ export const getPath: GetPath = ({ export const transformProps: TransformProps = async (props) => { const { document } = props; - + const layoutData = JSON.parse(document.__.layout); const migratedData = migrate( - JSON.parse(document.__.layout), + layoutData, migrationRegistry, locatorConfig, document ); - const resolvedPuckData = await resolveAllData(migratedData, locatorConfig, { + const translations = await injectTranslations(document); + const resolvedData = await resolveAllData(migratedData, locatorConfig, { streamDocument: document, }); - document.__.layout = JSON.stringify(resolvedPuckData); + const resolvedPuckData = await processTemplateLayoutData({ + layoutData, + processedLayout: resolvedData, + templateId: "locator", + targetLocale: document.locale, + targetTranslations: translations, + }); - const translations = await injectTranslations(document); + document.__.layout = JSON.stringify(resolvedPuckData); return { ...props, document, translations }; }; diff --git a/packages/visual-editor/src/vite-plugin/templates/main.tsx b/packages/visual-editor/src/vite-plugin/templates/main.tsx index 1388f1257..86dd064b3 100644 --- a/packages/visual-editor/src/vite-plugin/templates/main.tsx +++ b/packages/visual-editor/src/vite-plugin/templates/main.tsx @@ -25,6 +25,7 @@ import { defaultThemeConfig, mainConfig, getSchema, + processTemplateLayoutData, injectTranslations, getCanonicalUrl, resolveUrlTemplate, @@ -105,19 +106,26 @@ export const getPath: GetPath = ({ export const transformProps: TransformProps = async (props) => { const { document } = props; - + const layoutData = JSON.parse(document.__.layout); const migratedData = migrate( - JSON.parse(document.__.layout), + layoutData, migrationRegistry, mainConfig, document ); - const resolvedPuckData = await resolveAllData(migratedData, mainConfig, { + const translations = await injectTranslations(document); + const resolvedData = await resolveAllData(migratedData, mainConfig, { streamDocument: document, }); - document.__.layout = JSON.stringify(resolvedPuckData); + const resolvedPuckData = await processTemplateLayoutData({ + layoutData, + processedLayout: resolvedData, + templateId: "main", + targetLocale: document.locale, + targetTranslations: translations, + }); - const translations = await injectTranslations(document); + document.__.layout = JSON.stringify(resolvedPuckData); return { ...props, document, translations }; };