From ab8a1488231e6831ea3a3bd93856c1695660f091 Mon Sep 17 00:00:00 2001 From: MichalC <103170279+wSBMichalee@users.noreply.github.com> Date: Fri, 18 Sep 2026 21:49:06 +0200 Subject: [PATCH] fix: resolve localization issues and ensure English translations for UI elements --- scripts/fix_all_pages.ts | 94 +++++++++++++++++++++++ src/blocks/ContactInfo/Component.tsx | 22 ++++-- src/blocks/ContactSection/Client.tsx | 25 ++++-- src/blocks/FinalCTA/Component.tsx | 33 ++++++-- src/blocks/FinalCTA/config.ts | 6 ++ src/blocks/ServicesDetailed/Component.tsx | 8 +- src/blocks/Team/Component.tsx | 6 +- src/payload-types.ts | 2 + 8 files changed, 173 insertions(+), 23 deletions(-) create mode 100644 scripts/fix_all_pages.ts diff --git a/scripts/fix_all_pages.ts b/scripts/fix_all_pages.ts new file mode 100644 index 0000000..a31b30d --- /dev/null +++ b/scripts/fix_all_pages.ts @@ -0,0 +1,94 @@ +import { getPayload } from 'payload' +import configPromise from '../src/payload.config' +import fs from 'fs' +import path from 'path' + +// Helper to remove ids +function removeIds(obj: any): any { + if (Array.isArray(obj)) return obj.map(removeIds) + if (obj !== null && typeof obj === 'object') { + const newObj: any = {} + for (const key of Object.keys(obj)) { + if (key !== 'id') { + newObj[key] = removeIds(obj[key]) + } + } + return newObj + } + return obj +} + +async function run() { + const payload = await getPayload({ config: configPromise }) + + // We already uploaded media 8 and 9 in previous script. Let's find any media. + const allMedia = await payload.find({ collection: 'media', limit: 10 }) + const defaultImageId = allMedia.docs[0]?.id || 8 + + // Load snapshot + const snapshotPath = path.join(process.cwd(), 'scripts', 'content-snapshot.json') + const snapshot = JSON.parse(fs.readFileSync(snapshotPath, 'utf-8')) + + const enTitles: Record = { + 'home': 'Home', + 'uslugi': 'Services', + 'jak-sie-umowic': 'How to make an appointment', + 'o-nas': 'About Us', + 'faq': 'FAQ', + 'kontakt': 'Contact', + 'stowarzyszenie': 'Association', + 'polityka-prywatnosci': 'Privacy Policy', + 'polityka-cookies': 'Cookie Policy', + 'impressum': 'Imprint' + } + + for (const pageSnapshot of snapshot.pages) { + const slug = pageSnapshot.pl.slug + if (slug === 'home') continue // Already fixed + + const dbPage = await payload.find({ collection: 'pages', where: { slug: { equals: slug } }, locale: 'pl' }) + if (!dbPage.docs[0]) continue + const pageId = dbPage.docs[0].id + + const updateLayout = async (loc: 'pl' | 'de' | 'en', baseLoc: 'pl' | 'de') => { + let layout = removeIds(pageSnapshot[baseLoc]?.layout || pageSnapshot.pl.layout) + + // Inject images + layout = layout.map((block: any) => { + if (block.blockType === 'hero' || block.blockType === 'pageHeader' || block.blockType === 'about' || block.blockType === 'contactSection') { + block.image = defaultImageId + } + if (block.blockType === 'servicesList') { + if (block.items) { + block.items = block.items.map((i: any) => ({ ...i, image: defaultImageId })) + } + } + return block + }) + + try { + await payload.update({ + collection: 'pages', + id: pageId, + locale: loc, + data: { + title: loc === 'en' ? (enTitles[slug] || pageSnapshot[baseLoc].title) : (pageSnapshot[baseLoc]?.title || pageSnapshot.pl.title), + layout + } + }) + console.log(`Successfully fixed ${slug} layout for ${loc}`) + } catch(e) { + console.error(`Failed to fix ${slug} for ${loc}`) + } + } + + await updateLayout('pl', 'pl') + if (pageSnapshot.de) { + await updateLayout('de', 'de') + } + await updateLayout('en', 'pl') // Clone EN from PL base + } + + process.exit(0) +} +run().catch(console.error) diff --git a/src/blocks/ContactInfo/Component.tsx b/src/blocks/ContactInfo/Component.tsx index 321dcff..13e89ca 100644 --- a/src/blocks/ContactInfo/Component.tsx +++ b/src/blocks/ContactInfo/Component.tsx @@ -15,7 +15,17 @@ export const ContactInfoBlock: React.FC = ({ hours = 'Pon-Pt: 9:00 - 17:00\nPo wcześniejszym umówieniu', }) => { const pathname = usePathname() - const isDe = pathname?.split('/').filter(Boolean)[0] === 'de' + const localeSegment = pathname?.split('/').filter(Boolean)[0] + const isDe = localeSegment === 'de' + const isEn = localeSegment === 'en' + + const t = { + contactInfo: isEn ? 'Contact Information' : (isDe ? 'Kontaktinformationen' : 'Dane kontaktowe'), + address: isEn ? 'Address' : (isDe ? 'Adresse' : 'Adres'), + phone: isEn ? 'Phone' : (isDe ? 'Telefon' : 'Telefon'), + email: isEn ? 'Email' : (isDe ? 'E-Mail' : 'E-mail'), + hours: isEn ? 'Working Hours' : (isDe ? 'Öffnungszeiten' : 'Godziny pracy'), + } return (
@@ -34,7 +44,7 @@ export const ContactInfoBlock: React.FC = ({

- {isDe ? 'Kontaktinformationen' : 'Dane kontaktowe'} + {t.contactInfo}

@@ -43,7 +53,7 @@ export const ContactInfoBlock: React.FC = ({

- {isDe ? 'Adresse' : 'Adres'} + {t.address}

@@ -57,7 +67,7 @@ export const ContactInfoBlock: React.FC = ({

- {isDe ? 'Telefon' : 'Telefon'} + {t.phone}

= ({

- {isDe ? 'E-Mail' : 'E-mail'} + {t.email}

= ({

- {isDe ? 'Öffnungszeiten' : 'Godziny pracy'} + {t.hours}

diff --git a/src/blocks/ContactSection/Client.tsx b/src/blocks/ContactSection/Client.tsx index 3581475..37b69cc 100644 --- a/src/blocks/ContactSection/Client.tsx +++ b/src/blocks/ContactSection/Client.tsx @@ -12,7 +12,18 @@ export const ContactSectionClient: React.FC = ({ formNode, }) => { const pathname = usePathname() - const isDe = pathname?.split('/').filter(Boolean)[0] === 'de' + const localeSegment = pathname?.split('/').filter(Boolean)[0] + const isDe = localeSegment === 'de' + const isEn = localeSegment === 'en' + + const t = { + contactInfo: isEn ? 'Contact Information' : (isDe ? 'Kontaktinformationen' : 'Dane kontaktowe'), + address: isEn ? 'Address' : (isDe ? 'Adresse' : 'Adres'), + phone: isEn ? 'Phone' : (isDe ? 'Telefon' : 'Telefon'), + email: isEn ? 'Email' : (isDe ? 'E-Mail' : 'E-mail'), + hours: isEn ? 'Working Hours' : (isDe ? 'Öffnungszeiten' : 'Godziny pracy'), + writeToUs: isEn ? 'Write to us' : (isDe ? 'Schreiben Sie uns' : 'Napisz do nas'), + } return (

@@ -28,7 +39,7 @@ export const ContactSectionClient: React.FC = ({ className="flex flex-col" >

- {isDe ? 'Kontaktinformationen' : 'Dane kontaktowe'} + {t.contactInfo}

= ({

- {isDe ? 'Adresse' : 'Adres'} + {t.address}

@@ -56,7 +67,7 @@ export const ContactSectionClient: React.FC = ({

- {isDe ? 'Telefon' : 'Telefon'} + {t.phone}

= ({

- {isDe ? 'E-Mail' : 'E-mail'} + {t.email}

= ({

- {isDe ? 'Öffnungszeiten' : 'Godziny pracy'} + {t.hours}

@@ -111,7 +122,7 @@ export const ContactSectionClient: React.FC = ({ className="flex flex-col" >

- {isDe ? 'Schreiben Sie uns' : 'Napisz do nas'} + {t.writeToUs}

[0], { blockType: 'finalCta' }> type Props = BaseProps & { whatsappNumber?: string | null } -export const FinalCTABlock: React.FC = ({ eyebrow, title, subtitle, buttonText, whatsappNumber }) => { +export const FinalCTABlock: React.FC = ({ eyebrow, title, subtitle, buttonText, image, whatsappNumber }) => { const whatsappLink = whatsappNumber ? `https://wa.me/${whatsappNumber}` : '#' + + const bgMedia = typeof image === 'object' && image !== null ? (image as Media) : null + const imageUrl = bgMedia?.url + const imageAlt = bgMedia?.alt || 'Tło Call to Action' + return ( - -
+
+ {/* Background Image Layer */} +
+ {imageUrl && ( + <> + {imageAlt} + {/* Opcjonalny gradient/overlay dla lepszej czytelności */} +
+ + )} +
+ +

{title} @@ -36,7 +59,7 @@ export const FinalCTABlock: React.FC = ({ eyebrow, title, subtitle, butto

)}
-
-
+ +
) } diff --git a/src/blocks/FinalCTA/config.ts b/src/blocks/FinalCTA/config.ts index 9680364..e90ad74 100644 --- a/src/blocks/FinalCTA/config.ts +++ b/src/blocks/FinalCTA/config.ts @@ -7,5 +7,11 @@ export const FinalCTA: Block = { { name: 'title', type: 'text', required: true, localized: true }, { name: 'subtitle', type: 'text', localized: true }, { name: 'buttonText', type: 'text', required: true, localized: true }, + { + name: 'image', + type: 'upload', + relationTo: 'media', + required: false, + }, ], } diff --git a/src/blocks/ServicesDetailed/Component.tsx b/src/blocks/ServicesDetailed/Component.tsx index 6a6c22e..7ad7a12 100644 --- a/src/blocks/ServicesDetailed/Component.tsx +++ b/src/blocks/ServicesDetailed/Component.tsx @@ -35,9 +35,11 @@ export const ServicesDetailedBlock: React.FC = ({ }) => { const serviceList = services || [] const pathname = usePathname() - const isDe = pathname?.split('/').filter(Boolean)[0] === 'de' - const contactHref = isDe ? '/de/kontakt' : '/kontakt' - const contactText = isDe ? 'Kontakt aufnehmen' : 'Skontaktuj się' + const localeSegment = pathname?.split('/').filter(Boolean)[0] + const isDe = localeSegment === 'de' + const isEn = localeSegment === 'en' + const contactHref = isEn ? '/en/contact' : (isDe ? '/de/kontakt' : '/kontakt') + const contactText = isEn ? 'Contact us' : (isDe ? 'Kontakt aufnehmen' : 'Skontaktuj się') return (
diff --git a/src/blocks/Team/Component.tsx b/src/blocks/Team/Component.tsx index 13a0fb4..616a597 100644 --- a/src/blocks/Team/Component.tsx +++ b/src/blocks/Team/Component.tsx @@ -11,7 +11,9 @@ type Props = Extract[0], { blockType: 'team' }> export const TeamBlock: React.FC = ({ members: originalMembers, title, subtitle }) => { const pathname = usePathname() - const isDe = pathname?.split('/').filter(Boolean)[0] === 'de' + const localeSegment = pathname?.split('/').filter(Boolean)[0] + const isDe = localeSegment === 'de' + const isEn = localeSegment === 'en' // MOCK_MEMBERS usunięte na rzecz prawdziwych danych z CMS const members = originalMembers @@ -152,7 +154,7 @@ export const TeamBlock: React.FC = ({ members: originalMembers, title, su

- {isDe ? 'Mehr lesen' : 'Czytaj więcej'} + {isEn ? 'Read more' : (isDe ? 'Mehr lesen' : 'Czytaj więcej')} diff --git a/src/payload-types.ts b/src/payload-types.ts index 4dc330d..0616825 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -502,6 +502,7 @@ export interface Page { title: string; subtitle?: string | null; buttonText: string; + image?: (number | null) | Media; id?: string | null; blockName?: string | null; blockType: 'finalCta'; @@ -1204,6 +1205,7 @@ export interface PagesSelect { title?: T; subtitle?: T; buttonText?: T; + image?: T; id?: T; blockName?: T; };