Skip to content

chore: swap to i18next-cli#1033

Open
mkilpatrick wants to merge 48 commits intomainfrom
i18n
Open

chore: swap to i18next-cli#1033
mkilpatrick wants to merge 48 commits intomainfrom
i18n

Conversation

@mkilpatrick
Copy link
Collaborator

@mkilpatrick mkilpatrick commented Feb 5, 2026

This swaps from i18n-scanner to i18next-cli because:

  • i18n-scanner hasn't been updated in two years and i18next-cli seems to be the preferred library
  • i18next-cli has better syncing functionality and options, which let's us simplify/remove some of the custom scripts that were previously necessary

This also removes the insertI18n script because it was clunky and not always accurate. We should add the correct translation functions manually when necessary.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

Warning: Component files have been updated but no migrations have been added. See https://github.com/yext/visual-editor/blob/main/packages/visual-editor/src/components/migrations/README.md for more information.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

⚠️ Deleted Translation Keys Detected

🔤 Deleted Translation Keys

CTA

Key Languages Removed
CTA cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

Category

Key Languages Removed
Category cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

Heading

Key Languages Removed
Heading cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

Image

Key Languages Removed
Image cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

Link

Key Languages Removed
Link cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

addressInput

Key Languages Removed
addressInput.city cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.countryCode cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.line1 cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.line2 cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.line3 cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.postalCode cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.region cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
addressInput.sublocality cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

arrayField

Key Languages Removed
arrayField cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

borderRadiusDefaultLabel

Key Languages Removed
borderRadiusDefaultLabel cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

categories

Key Languages Removed
categories.directory cs,da de
categories.locator cs,da de

category

Key Languages Removed
category cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

components

Key Languages Removed
components.DirectoryGrid cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
components.Video cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
components.enhancedCallToAction cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
components.faqs cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
components.imageButton cs,da et,fi hr,hu it,ja lt,lv nb,nl pl,pt ro,sk sv,tr zh,zh-TW
components.servicesList cs,da de

copyrightMessage

Key Languages Removed
copyrightMessage cs,da de

ctaTypes

Key Languages Removed
ctaTypes.link cs,da de

currentLocation

Key Languages Removed
currentLocation da,pl sk,sv

emailList

Key Languages Removed
emailList cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

enterSchemaMarkup

Key Languages Removed
enterSchemaMarkup cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

expandedHeaderDesktop

Key Languages Removed
expandedHeaderDesktop cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

expandedHeaderMobile

Key Languages Removed
expandedHeaderMobile cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

fields

Key Languages Removed
fields.CTAVariant cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.aspectRatioForLogo cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.breadcrumbsBackgroundColor cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.businessName cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.businessNameHeadingLevel cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.callToAction cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.cards cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.category cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.contributorName cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.coordinate cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.description cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.destinationURL cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.displayType cs,da de
fields.emailsListLength cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.eventName cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.events cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.format cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.hasLocalizedValue cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.heading cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.headingText cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.headshot cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.height cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.hero cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.hoursText cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.imageUrl cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.includeHyperlink cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.infoColumn cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.insightSection cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.level cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.localGeomodifier cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.localGeomodifierHeadingLevel cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.logo cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.logoLink cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.logoStyles cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.logoUrl cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.mainPhone cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.name cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.HoursStatus cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.HoursTable cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.base cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.bottom cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.false cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.large cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.right cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.showFullText cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.small cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.sticky zh-TW
fields.options.top cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.true cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.options.truncate cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.presetImageType cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.primaryCTAVariant cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.primaryCta cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.primaryHeader cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.primaryHeaderLinks cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.products cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryCTAVariant cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryCta cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryFooter cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryFooterLinks cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryHeader cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryHeaderLinks cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.secondaryLinks cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.servicesColumn cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.servicesList cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.siteName cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.socialLinks cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.socialMedia cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.target cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.team cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.teamSection cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.testimonialSection cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.testimonials cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.textList cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.url cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.utilityImagesStyles cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.utilityImagesWidth cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
fields.width cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

filters

Key Languages Removed
filters cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

label

Key Languages Removed
label cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

linkType

Key Languages Removed
linkType cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

loadingReviews

Key Languages Removed
loadingReviews cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

localGeomodifier

Key Languages Removed
localGeomodifier cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

logoLink

Key Languages Removed
logoLink fr

mediaType

Key Languages Removed
mediaType cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

name

Key Languages Removed
name cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

noHeroFieldsMsg

Key Languages Removed
noHeroFieldsMsg cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

noPromoFieldsMsg

Key Languages Removed
noPromoFieldsMsg cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

pageSettings

Key Languages Removed
pageSettings cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

presetImages

Key Languages Removed
presetImages.appGallery cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.appGalleryOutline cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.appStore cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.appStoreOutline cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.apple cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.arrowDown cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.arrowLeft cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.arrowRight cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.arrowUp cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.calendar cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.check cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.close cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.download cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.dribbble cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.email cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.facebook cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.figma cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.galaxyStore cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.galaxyStoreOutline cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.google cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.googlePlay cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.googlePlayOutline cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.heart cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.location cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.menu cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.minus cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.next cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.pause cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.phone cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.play cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.plus cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.previous cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.search cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.share cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.star cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.twitter cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
presetImages.uberEats cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

primaryHeader

Key Languages Removed
primaryHeader cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

professionalHero

Key Languages Removed
professionalHero cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

recentReviews

Key Languages Removed
recentReviews cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

search

Key Languages Removed
search cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

secondaryHeader

Key Languages Removed
secondaryHeader cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

showAdditionalHeaderLinks

Key Languages Removed
showAdditionalHeaderLinks cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

theme

Key Languages Removed
theme.fontWeight.black cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.bold cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.extrabold cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.extralight cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.light cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.medium cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.normal cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.semibold cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.fontWeight.thin cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.radius.pill cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW
theme.radius.pill_shape cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

title

Key Languages Removed
title cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

video

Key Languages Removed
video cs,da de,en en-GB,es et,fi fr,hr hu,it ja,lt lv,nb nl,pl pt,ro sk,sv tr,zh zh-TW

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR migrates the visual-editor's internationalization infrastructure from i18next-scanner to i18next-cli. The refactoring includes new configuration files for platform and components translation extraction, updated locale JSON files across 20+ languages with reorganized key structures (adding accessibility labels, new sections, and removing deprecated preset images), removal of legacy i18n automation scripts, and updates to component code to align with the new translation key naming conventions. The package.json is updated to reflect the new tooling dependencies, and utility scripts are added to propagate translations between platform and components locales and validate interpolation variables.

Suggested labels

create-dev-release

Suggested reviewers

  • asanehisa
  • benlife5
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (72 files):

⚔️ .github/workflows/check-i18n.yml (content)
⚔️ packages/visual-editor/THIRD-PARTY-NOTICES (content)
⚔️ packages/visual-editor/locales/components/cs/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/da/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/de/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/en-GB/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/en/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/es/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/et/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/fi/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/fr/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/hr/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/hu/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/it/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/ja/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/lt/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/lv/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/nb/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/nl/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/pl/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/pt/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/ro/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/sk/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/sv/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/tr/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/zh-TW/visual-editor.json (content)
⚔️ packages/visual-editor/locales/components/zh/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/cs/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/da/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/de/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/en-GB/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/en/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/es/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/et/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/fi/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/fr/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/hr/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/hu/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/it/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/ja/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/lt/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/lv/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/nb/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/nl/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/pl/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/pt/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/ro/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/sk/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/sv/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/tr/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/zh-TW/visual-editor.json (content)
⚔️ packages/visual-editor/locales/platform/zh/visual-editor.json (content)
⚔️ packages/visual-editor/package.json (content)
⚔️ packages/visual-editor/scripts/generateTranslations.ts (content)
⚔️ packages/visual-editor/src/components/CustomCodeSection.tsx (content)
⚔️ packages/visual-editor/src/components/Locator.tsx (content)
⚔️ packages/visual-editor/src/components/LocatorResultCard.tsx (content)
⚔️ packages/visual-editor/src/components/atoms/cta.tsx (content)
⚔️ packages/visual-editor/src/components/base/buttons/AppGalleryButton.tsx (content)
⚔️ packages/visual-editor/src/components/base/buttons/AppStoreButton.tsx (content)
⚔️ packages/visual-editor/src/components/base/buttons/GalaxyStoreButton.tsx (content)
⚔️ packages/visual-editor/src/components/base/buttons/GooglePlayButton.tsx (content)
⚔️ packages/visual-editor/src/components/base/buttons/GooglePlayWhiteButton.tsx (content)
⚔️ packages/visual-editor/src/components/contentBlocks/CTAGroup.tsx (content)
⚔️ packages/visual-editor/src/components/contentBlocks/HeadingText.tsx (content)
⚔️ packages/visual-editor/src/components/contentBlocks/Video.tsx (content)
⚔️ packages/visual-editor/src/components/directory/DirectoryWrapper.tsx (content)
⚔️ packages/visual-editor/src/components/footer/SecondaryFooterSlot.tsx (content)
⚔️ packages/visual-editor/src/components/header/HeaderLinks.tsx (content)
⚔️ packages/visual-editor/src/components/pageSections/AboutSection/AboutSectionDetailsColumn.tsx (content)
⚔️ packages/visual-editor/src/utils/themeConfigOptions.ts (content)
⚔️ pnpm-lock.yaml (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title 'chore: swap to i18next-cli' clearly and concisely describes the main change: replacing i18n-scanner with i18next-cli.
Description check ✅ Passed Description is directly related to the changeset, explaining the motivation and benefits of swapping from i18n-scanner to i18next-cli and removing the insertI18n script.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch i18n

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/visual-editor/locales/components/sv/visual-editor.json (1)

25-37: ⚠️ Potential issue | 🟡 Minor

Polish Swedish translations for new section labels.

Lines 25–37 and 62–75 include a few literal/awkward strings (or English) that read unnaturally in Swedish UI. Consider updating for consistency with common terminology.

✏️ Example adjustments (confirm with localization)
-  "coreInfoSection": "Kärninfo -sektionen",
+  "coreInfoSection": "Kärninfo-sektionen",
-  "hours": "Timme",
-  "hoursSection": "Timmarssektion",
+  "hours": "Öppettider",
+  "hoursSection": "Öppettidsavsnitt",
-  "promoMedia": "Promo media",
+  "promoMedia": "Kampanjmedia",
-  "servicesSection": "Serviceavdelning",
+  "servicesSection": "Tjänsteavsnitt",

Also applies to: 62-75

packages/visual-editor/locales/platform/ja/visual-editor.json (1)

28-28: ⚠️ Potential issue | 🟡 Minor

“パン塊” is an incorrect breadcrumb term.

For breadcrumb navigation, “パンくず” or “パンくずリスト” is the standard UI term.

✍️ Suggested wording
-  "breadcrumb": "パン塊",
+  "breadcrumb": "パンくず",
packages/visual-editor/locales/platform/nb/visual-editor.json (1)

141-141: ⚠️ Potential issue | 🟡 Minor

Incorrect Norwegian translation for "Default".

The translation "Misligholde" is used for "Default" in multiple places, but this Norwegian word means "to default on a payment" or "to neglect/fail an obligation" — not a default/fallback option in a UI context. The correct translation for a default setting should be "Standard".

Affected locations:

  • Line 141: "default": "Misligholde"
  • Line 275: "default": "Misligholde"
  • Line 448: "fontSizeDefaultLabel": "Misligholde"
  • Line 566: "spacingDefaultLabel": "Misligholde"
🌍 Proposed fix for translation accuracy
-  "default": "Misligholde",
+  "default": "Standard",
-        "default": "Misligholde",
+        "default": "Standard",
-  "fontSizeDefaultLabel": "Misligholde",
+  "fontSizeDefaultLabel": "Standard",
-  "spacingDefaultLabel": "Misligholde",
+  "spacingDefaultLabel": "Standard",

Also applies to: 275-275, 448-448, 566-566

packages/visual-editor/locales/platform/fr/visual-editor.json (1)

83-85: ⚠️ Potential issue | 🟡 Minor

Same interpolation issue: {{numéro}} should likely be {{number}}.

This is the same issue as in the components French locale. The interpolation variable {{numéro}} should match the code's parameter name, which is likely number.

Proposed fix
     "footerUtilityImagesSlot": {
-      "defaultAlt": "Image utilitaire {{numéro}}"
+      "defaultAlt": "Image utilitaire {{number}}"
     },
🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/components/ja/visual-editor.json`:
- Line 46: The translation key locationsWithinDistanceOf_one uses non-matching
placeholders {{距離}} and {{ユニット}} which i18next won't interpolate and differ from
the _other variant; update the string for locationsWithinDistanceOf_one to use
the same interpolation tokens as the plural form (e.g., {{distance}} and
{{unit}}) and mirror the structure of locationsWithinDistanceOf_other so both
singular and plural keys interpolate consistently.

In `@packages/visual-editor/locales/components/pt/visual-editor.json`:
- Around line 20-24: The Portuguese and French translations use locale-specific
placeholder names ({{número}} / {{numéro}}) but the app passes the interpolation
key "number"; update the translation key
components.footerUtilityImagesSlot.defaultAlt (and the equivalent French key) to
use the placeholder {{number}} so the runtime interpolation receives the correct
variable name.

In `@packages/visual-editor/locales/components/ro/visual-editor.json`:
- Line 9: The "breadcrumb" translation value in the locales JSON is incorrect
("Pescăruș" = seagull); update the value for the "breadcrumb" key in
packages/visual-editor/locales/components/ro/visual-editor.json to a correct
Romanian term such as "Traseu de navigare", "Navigare" or leave as "Breadcrumb"
(choose the preferred term used elsewhere for consistency) so the UI label
correctly reflects the navigation breadcrumb element.

In `@packages/visual-editor/locales/platform/ja/visual-editor.json`:
- Line 481: The translation key locationsWithinDistanceOf_one uses non-matching
placeholder names {{距離}} and {{ユニット}} which i18next won't replace; update the
value for locationsWithinDistanceOf_one to use the same interpolation
placeholders as locationsWithinDistanceOf_other (e.g., {{distance}} and
{{unit}}) and preserve spacing/order and plural form so interpolation works
consistently across both keys.

In `@packages/visual-editor/package.json`:
- Line 85: The package.json dependency for i18next-cli is invalid (currently
"^1.42.0"); confirm whether version 1.42.0 exists in the npm registry and if not
update the i18next-cli entry to a valid published version (e.g., "^1.36.1") or
pin to the exact published release; edit the "i18next-cli" dependency in
package.json (alongside the existing "i18next" entry) to a registry-valid semver
and run npm/yarn install to verify resolution.

In `@packages/visual-editor/scripts/propagatePlatformToComponents.mjs`:
- Around line 10-16: The loadJsonSafe function currently swallows all errors and
returns {} for any failure; change loadJsonSafe to only treat missing files as
empty by catching the fs.readFile/JSON.parse error, checking the error code
(e.g., err.code === 'ENOENT') and returning {} only for that case, and
rethrowing (or propagate) any other errors so malformed JSON or read-permission
issues surface; update references to loadJsonSafe accordingly so callers still
get the parsed object when successful.
🟡 Minor comments (35)
packages/visual-editor/locales/platform/hu/visual-editor.json-244-244 (1)

244-244: ⚠️ Potential issue | 🟡 Minor

Localize the new linkTarget label.

This value is still English in the Hungarian file.

📝 Suggested translation
-    "linkTarget": "Link Target",
+    "linkTarget": "Hivatkozás célja",
packages/visual-editor/locales/components/pl/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Typo in translation value: "Breatcrumb" should be a proper Polish translation.

The value "Breatcrumb" appears to be a typo of the English word "Breadcrumb" rather than an actual Polish translation. This should be translated to Polish, e.g., "Ścieżka nawigacji" (navigation path) or "Nawigacja okruszkowa" (breadcrumb navigation).

🐛 Proposed fix
-  "breadcrumb": "Breatcrumb",
+  "breadcrumb": "Ścieżka nawigacji",
packages/visual-editor/locales/components/et/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Possible mistranslation: "Riivsaia" is the culinary breadcrumb.

"Riivsaia" in Estonian refers to breadcrumbs used in cooking (food item), not the navigation UI concept. For navigation breadcrumbs, consider using a term that conveys the path/trail concept, such as "Teekond" (path), "Jäljerida" (trail), or simply retaining "Breadcrumb" as a recognized UI term.

packages/visual-editor/locales/components/sv/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Fix Swedish typo for breadcrumb label.

Line 9 looks misspelled (“Brödsmum”); likely intended “Brödsmulor”.

✏️ Suggested fix
-  "breadcrumb": "Brödsmum",
+  "breadcrumb": "Brödsmulor",
packages/visual-editor/locales/components/lv/visual-editor.json-35-37 (1)

35-37: ⚠️ Potential issue | 🟡 Minor

Translation inconsistency: "hours" translated as "Laiks" (time) instead of "Stundas" (hours).

Line 35 translates "hours" as "Laiks", which means "time" in Latvian. However, line 36 correctly uses "Stundu" (genitive of "Stundas") in "hoursSection": "Stundu sadaļa". This inconsistency suggests "hours" should be "Stundas" to match the section key and accurately represent business hours.

Proposed fix
-  "hours": "Laiks",
+  "hours": "Stundas",
packages/visual-editor/locales/components/hr/visual-editor.json-35-37 (1)

35-37: ⚠️ Potential issue | 🟡 Minor

Ambiguous and potentially incorrect translations for section labels.

A few translation concerns:

  • Line 35: "Sate" uses the accusative case, which is unusual for a standalone label. Consider "Sati" (nominative) or "Radno vrijeme" (working hours).
  • Lines 36-37: Both "hoursSection" and "informationSection" translate to the identical "Odjeljak" (Section), losing semantic distinction. Consider "Odjeljak s radnim vremenom" and "Informacijski odjeljak" to preserve context.
packages/visual-editor/locales/components/hr/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Potentially incorrect translation for "breadcrumb".

"Krušnica" means "breadbox" in Croatian, not the UI navigation concept of breadcrumbs. For navigation breadcrumbs, consider using "Navigacijska staza" (navigation path) or "Breadcrumb" (borrowed term), which are more commonly understood in Croatian UI contexts.

packages/visual-editor/locales/components/sk/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Likely mistranslation: "Strúhanka" is the culinary term for breadcrumbs.

"Strúhanka" refers to bread crumbs used in cooking (for breading food). For UI navigation breadcrumbs, consider using "Navigačná cesta" (navigation path) or "Drobečková navigácia", which are more appropriate for the navigation context.

packages/visual-editor/locales/components/sk/visual-editor.json-35-37 (1)

35-37: ⚠️ Potential issue | 🟡 Minor

Potential translation inconsistencies.

A few translations may need review:

  1. Line 36: "hoursSection": "Čas" — "Čas" means "Time", but the key suggests "Hours Section". Consider "Otváracie hodiny" (Opening hours) for consistency with "hours": "Hodiny".

  2. Line 60: "phone": "Telefonovať" — This is the verb infinitive "To phone/call". If used as a noun label, "Telefón" would be more appropriate. If it's a call-to-action, "Zavolať" (Call) might work better.

  3. Lines 37, 75: Multiple keys (informationSection, servicesSection) translate to the same generic "Sekcia", which may cause ambiguity if displayed in different UI contexts.

Also applies to: 60-60

packages/visual-editor/locales/platform/hr/visual-editor.json-244-244 (1)

244-244: ⚠️ Potential issue | 🟡 Minor

Untranslated text in Croatian locale.

The value "Link Target" is English and should be translated to Croatian for consistency. Consider using "Cilj veze" or "Odredište veze".

Suggested fix
-    "linkTarget": "Link Target",
+    "linkTarget": "Cilj veze",
packages/visual-editor/locales/platform/it/visual-editor.json-483-484 (1)

483-484: ⚠️ Potential issue | 🟡 Minor

Inconsistent capitalization between singular and plural forms.

The singular form uses lowercase posizione while the plural form uses uppercase Località. For consistency, both should use the same casing (typically lowercase in Italian for common nouns in mid-sentence context).

📝 Suggested fix
-  "locationWithCount_one": "{{count}} posizione",
-  "locationWithCount_other": "{{count}} Località",
+  "locationWithCount_one": "{{count}} posizione",
+  "locationWithCount_other": "{{count}} località",
packages/visual-editor/locales/components/nb/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Fix the typo and verify new section labels are fully localized.

I see a spacing typo in coreInfoSection, and promoMedia is still in English. While you’re here, please confirm the new section labels (hours, hoursSection, informationSection, services, servicesSection) align with your Norwegian terminology.

🔧 Proposed fix for the typo
-  "coreInfoSection": "Kjerneinfo -seksjon",
+  "coreInfoSection": "Kjerneinfo-seksjon",

Also applies to: 35-37, 60-63, 74-75

packages/visual-editor/locales/components/ja/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

“パン塊” is an incorrect breadcrumb term.

For breadcrumb navigation, “パンくず” or “パンくずリスト” is the common UI wording in Japanese. Consider aligning to that.

✍️ Suggested wording
-  "breadcrumb": "パン塊",
+  "breadcrumb": "パンくず",
packages/visual-editor/locales/platform/ro/visual-editor.json-451-451 (1)

451-451: ⚠️ Potential issue | 🟡 Minor

Fix hyphen spacing in “Heading”.

There’s an extra space around the hyphen that will render awkwardly.

📝 Proposed fix
-  "Heading": "Îndreptându -se",
+  "Heading": "Îndreptându-se",
packages/visual-editor/locales/platform/tr/visual-editor.json-323-326 (1)

323-326: ⚠️ Potential issue | 🟡 Minor

Align “HoursTable” translation with existing label.

components.hoursTable uses “Saatler Tablosu”, but the option value is “Saat Tablosu”. Consider matching to avoid inconsistent UI wording.

✏️ Suggested translation tweak
-      "HoursTable": "Saat Tablosu",
+      "HoursTable": "Saatler Tablosu",
packages/visual-editor/locales/platform/tr/visual-editor.json-206-208 (1)

206-208: ⚠️ Potential issue | 🟡 Minor

Use the correct accusative form for “expand footer.”

“Altbilgi genişlet” is ungrammatical; the natural UI verb is “Altbilgiyi genişlet”.

✏️ Suggested translation tweak
-    "expandFooter": "Altbilgi genişlet",
+    "expandFooter": "Altbilgiyi genişlet",
packages/visual-editor/locales/platform/tr/visual-editor.json-479-484 (1)

479-484: ⚠️ Potential issue | 🟡 Minor

Use singular noun after numbers in Turkish.

For counted quantities, Turkish keeps the noun singular (e.g., “5 konum”, not “5 konumlar”). Also consider consistent casing between _one and _other.

✏️ Suggested translation tweak
-  "locationWithCount_one": "{{count}} Konum",
-  "locationWithCount_other": "{{count}} konumlar",
+  "locationWithCount_one": "{{count}} konum",
+  "locationWithCount_other": "{{count}} konum",
packages/visual-editor/locales/platform/tr/visual-editor.json-44-45 (1)

44-45: ⚠️ Potential issue | 🟡 Minor

Differentiate verb “close” from state “closed.”

With the new closed key, both close and closed translate to “Kapalı”. If close is a button/action, the more natural verb is “Kapat”, while “Kapalı” fits the state. Please confirm intent.

✏️ Suggested translation tweak
-  "close": "Kapalı",
+  "close": "Kapat",
   "closed": "Kapalı",
packages/visual-editor/locales/platform/cs/visual-editor.json-403-403 (1)

403-403: ⚠️ Potential issue | 🟡 Minor

Prefer the imperative form for “showCTA”.
“Zobrazit …” is infinitive; the imperative “Zobrazte …” aligns better with the Czech style guideline for action labels. Based on learnings: In Czech translations for the visual editor, prefer imperative verb forms that align with the English phrasing (e.g., use 'Naplňte nádobu' for 'Fill Container') rather than adjective+noun constructions.

✏️ Suggested update
-    "showCTA": "Zobrazit výzvu k akci",
+    "showCTA": "Zobrazte výzvu k akci",
packages/visual-editor/locales/platform/cs/visual-editor.json-451-451 (1)

451-451: ⚠️ Potential issue | 🟡 Minor

“Heading” is better translated as “Nadpis”.
“Záhlaví” maps to “Header” and can confuse with existing header labels.

✏️ Suggested update
-  "Heading": "Záhlaví",
+  "Heading": "Nadpis",
packages/visual-editor/locales/platform/cs/visual-editor.json-45-45 (1)

45-45: ⚠️ Potential issue | 🟡 Minor

Use sentence case for the “closed” status label.
Uppercase “ZAVŘENO” is inconsistent with other status strings and can read as shouting. Consider “Zavřeno” unless UI styling uppercases it.

✏️ Suggested update
-  "closed": "ZAVŘENO",
+  "closed": "Zavřeno",
packages/visual-editor/locales/components/nl/visual-editor.json-35-37 (1)

35-37: ⚠️ Potential issue | 🟡 Minor

Use compound form to match Dutch conventions and align with similar translations in this file.
"Uren sectie" (two words) is not standard Dutch spelling. The compound form "urensectie" follows Dutch rules for compound nouns and aligns with "Dienstensectie" (servicesSection) already in the file.

✏️ Proposed change
-  "hoursSection": "Uren sectie",
+  "hoursSection": "Urensectie",
packages/visual-editor/locales/components/nl/visual-editor.json-60-63 (1)

60-63: ⚠️ Potential issue | 🟡 Minor

Use idiomatic Dutch compound forms for consistency.
"Sectie Fotogalerij" should be "Fotogalerijsectie" and "Promo media" should be "Promomedia" per Dutch compound noun conventions (samenstellingen schrijf je aaneen). Note that "Promobanner" on line 62 already uses the correct compound form, establishing the pattern.

✏️ Proposed changes
-  "photoGallerySection": "Sectie Fotogalerij",
+  "photoGallerySection": "Fotogalerijsectie",
...
-  "promoMedia": "Promo media",
+  "promoMedia": "Promomedia",
packages/visual-editor/locales/platform/et/visual-editor.json-483-484 (1)

483-484: ⚠️ Potential issue | 🟡 Minor

Change locationWithCount_other from nominative plural to partitive singular.

Estonian grammar requires partitive singular after numerals greater than 1 (e.g., "kaks asukohta", "kolm asukohta"). The current nominative plural form "asukohad" is grammatically incorrect; it should be the partitive singular "asukohta".

✏️ Suggested fix
-  "locationWithCount_other": "{{count}} asukohad",
+  "locationWithCount_other": "{{count}} asukohta",
packages/visual-editor/locales/platform/sk/visual-editor.json-483-484 (1)

483-484: ⚠️ Potential issue | 🟡 Minor

Align singular/plural noun for location counts.
The singular “umiestnenie” doesn’t match the plural “lokality.” Consider “lokalita/lokality.”

Suggested wording
-  "locationWithCount_one": "{{count}} umiestnenie",
-  "locationWithCount_other": "{{count}} lokality",
+  "locationWithCount_one": "{{count}} lokalita",
+  "locationWithCount_other": "{{count}} lokality",
packages/visual-editor/locales/platform/sk/visual-editor.json-207-207 (1)

207-207: ⚠️ Potential issue | 🟡 Minor

Prefer an imperative form for the expand action.
“Rozširovať” reads like an ongoing action; UI commands elsewhere use an imperative (“Zobraziť”, “Skryť”). Consider “Rozšíriť pätu” to match “Rozšírená päta.”

Suggested wording
-    "expandFooter": "Rozširovať pätu",
+    "expandFooter": "Rozšíriť pätu",
packages/visual-editor/locales/platform/sk/visual-editor.json-451-451 (1)

451-451: ⚠️ Potential issue | 🟡 Minor

Translate “Heading” as a noun.
“Hlavný” is an adjective; for a component label, “Nadpis” is clearer.

Suggested wording
-  "Heading": "Hlavný",
+  "Heading": "Nadpis",
packages/visual-editor/locales/platform/sk/visual-editor.json-467-467 (1)

467-467: ⚠️ Potential issue | 🟡 Minor

Use a noun for “Link.”
“Prepojiť” is a verb, while nearby labels use the noun “odkaz” (e.g., “linkLabel”).

Suggested wording
-  "Link": "Prepojiť",
+  "Link": "Odkaz",
packages/visual-editor/scripts/generateTranslations.mjs-74-76 (1)

74-76: ⚠️ Potential issue | 🟡 Minor

Tighten context-marker stripping to avoid deleting legitimate bracketed text.

The current regex removes any bracketed content, which can truncate translations that legitimately include brackets. Target the specific [[context: ...]] marker instead.

🐛 Suggested fix
 function removeEmbeddedContext(text) {
-  return text.replace(/\[+.*?\]+/g, "").trim();
+  return text
+    .replace(/\s*\[\[context:.*?]]\s*/g, " ")
+    .replace(/\s{2,}/g, " ")
+    .trim();
 }
packages/visual-editor/locales/components/it/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Incorrect translation: "Pane" means "Bread", not "Breadcrumb".

The Italian translation for breadcrumb is incorrect. "Pane" literally means "Bread" in Italian. For a navigation breadcrumb, the correct translation would be "Percorso di navigazione" (navigation path) or "Briciole di pane" (literal breadcrumbs, commonly used in UI contexts).

Suggested fix
-  "breadcrumb": "Pane",
+  "breadcrumb": "Percorso di navigazione",
packages/visual-editor/locales/components/fi/visual-editor.json-37-37 (1)

37-37: ⚠️ Potential issue | 🟡 Minor

Incorrect translation: "Tiedonsiirto" means "Data transfer", not "Information Section".

The Finnish translation for informationSection is incorrect. "Tiedonsiirto" means "Data transfer" in Finnish. The correct translation for "Information Section" would be "Tiedot-osio" or "Tietoja-osio".

Suggested fix
-  "informationSection": "Tiedonsiirto",
+  "informationSection": "Tiedot-osio",
packages/visual-editor/locales/components/cs/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Incorrect translation: "Strouha" means "ditch/gutter", not "Breadcrumb".

The Czech translation for breadcrumb is incorrect. "Strouha" means "ditch" or "gutter" in Czech. For navigation breadcrumbs, the correct translation would be "Drobečková navigace" (breadcrumb navigation) or simply retain "Breadcrumb" as many Czech applications do.

Suggested fix
-  "breadcrumb": "Strouha",
+  "breadcrumb": "Drobečková navigace",
packages/visual-editor/locales/components/fr/visual-editor.json-21-23 (1)

21-23: ⚠️ Potential issue | 🟡 Minor

Interpolation variable {{numéro}} is incorrect — must be {{number}}.

The code passes number as the interpolation parameter (line 85 in FooterUtilityImagesSlot.tsx), but the French locale uses {{numéro}}. This mismatch will cause the French translation to display literally as "Image utilitaire {{numéro}}" instead of interpolating the image number. The English locale correctly uses {{number}}.

packages/visual-editor/locales/platform/zh-TW/visual-editor.json-479-484 (1)

479-484: ⚠️ Potential issue | 🟡 Minor

Align count phrasing between _one and _other.
_other currently drops the classifier, yielding “2位置”. Match the _one phrasing for consistency.

🛠️ Suggested fix
-  "locationsNear_other": "“{{name}}”附近有{{count}}位置",
+  "locationsNear_other": "“{{name}}”附近有 {{count}} 個位置",
...
-  "locationWithCount_other": "{{count}}位置",
+  "locationWithCount_other": "{{count}} 個位置",
packages/visual-editor/locales/components/zh-TW/visual-editor.json-42-47 (1)

42-47: ⚠️ Potential issue | 🟡 Minor

Fix inconsistent count wording between _one and _other.
_one uses 「個位置」 while _other drops the classifier, producing outputs like “2位置”. Align the _other strings with the _one format.

🛠️ Suggested fix
-  "locationWithCount_other": "{{count}}位置",
+  "locationWithCount_other": "{{count}} 個位置",
...
-  "locationsNear_other": "“{{name}}”附近有{{count}}位置",
+  "locationsNear_other": "“{{name}}”附近有 {{count}} 個位置",
🧹 Nitpick comments (16)
packages/visual-editor/locales/components/tr/visual-editor.json (2)

25-37: Minor capitalization inconsistency in section labels.

There's inconsistent capitalization between section translations:

  • Title case: "coreInfoSection": "Çekirdek Bilgi Bölümü", "hoursSection": "Saatler Bölümü"
  • Sentence case: "informationSection": "Bilgi bölümü"

Consider aligning to a consistent style (likely title case to match the majority).

💅 Suggested fix for consistency
-  "informationSection": "Bilgi bölümü",
+  "informationSection": "Bilgi Bölümü",

62-63: Minor capitalization inconsistency in promo labels.

Similar inconsistency here:

  • "promoBanner": "Promosyon Banner'ı" (title case)
  • "promoMedia": "Promosyon medyası" (sentence case)
💅 Suggested fix for consistency
-  "promoMedia": "Promosyon medyası",
+  "promoMedia": "Promosyon Medyası",
packages/visual-editor/src/components/Locator.tsx (1)

83-93: Pluralization fallback may produce grammatically incorrect text.

The defaultValue uses the singular form ("mile", "kilometer") regardless of count. If translation keys are missing, i18next will return the singular default even when count > 1, producing strings like "5 mile" instead of "5 miles".

Consider using a pluralized fallback or ensuring the translation keys always exist:

🔧 Proposed fix with pluralized fallback
 const translateDistanceUnit = (
   t: (key: string, options?: Record<string, unknown>) => string,
   unit: "mile" | "kilometer",
   count: number
 ) => {
   if (unit === "mile") {
-    return t("mile", { count, defaultValue: "mile" });
+    return t("mile", { count, defaultValue: count === 1 ? "mile" : "miles" });
   }
 
-  return t("kilometer", { count, defaultValue: "kilometer" });
+  return t("kilometer", { count, defaultValue: count === 1 ? "kilometer" : "kilometers" });
 };
packages/visual-editor/locales/components/lv/visual-editor.json (2)

9-9: Consider using a UI-appropriate term for "breadcrumb".

"Rīvmaize" is the literal Latvian translation for breadcrumbs (the food item). For navigation breadcrumbs in UI contexts, some locales use an adapted term or keep the English "breadcrumb" to preserve the metaphor. This might confuse users expecting a navigation-related term.

Please verify with a native Latvian speaker or the localization team whether "Rīvmaize" is the preferred UI term for navigation breadcrumbs, or if an alternative like "Navigācijas ceļš" (navigation path) would be clearer.


60-63: "promoMedia" left untranslated.

"promoMedia": "Promo Media" remains in English. If this is intentional (e.g., brand term), this is fine. Otherwise, consider translating to Latvian such as "Reklāmas mediji" for consistency with other translated keys like "promoBanner": "Reklāmas reklāmkarogs".

packages/visual-editor/locales/platform/fi/visual-editor.json (3)

131-132: Duplicate keys with different casing at root level.

Both cta and CTA exist at the same nesting level with identical values. This creates ambiguity for developers choosing which key to use, and one may become orphaned over time. If these serve distinct purposes (e.g., component name vs. field label), consider documenting the distinction or using different key paths.

The same pattern appears with link/Link at lines 466-467.


190-191: Duplicate field keys: ctaVariant vs CTAVariant.

Similar to root-level duplicates, fields.ctaVariant (line 190) and fields.CTAVariant (line 191) both exist with nearly identical translations (only whitespace differs: "CTA -variantti" vs "CTA-variantti"). Consider consolidating to a single key.


324-325: PascalCase keys in fields.options break convention.

HoursStatus and HoursTable use PascalCase while surrounding options like hour12, hour24, and image use camelCase. This suggests these may be component type identifiers extracted differently by the new tooling.

packages/visual-editor/locales/platform/hr/visual-editor.json (1)

483-484: Consider adding _few plural form for complete Croatian pluralization.

Croatian uses different plural forms: "lokacija" (1), "lokacije" (2-4), "lokacija" (5+). The current setup handles 1 and 5+ correctly, but displaying "2 lokacija" instead of "2 lokacije" would be grammatically incorrect.

If i18next is configured for Croatian plural rules, consider adding:

"locationWithCount_few": "{{count}} lokacije"
packages/visual-editor/locales/platform/lt/visual-editor.json (1)

324-325: Duplicate keys under options: HoursStatus and HoursTable.

These PascalCase keys duplicate existing keys at components.hoursStatus (line 95) and components.hoursTable (line 96) with identical translations. If intentional for different namespaces, this is acceptable; otherwise, consider referencing the existing keys.

packages/visual-editor/locales/components/hu/visual-editor.json (3)

9-9: Confirm breadcrumb term matches your HU glossary.

“Zsemlemorzsa” is very literal; if your UI standard uses “morzsamenü” (or similar), consider aligning for consistency.

🔤 Example adjustment (if this matches your glossary)
-  "breadcrumb": "Zsemlemorzsa",
+  "breadcrumb": "Morzsamenü",

35-37: Consider aligning “hours” terminology with standard business-hours wording.

If your product glossary prefers “Nyitvatartás”, these two keys might read more naturally.

🔤 Example adjustment (if this matches your glossary)
-  "hours": "Órák",
-  "hoursSection": "Órás szakasz",
+  "hours": "Nyitvatartás",
+  "hoursSection": "Nyitvatartás szakasz",

60-63: Align promo banner wording with existing “szalaghirdetés” usage.

heroBanner uses “szalaghirdetés”, so keeping promoBanner consistent may improve UX consistency.

🔤 Example adjustment
-  "promoBanner": "Promó banner",
+  "promoBanner": "Promóciós szalaghirdetés",
packages/visual-editor/scripts/generateTranslations.mjs (2)

93-115: Add request timeout to prevent hanging on stalled API calls.

The fetch call lacks a timeout and can hang indefinitely if the Google Translate API becomes unresponsive, freezing the CLI. Node 18+ (which this package supports) has global fetch available, so no polyfill is needed—only a timeout.

⏱️ Add a request timeout
 async function translateText(text, targetLang) {
   const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${defaultLng}&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}`;
-  const res = await fetch(url);
+  const controller = new AbortController();
+  const timeout = setTimeout(() => controller.abort(), 15000);
+  let res;
+  try {
+    res = await fetch(url, { signal: controller.signal });
+  } finally {
+    clearTimeout(timeout);
+  }

198-221: Batch requests to avoid triggering the unofficial endpoint's rate-limiting.

The translate.googleapis.com/translate_a/single endpoint (gtx client) is unofficial and uses dynamic rate limiting—it can return 429 errors or temporarily block your IP if too many requests arrive concurrently. Batching helps prevent hitting these thresholds.

🔧 Batch requests with a small concurrency window
-    await Promise.allSettled(
-      keysToTranslate.map(async (key) => {
+    const BATCH_SIZE = 5;
+    for (let i = 0; i < keysToTranslate.length; i += BATCH_SIZE) {
+      const batch = keysToTranslate.slice(i, i + BATCH_SIZE);
+      await Promise.allSettled(
+        batch.map(async (key) => {
           let english = defaultJson[key];
           const context = extractContextFromKey(key, defaultKeySet);
@@
-      })
-    );
+        })
+      );
+    }
packages/visual-editor/i18next-cli.platform.config.ts (1)

47-47: Platform config includes additional translation functions pt and msg.

The platform config extracts from functions ["t", "*.t", "i18next.t", "pt", "msg"] while the components config only uses ["t", "*.t", "i18next.t"]. Ensure this difference is intentional and that pt and msg are platform-specific translation helpers.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@packages/visual-editor/scripts/generateTranslations.mjs`:
- Around line 154-160: The loadJsonSafe function currently swallows all
read/parse errors by returning {}, which hides corrupted JSON; update
loadJsonSafe to catch the error into a variable, treat only ENOENT as a benign
case (return {}), but rethrow any other errors (including JSON.parse failures)
so callers can handle or fail fast; locate the async function loadJsonSafe and
change its try/catch to inspect err.code === 'ENOENT' before returning {} and
otherwise throw err.
- Around line 101-103: The removeEmbeddedContext function is too aggressive:
replace the broad regex /\[+.*?\]+/g with a marker-specific pattern so only the
translation context marker is stripped; update removeEmbeddedContext to use a
dedicated regex constant (e.g. match only "[[context...]]" or "[context:...]"
depending on project convention) such as /\[\[context:.*?\]\]/g or
/\[context:.*?\]/g and trim the result, and ensure the function references that
regex (removeEmbeddedContext) so legitimate bracketed text like "[beta]" is
preserved.
- Around line 212-280: In translateFile, currently failures only increment
failCount and still call saveJson causing partial writes; after the
Promise.allSettled completes check failCount and if > 0 prevent writing (or
abort) by skipping saveJson and logging/throwing an error so no partial
translations are persisted. Concretely: after the await Promise.allSettled(...)
block inspect failCount and if it's non‑zero and not isDryRun, log a clear error
including type/lng and either throw or continue to the next language instead of
calling saveJson; ensure the finalConsole log reflects that the file was not
saved when failures occurred.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/components/fr/visual-editor.json`:
- Line 9: Replace the incorrect French translation for the "breadcrumb" key in
the locales JSON: update the value of the "breadcrumb" property (in
packages/visual-editor/locales/components/fr/visual-editor.json) from
"Chapelure" to the standard UI term "Fil d'Ariane" so the breadcrumb navigation
label uses the correct French UX phrasing.

In `@packages/visual-editor/locales/components/ja/visual-editor.json`:
- Line 9: The "breadcrumb" translation value currently reads "パン塊" (wrong
meaning); update the JSON entry for the "breadcrumb" key in
packages/visual-editor/locales/components/ja/visual-editor.json to use the
correct Japanese UI term "パンくずリスト" (or alternatively "Breadcrumb" if you prefer
to match the Romanian style) so the label accurately represents breadcrumb
navigation.

In `@packages/visual-editor/locales/platform/ja/visual-editor.json`:
- Around line 479-484: Unify the Japanese plural forms so _one and _other are
identical: update "locationWithCount_other" to match "locationWithCount_one" by
using the more natural counter phrase "{{count}} 件の場所"; locate the two keys
"locationWithCount_one" and "locationWithCount_other" in the visual-editor.json
and replace the _other value accordingly so both read "{{count}} 件の場所".

In `@packages/visual-editor/locales/platform/ro/visual-editor.json`:
- Line 451: Replace the incorrect Romanian value for the "Heading" key
(currently "Îndreptându -se") with the correct UI term "Titlu" (or "Rubrică" to
match existing "headingLevel": "Nivel de rubrică"); also remove the spurious
space before any hyphen if present (fix the hyphenation artifact). Update the
"Heading" entry so it reads simply "Titlu" to align with "headingLevel" and
other UI label translations.
- Around line 131-132: The cta/CTA and link/Link keys are ambiguous in Romanian
and mirror each other; either give them semantically distinct translations to
match how they’re used (e.g., distinguish the UI label used by CtaWrapper.tsx's
pt("cta","CTA") from the group label used by CTAGroup.tsx's pt("CTA","CTA")), or
consolidate usage by updating the source to a single key and removing the
duplicate in the locale. Locate the keys "cta"/"CTA" and "link"/"Link" in
packages/visual-editor/locales/platform/ro/visual-editor.json and: 1) if keeping
both keys, replace the duplicate values with different, context-appropriate
Romanian strings that reflect the different UI contexts referenced by
CtaWrapper.tsx and CTAGroup.tsx; or 2) if consolidating, change the source
references (pt calls in CtaWrapper.tsx and CTAGroup.tsx) to use one canonical
key and remove the redundant locale entry.

In `@packages/visual-editor/scripts/checkInterpolationVariables.mjs`:
- Around line 306-335: The code currently calls autoFixSingleVariableMismatch
and, if it returns null for a single-variable mismatch, falls through without
reporting; update the logic around the autoFixSingleVariableMismatch call (the
block using CHECK_ONLY, autoFixSingleVariableMismatch, localeFlat, fixedEntries,
and issues) so that when details.mismatchCount > 0 and either CHECK_ONLY is true
or autoFixSingleVariableMismatch returned null (i.e., no safe fix), you push an
issue entry into the issues array with the same fields currently used (instance,
locale, file, line via findLineNumberForKey, key, expected, actual,
mismatchCount); alternatively change the later condition to check
details.mismatchCount > 0 instead of > 1 to ensure single-variable mismatches
that couldn't be fixed are reported.
🧹 Nitpick comments (8)
packages/visual-editor/locales/platform/fr/visual-editor.json (1)

68-68: Inconsistent key casing: PascalCase keys mixed with camelCase siblings.

DirectoryGrid (line 68), Video (line 124), HoursStatus (line 324), and HoursTable (line 325) use PascalCase while all surrounding keys in the same objects use camelCase (e.g., directory, videoSection, hoursStatus). If these are extracted directly from React component names, consider normalizing them to camelCase in the i18next-cli config (e.g., via a key transformation) to keep the locale files consistent.

Example normalization
-    "DirectoryGrid": "Grille de répertoire",
+    "directoryGrid": "Grille de répertoire",
...
-    "Video": "Vidéo",
+    "video": "Vidéo",
...
-      "HoursStatus": "Statut des heures",
-      "HoursTable": "Tableau des heures",
+      "hoursStatus": "Statut des heures",
+      "hoursTable": "Tableau des heures",

(Corresponding source code t() calls would need to be updated to match.)

Also applies to: 124-124, 324-325

packages/visual-editor/locales/platform/pt/visual-editor.json (1)

68-68: PascalCase keys break the prevailing camelCase convention.

DirectoryGrid (line 68), Video (line 124), HoursStatus (line 324), HoursTable (line 325), and Heading (line 451) all use PascalCase while the rest of the file is consistently camelCase. This is likely auto-extracted from React component names by i18next-cli. If so, this is expected, but worth confirming the extraction config is intentional and consistent across all locales.

Also applies to: 124-124, 324-325, 451-451

packages/visual-editor/locales/platform/et/visual-editor.json (1)

68-68: PascalCase keys mixed with camelCase siblings.

DirectoryGrid (Line 68) and Video (Line 124) within components, and HoursStatus/HoursTable (Lines 324–325) within options, break the camelCase convention used by all their sibling keys. This is likely an artifact of how the new i18next-cli extraction maps source-code identifiers to translation keys. Not a functional issue, but worth noting for consistency.

Also applies to: 124-124, 324-325

packages/visual-editor/locales/platform/ro/visual-editor.json (1)

68-68: PascalCase keys (DirectoryGrid, Video, CTAVariant, HoursStatus, HoursTable) break the camelCase convention used by the rest of this file.

The vast majority of keys in this file follow camelCase (e.g., directoryRootLinkLabel, hoursStatus, hoursTable, ctaVariant). These PascalCase additions appear to be auto-extracted component/type names. Notably, some of these duplicate existing camelCase keys in other sections (e.g., components.hoursStatus at line 95 vs options.HoursStatus at line 324).

If these keys are generated by the new i18next-cli extraction, it may be worth configuring the key naming to enforce consistent casing.

Also applies to: 124-124, 191-191, 324-325

packages/visual-editor/scripts/propagatePlatformToComponents.mjs (1)

37-49: Consider extracting shared utilities (flatten, unflatten, sortObject, loadJsonSafe) into a common module.

These functions are duplicated nearly verbatim across propagatePlatformToComponents.mjs, checkInterpolationVariables.mjs, and generateTranslations.mjs. A shared scripts/utils.mjs would reduce maintenance surface and ensure bug fixes propagate consistently (e.g., the loadJsonSafe error-handling fix in this file isn't applied in the other two scripts).

Also applies to: 54-70, 75-86

packages/visual-editor/scripts/checkInterpolationVariables.mjs (1)

289-292: Double file read: localePath is read twice — once raw and once parsed.

Line 291 reads the raw file content for line-number lookup, then line 292 reads and parses the same file again via loadJsonSafe. Consider reading once and reusing.

♻️ Proposed optimization
-    const localeRaw = await fs.readFile(localePath, "utf-8").catch(() => "");
-    const localeFlat = flatten(await loadJsonSafe(localePath));
+    let localeRaw = "";
+    let localeFlat = {};
+    try {
+      localeRaw = await fs.readFile(localePath, "utf-8");
+      localeFlat = flatten(JSON.parse(localeRaw));
+    } catch (error) {
+      if (error?.code !== "ENOENT") throw error;
+    }
packages/visual-editor/scripts/generateTranslations.mjs (2)

155-178: Relies on an unofficial, undocumented Google Translate endpoint.

translate.googleapis.com/translate_a/single?client=gtx is not a public API — it's subject to rate limiting, CAPTCHAs, and can break without notice. For a CI/development tool this may be acceptable, but be aware of the fragility.

Additionally, Promise.allSettled on line 275 fires all key translations concurrently with no concurrency limit or rate throttling, which increases the chance of hitting rate limits for locales with many missing keys.

♻️ Add basic concurrency limiting

Consider batching translations (e.g., 5 at a time) to avoid hammering the endpoint:

// Simple serial or batched approach
for (const key of keysToTranslate) {
  // translate one at a time, or use a small batch with Promise.all
}

203-215: flatten uses for...in instead of Object.keys(), inconsistent with other scripts.

for (const key in obj) iterates inherited enumerable properties, unlike Object.keys(obj) used in the other two scripts' flatten implementations. For JSON.parse output this is benign, but it's an inconsistency that could surprise if the input shape ever changes.

♻️ Align with other scripts
-  for (const key in obj) {
+  for (const key of Object.keys(obj)) {

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/visual-editor/locales/platform/sv/visual-editor.json (1)

28-28: ⚠️ Potential issue | 🟡 Minor

Fix invalid Swedish translation for breadcrumb navigation key.

"Brödsmum" is not valid Swedish. The correct translation is "Brödsmula" (singular form, matching the key name). This affects user-facing breadcrumb navigation text.

Proposed fix
-  "breadcrumb": "Brödsmula",
+  "breadcrumb": "Brödsmula",
packages/visual-editor/scripts/generateTranslations.ts (1)

180-205: ⚠️ Potential issue | 🟡 Minor

Unofficial Google Translate endpoint with no timeout or rate limiting.

  1. The client=gtx endpoint is an undocumented, unofficial Google Translate API. It can be rate-limited or blocked without notice.
  2. fetch has no AbortSignal timeout — a hung request will stall the pipeline indefinitely.

Consider adding a timeout:

Proposed timeout addition
 const translateText = async (
   text: string,
   targetLang: string
 ): Promise<string> => {
   const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${DEFAULT_LANGUAGE}&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}`;
-  const response = await fetch(url);
+  const response = await fetch(url, {
+    signal: AbortSignal.timeout(10_000),
+  });
🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/components/ja/visual-editor.json`:
- Around line 44-47: Unify the Japanese singular/plural variants so they are
identical for each key: make locationsNear_one and locationsNear_other the same
string, and make locationsWithinDistanceOf_one and
locationsWithinDistanceOf_other the same string; choose a single
particle/phrase, consistent spacing around interpolation tokens (e.g.,
"「{{name}}」付近の {{count}} か所の場所" or preferred equivalent), and use the same
counter word (件 or か所) in both forms so translators and runtime output do not
diverge when count changes.

In `@packages/visual-editor/locales/platform/cs/visual-editor.json`:
- Around line 323-324: The JSON contains duplicated keys with inconsistent
casing: "hoursTable" (components) vs "HoursTable" (fields.options) and
"hoursStatus" vs "HoursStatus"; decide whether both variants are required or
consolidate them—either make the two "hoursTable"/"HoursTable" values identical
(e.g., both "TABULKA HODINY" or both "Tabulka hodin") and do the same for
"hoursStatus"/"HoursStatus", or remove the redundant keys so only the canonical
key (prefer the existing "hoursTable" and "hoursStatus" in components) remains;
update the translations accordingly in visual-editor.json to ensure consistent
casing/values for the keys HoursTable/hoursTable and HoursStatus/hoursStatus.
- Around line 189-190: The JSON contains duplicate translation keys "ctaVariant"
and "CTAVariant" with identical values; remove the redundant key or consolidate
them depending on runtime usage: search the codebase for references to
CTAVariant and ctaVariant (case-sensitive) and if only one form is used keep
that single key (prefer the existing "ctaVariant"), otherwise keep both but
ensure translations stay synchronized and add a comment explaining why both
forms are required; update the file to remove the duplicate entry (or add the
explanatory comment) and run the provided ripgrep checks to verify no callers
break.

In `@packages/visual-editor/locales/platform/da/visual-editor.json`:
- Line 239: The Danish locale entry for the key "linkLabel" currently contains
English text ("Link Label"); update the value for "linkLabel" in the
visual-editor.json Danish file to a proper Danish translation (e.g.,
"Link-etiket" or another agreed translation) or explicitly mark it as
untranslated/TO_TRANSLATE if you want to flag it for later review; reference the
nearby key "linkTarget" to match localization style and ensure the JSON string
remains valid.

In `@packages/visual-editor/locales/platform/fi/visual-editor.json`:
- Around line 481-482: Update the Finnish pluralization strings for the location
count: change the translation value for "locationWithCount_other" from the
nominative plural to the partitive singular used after numerals, i.e., replace
the current "{{count}} sijainnit" with "{{count}} sijaintia"; ensure the keys
"locationWithCount_one" and "locationWithCount_other" remain unchanged and
consistent with nearby entries like "{{count}} sijaintia lähellä kohdetta
{{name}}".

In `@packages/visual-editor/locales/platform/fr/visual-editor.json`:
- Around line 239-244: The translation for the key "linkType" is inconsistent
("Type de liaison") with adjacent keys like "linkLabel" and "linkTarget" which
use "lien"; update the value for linkType to "Type de lien" so all three keys
(linkType, linkLabel, linkTarget) use the same terminology and ensure
consistency across the locale file.
- Line 402: The translation for the key "showCTA" is inconsistent — replace its
value "Afficher l'incitation à l'action" with the acronym form used elsewhere;
update the "showCTA" entry to use "Afficher le CTA" so it matches keys like
"cta" and "showPrimaryCTA".

In `@packages/visual-editor/locales/platform/hr/visual-editor.json`:
- Line 243: The entry for the key "linkTarget" is still in English; replace its
value with the Croatian translation to match the surrounding keys (e.g., change
"Link Target" to "Odredište veze" for the "linkTarget" key) so the locale file
remains fully translated and consistent with "linkLabel" and "linkType".

In `@packages/visual-editor/locales/platform/hu/visual-editor.json`:
- Around line 189-190: The locale file contains near-duplicate keys ctaVariant
and CTAVariant with inconsistent values (one has an extra space before the
hyphen); update them so they use the same normalized translation string (e.g.,
"CTA-változat") and consistent spacing, and if both keys are required by the
code ensure both entries have identical values, otherwise remove or consolidate
the duplicate key to the canonical identifier (ctaVariant or CTAVariant) used by
the source code.
- Line 243: Replace the English value for the JSON key "linkTarget" with the
correct Hungarian translation; locate the "linkTarget" entry in
packages/visual-editor/locales/platform/hu/visual-editor.json and change "Link
Target" to a Hungarian string such as "Hivatkozás célja" (or another approved
Hungarian translation) ensuring the file remains valid JSON and preserves
surrounding commas/formatting.

In `@packages/visual-editor/locales/platform/it/visual-editor.json`:
- Around line 481-482: The translation keys locationWithCount_one and
locationWithCount_other have inconsistent capitalization ("{{count}} posizione"
vs "{{count}} Località"); update locationWithCount_other to match the singular
style by changing "{{count}} Località" to "{{count}} località" so both forms use
the same lowercase capitalization.

In `@packages/visual-editor/locales/platform/nb/visual-editor.json`:
- Line 244: The JSON key "linkType" currently has an English value ("Link
Type"); replace that value with the correct Norwegian translation (e.g.,
"Koblingstype" or "Linktype") so the locale entry for "linkType" is in
Norwegian; update the value for the "linkType" key in the visual-editor.nb
locale JSON to the chosen Norwegian string.

In `@packages/visual-editor/locales/platform/nl/visual-editor.json`:
- Line 611: The Dutch translation for the key theme.fontWeight.fontWeight is
incorrect—"Lettertype" means "Font" not "Font Weight"; update the value for the
"fontWeight" key (the one nested under theme.fontWeight / the JSON entry
currently "Lettertype") to a correct Dutch term such as "Lettergewicht" or
"Tekstdikte" so it correctly reflects "Font Weight".

In `@packages/visual-editor/locales/platform/pl/visual-editor.json`:
- Around line 481-482: The pluralization for the key "locationWithCount" only
defines `_one` and `_other`, which is incorrect for Polish; add `_few` and
`_many` variants so i18next/CLDR plural rules can select correct forms (e.g.,
`_few` => "{{count}} lokalizacje", `_many` => "{{count}} lokalizacji") alongside
the existing `_one` and `_other`; apply the same pattern to any other Polish
plural keys (e.g., "kilometer", "mile", "totalReviews", "locationsNear") to
ensure counts map to one/few/many/other correctly.

In `@packages/visual-editor/locales/platform/sk/visual-editor.json`:
- Line 450: The JSON value for the "heading" key is mistranslated as
"Smerovanie" (routing); update the value to the correct Slovak term "Nadpis" for
the "heading" key in this file and also search for the "sectionHeading" key
(mentioned at line 391) and replace its value "Smerovanie sekcie" with "Nadpis
sekcie" if appropriate to keep consistency; ensure you only change the string
values for the keys "heading" and "sectionHeading" (no other keys or
formatting).
- Around line 481-482: Change the inconsistent Slovak wording so both keys use
the same root "lokácia"/"lokality": update locationWithCount_one to use
"{{count}} lokácia" (singular) and keep/update locationWithCount_other to
"{{count}} lokality" (plural) so the singular and plural forms are consistent
and use the same concept.

In `@packages/visual-editor/locales/platform/sv/visual-editor.json`:
- Line 68: Remove the unused PascalCase locale keys HoursStatus and HoursTable
from the visual-editor JSON to avoid duplicate entries—keep the camelCase keys
used by the code (components.hoursStatus and components.hoursTable) and retain
intentional PascalCase keys like DirectoryGrid and Video; locate the two
PascalCase entries named "HoursStatus" and "HoursTable" in the file and delete
those lines so only the camelCase variants remain.

In `@packages/visual-editor/locales/platform/zh-TW/visual-editor.json`:
- Around line 481-482: The two plural keys locationWithCount_one and
locationWithCount_other are inconsistent (one uses " {{count}} 個位置" with a space
and classifier, the other uses "{{count}}位置" without them); update the
translations so both plural forms match (e.g., set locationWithCount_other to
the same string as locationWithCount_one or vice versa) to ensure consistent
pluralization and display across zh-TW; edit the entries for
locationWithCount_one and locationWithCount_other in the visual-editor.json
accordingly.

In `@packages/visual-editor/locales/platform/zh/visual-editor.json`:
- Around line 481-482: The two translation keys locationWithCount_one and
locationWithCount_other are inconsistent; make both identical by using the same
Chinese phrase with the classifier — update locationWithCount_other to match
locationWithCount_one (i.e., both should be "{{count}} 个位置") so both plural
forms are the same.
- Around line 189-190: Remove the duplicate top-level locale keys "ctaVariant"
and "CTAVariant": either delete both if unused, or consolidate by keeping a
single canonical key (preferably "fields.ctaVariant") and move/rename the
translated value there; then run a quick search for usages of "ctaVariant" or
"CTAVariant" to update any callers to the canonical key and ensure msg()/i18n
lookups still resolve correctly.
🧹 Nitpick comments (15)
packages/visual-editor/locales/platform/fi/visual-editor.json (1)

68-68: Inconsistent key casing: PascalCase keys among camelCase siblings.

"DirectoryGrid" and "Video" use PascalCase while all surrounding keys in components use camelCase (e.g., directoryCard, videoSection). The same pattern appears for CTAVariant (Line 190), HoursStatus (Line 323), and HoursTable (Line 324). If these map directly to component/option names in code, this may be intentional — but it's worth confirming the convention so lookups don't silently miss due to casing mismatches.

,

#!/bin/bash
# Check if PascalCase keys like DirectoryGrid, Video, HoursStatus, HoursTable, CTAVariant
# are used consistently across all locale files in this directory tree
echo "=== PascalCase keys in platform locale files ==="
rg -n '"(DirectoryGrid|Video|CTAVariant|HoursStatus|HoursTable)"' --type json -g '*/locales/platform/*' | head -40

echo ""
echo "=== Check component code referencing these keys ==="
rg -n 'DirectoryGrid|HoursStatus|HoursTable' --type ts --type tsx -g '!**/locales/**' -g '!node_modules/**' | head -30

Also applies to: 124-124

packages/visual-editor/locales/platform/it/visual-editor.json (1)

68-68: PascalCase keys mixed with camelCase siblings.

DirectoryGrid (Line 68), Video (Line 124), HoursStatus (Line 323), and HoursTable (Line 324) use PascalCase, while surrounding keys are camelCase (directory, videoSection, hour12, hour24). This is likely driven by the new i18next-cli extracting component/enum names verbatim, but it creates an inconsistent convention within the same JSON object.

If PascalCase is the intended convention going forward for component-derived keys, consider documenting it. Otherwise, normalizing to camelCase would keep the file consistent.

Also applies to: 124-124, 323-324

packages/visual-editor/locales/platform/lt/visual-editor.json (1)

68-68: Inconsistent key casing: PascalCase keys among camelCase siblings.

"DirectoryGrid" (Line 68) and "Video" (Line 124) use PascalCase, while all surrounding sibling keys in components use camelCase (e.g., directory, videoSection, aboutSection). The same pattern appears in fields.options with "HoursStatus" / "HoursTable" (Lines 323–324). This likely reflects the i18next-cli extracting raw component/type names. Consider normalizing to camelCase for consistency, or documenting the convention if PascalCase is intentional for component-name keys.

Also applies to: 124-124

packages/visual-editor/locales/platform/da/visual-editor.json (1)

68-68: Normalize PascalCase keys to camelCase for consistency.

Keys DirectoryGrid (line 68), Video (line 124), HoursStatus (line 323), and HoursTable (line 324) use PascalCase while the file overwhelmingly uses camelCase (e.g., directory, videoSection, hoursStatus, hoursTable). Note that camelCase equivalents already exist: hoursStatus (line 95) and hoursTable (line 96), creating redundancy. Either standardize all component/field names to camelCase to match the file convention, or document the rationale for the mixed convention.

packages/visual-editor/locales/platform/pl/visual-editor.json (1)

28-28: Pre-existing typo: "Breatcrumb" → "Breadcrumb".

"Breatcrumb" (Line 28) and "Breatcrumbs" (Line 60) appear to be typos — the English loanword should be "Breadcrumb"/"Breadcrumbs". Not introduced in this PR, but worth fixing while the locale files are being reworked.

packages/visual-editor/locales/platform/de/visual-editor.json (1)

68-68: PascalCase keys in locale file correspond to source code identifiers and appear intentional, but confirm this pattern is expected for future consistency.

DirectoryGrid (line 68), Video (line 124), HoursStatus and HoursTable (lines 323-324), and CTAVariant (line 190) use PascalCase while all sibling keys in their respective objects use camelCase. These keys correspond to source code component/type names (DirectoryGrid type in defaultLayoutData.ts, CTAVariant type in atoms/cta.tsx, HoursStatusAtom/HoursTableAtom in LocatorResultCard.tsx), suggesting the naming is intentional to match source identifiers. Verify that this convention is documented or enforced for future locale additions to maintain consistency in the file.

Also, ctaVariant (line 189) and CTAVariant (line 190) coexist with slightly different translation values ("CTA -Variante" vs "CTA-Variante") — they appear to serve different purposes (field label vs type name), which is fine, but be aware both exist in the file.

packages/visual-editor/locales/platform/et/visual-editor.json (1)

68-68: PascalCase keys introduced within otherwise camelCase objects.

New keys like DirectoryGrid, Video, HoursStatus, and HoursTable use PascalCase while siblings use camelCase (e.g., directory, videoSection, hoursTable). This is likely intentional (matching component/enum names in code), but the mix could cause confusion—especially "hoursTable" (line 96) vs "HoursTable" (line 324) which live in different nested objects but look like near-duplicates.

Also applies to: 124-124, 323-324

packages/visual-editor/locales/platform/hr/visual-editor.json (1)

68-68: Inconsistent key casing: PascalCase keys (DirectoryGrid, Video) among camelCase siblings.

These likely mirror React component names, but they break the naming convention used by every other key in the components object. The same pattern appears in fields.options with HoursStatus/HoursTable (Lines 323–324). If this is intentional for the new i18next-cli extraction, no action needed—just flagging for awareness.

Also applies to: 124-124

packages/visual-editor/locales/platform/cs/visual-editor.json (1)

68-68: PascalCase keys DirectoryGrid and Video break the camelCase convention used by all surrounding keys.

Every other key in the components object uses camelCase (e.g., aboutSection, bannerSection, hoursStatus). These two PascalCase keys stand out and may confuse future contributors or cause lookup misses if code elsewhere expects camelCase.

If i18next-cli is extracting these from PascalCase component names, consider adding a key transformation in the extraction config to normalize to camelCase.

Also applies to: 124-124

packages/visual-editor/locales/platform/fr/visual-editor.json (1)

68-68: PascalCase keys DirectoryGrid and Video break the components naming convention.

Every other key in the components object uses camelCase (e.g., directory, videoSection, aboutSection). These two PascalCase keys appear to come from the i18next-cli extracting component names verbatim. If this is intentional, consider documenting the convention; otherwise, align them with the existing camelCase pattern.

Also applies to: 124-124

packages/visual-editor/scripts/checkInterpolationVariables.mjs (1)

22-101: Utility functions duplicated from jsonUtils.ts.

loadJsonSafe, saveJson, flatten, unflatten, sortObject, and getLocales mirror their TypeScript counterparts in src/utils/i18n/jsonUtils.ts. This is understandable since the .mjs script runs with node directly and can't import .ts files without a build step, but it creates a maintenance surface — changes to one copy must be mirrored in the other.

Consider running this script via tsx (like propagatePlatformToComponents.ts) to share the implementations, or add a comment noting the dependency.

packages/visual-editor/scripts/generateTranslations.ts (2)

254-282: Unbounded parallelism — all keys translated concurrently per locale.

Promise.allSettled fires every translateText call in parallel with no concurrency cap. For locales with many missing keys, this can trigger Google's rate limiter and cause most requests to fail.

Consider batching with a concurrency limit (e.g., via a simple semaphore or p-limit).

Example with p-limit
+import pLimit from "p-limit";
+
+const limit = pLimit(5);
+
     await Promise.allSettled(
       keysToTranslate.map(async (key) => {
+        return limit(async () => {
           const english = defaultJson[key];
           // ... translation logic ...
+        });
       })
     );

45-56: Misleading error when --type flag is present but value is missing.

If --type is the last argv element, process.argv[index + 1] is undefined, producing the error Unsupported --type "undefined". A clearer check would distinguish "missing value" from "wrong value."

Suggested improvement
 const getTypeArg = (): TranslationType => {
   const index = process.argv.findIndex((arg) => arg === "--type");
-  const raw = index >= 0 ? process.argv[index + 1] : "platform";
+  if (index < 0) return "platform";
+
+  const raw = process.argv[index + 1];
+  if (!raw || raw.startsWith("-")) {
+    throw new Error(`--type requires a value. This script only supports "--type platform".`);
+  }

   if (raw !== "platform") {
packages/visual-editor/src/utils/i18n/jsonUtils.ts (1)

46-61: flatten coerces non-object leaf values to String — arrays become comma-joined strings.

String([1, 2]) produces "1,2", which is lossy. This is fine for i18n string values but worth noting if the JSON ever contains non-string leaves beyond null/undefined.

packages/visual-editor/locales/platform/en/visual-editor.json (1)

68-68: PascalCase keys (DirectoryGrid, Video) break the camelCase convention used by sibling entries.

Under components, all other keys use camelCase (e.g., aboutSection, videoSection). DirectoryGrid and Video use PascalCase, presumably matching React component names. This is fine if intentional but consider aligning the convention for consistency across the i18n surface.

Also applies to: 124-124

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/visual-editor/locales/platform/cs/visual-editor.json (1)

28-28: ⚠️ Potential issue | 🟡 Minor

Same mistranslation: "breadcrumb": "Strouha" — see components file comment.

Same issue as in the components locale file. "Strouha" is not the correct Czech for navigational "breadcrumb." Line 60 (components.breadcrumbs) correctly uses "Strouhanka."

Proposed fix
-  "breadcrumb": "Strouha",
+  "breadcrumb": "Drobečková navigace",
packages/visual-editor/locales/platform/lv/visual-editor.json (1)

28-28: ⚠️ Potential issue | 🟡 Minor

"breadcrumb" translated as "Rīvmaize" (food breadcrumbs) — likely a machine-translation error.

"Rīvmaize" is the Latvian word for culinary breadcrumbs. For the UI navigation concept, the English loanword "Breadcrumb" (or a descriptive term like "Navigācijas ceļš") is more appropriate. The same issue appears at line 60 (components.breadcrumbs).

Proposed fix
-  "breadcrumb": "Rīvmaize",
+  "breadcrumb": "Navigācijas ceļš",

And at line 60:

-    "breadcrumbs": "Navigācijas ceļš",
+    "breadcrumbs": "Navigācijas ceļi",
packages/visual-editor/locales/platform/hr/visual-editor.json (1)

461-491: ⚠️ Potential issue | 🟡 Minor

Incorrect Croatian _few plural forms for unit nouns.

Croatian uses distinct forms for counts 2–4 (_few). Currently both _few and _other are identical, which produces incorrect grammar:

Key Current _few Correct _few
kilometer_few (Line 462) "kilometara" "kilometra"
mile_few (Line 490) "milja" "milje"

Croatian counting: 2 kilometra (gen. sg.), 5 kilometara (gen. pl.); 2 milje (nom. pl.), 5 milja (gen. pl.).

Proposed fix
   "kilometer_one": "kilometar",
-  "kilometer_few": "kilometara",
+  "kilometer_few": "kilometra",
   "kilometer_other": "kilometara",
   "mile_one": "milja",
-  "mile_few": "milja",
+  "mile_few": "milje",
   "mile_other": "milja",
🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/components/fi/visual-editor.json`:
- Line 37: Update the Finnish translation for the JSON key "informationSection"
in visual-editor.json: replace the incorrect value "Tiedonsiirto" with the
correct term "Tieto-osio" so the label reads appropriately for Finnish users;
locate the "informationSection" key in the file and change its string value
accordingly.

In `@packages/visual-editor/locales/components/fr/visual-editor.json`:
- Around line 54-56: The translation key "mile_many" in the locale file is
incorrect ("kilomètres"); update the value for "mile_many" to the correct French
word "miles" so it matches "mile_one" and "mile_other" and avoids showing
kilometers where miles are intended; locate the key "mile_many" in the
visual-editor.json and replace its string accordingly.

In `@packages/visual-editor/locales/components/hr/visual-editor.json`:
- Line 38: Update the Croatian `_few` plural variants to use the nominative
plural (counts 2–4) instead of the genitive plural; specifically change the keys
locationWithCount_few, locationsNear_few, locationsWithinDistanceOf_few,
mile_few, totalReviews_few and the kilometer_few entry to their correct
nominative-plural forms (e.g., "{{count}} lokacije" for locationWithCount_few,
"{{count}} lokacije u blizini…" for locationsNear_few, "{{count}} lokacije
unutar…" for locationsWithinDistanceOf_few, "milje" for mile_few, "{{count}}
recenzije" for totalReviews_few, and use "kilometra" for kilometer_few where
appropriate); verify other mentioned keys (lines 43,46,49,54,96) and replace
their `_few` values similarly with the nominative plural endings (-ije/-je for
feminine -ija/-ja nouns and -a for neuter/masculine as appropriate).

In `@packages/visual-editor/locales/components/it/visual-editor.json`:
- Line 9: The Italian translation for the key "breadcrumb" is incorrect ("Pane"
means bread); update the value for the "breadcrumb" key in the visual-editor
locale to a proper navigation term such as "Breadcrumb", "Percorso di
navigazione", or simply "Percorso" so it reflects the UI concept of navigation
breadcrumbs rather than the food item.

In `@packages/visual-editor/locales/platform/fr/visual-editor.json`:
- Around line 490-491: The "mile_many" translation is incorrect ("kilomètres");
update the JSON entry for the key "mile_many" to use the correct French word
"miles" to match the other plural forms (see "mile_one" and "mile_other"); edit
the value for "mile_many" in the visual-editor localization JSON so it equals
"miles" and run any i18n/locale validations or tests to ensure no formatting
errors.

In `@packages/visual-editor/scripts/generateTranslations.ts`:
- Around line 334-361: The current Promise.allSettled over translationTargets
fires all translateText calls in parallel causing rate-limits; change this to a
bounded-concurrency loop or use a limiter like p-limit to run at most N (e.g.,
5) translations concurrently. Keep the per-item logic
(maskInterpolationVariables, embedContextInText, removeEmbeddedContext,
unmaskInterpolationVariables), preserve updating cache.set(key.trim(),
translated), successCount/failCount increments, and the console logs/error
handling, but schedule translateText(...) through the limiter (or process
translationTargets in async batches) so translateText, cache updates and
counters occur inside the limited task function. Ensure Promise.allSettled
awaits the queued limited tasks so the script still waits for all translations
to finish.
🟡 Minor comments (47)
packages/visual-editor/locales/components/pl/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Typo: "Breatcrumb" → "Breadcrumb".

Missing the letter 'd'. This will be user-visible in the UI.

✏️ Proposed fix
-  "breadcrumb": "Breatcrumb",
+  "breadcrumb": "Breadcrumb",
packages/visual-editor/locales/components/es/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

"Migaja de pan" is an unusual choice for breadcrumb navigation.

The literal translation "Migaja de pan" (a single bread crumb/morsel) is not the standard UI term in Spanish. The common terms are "Migas de pan" (plural) or, more idiomatically for web navigation, "Ruta de navegación." Consider aligning with typical Spanish UI conventions.

packages/visual-editor/locales/components/es/visual-editor.json-46-48 (1)

46-48: ⚠️ Potential issue | 🟡 Minor

Inconsistent word order in locationsNear_many compared to sibling plural forms.

The _many variant places the count after the noun ("Ubicaciones {{count}} cerca de..."), while _one and _other place it before ("{{count}} ubicación/ubicaciones cerca de..."). This will produce visually jarring text if the _many form is ever resolved.

Proposed fix
-  "locationsNear_many": "Ubicaciones {{count}} cerca de \"{{name}}\"",
+  "locationsNear_many": "{{count}} ubicaciones cerca de \"{{name}}\"",
packages/visual-editor/locales/components/es/visual-editor.json-96-98 (1)

96-98: ⚠️ Potential issue | 🟡 Minor

Inconsistent term across totalReviews plural forms.

totalReviews_many uses "opiniones" while _one uses "reseña" and _other uses "reseñas". These are different words ("opinions" vs. "reviews"). Plural variants of the same key should use the same term to avoid a jarring switch in vocabulary based on count.

Proposed fix
-  "totalReviews_many": "{{count}} opiniones",
+  "totalReviews_many": "{{count}} reseñas",
packages/visual-editor/locales/components/ro/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Inconsistent use of definite vs. indefinite article in section labels.

The new section-related keys mix "Secțiune de …" (indefinite) and "Secțiunea …" (definite):

Key Value Article
hoursSection "Secțiune de ore" indefinite
informationSection "Secțiune de informații" indefinite
coreInfoSection "Secțiunea de informații de bază" definite
photoGallerySection "Secțiunea Galerie foto" definite
servicesSection "Secțiunea Servicii" definite

Pick one form consistently. Since these are UI section headings, the definite article ("Secțiunea …") is typically more natural in Romanian.

Proposed fix (align to definite article)
-  "hoursSection": "Secțiune de ore",
+  "hoursSection": "Secțiunea de ore",
-  "informationSection": "Secțiune de informații",
+  "informationSection": "Secțiunea de informații",

Also applies to: 35-37, 65-68, 79-80

packages/visual-editor/locales/components/ro/visual-editor.json-49-49 (1)

49-49: ⚠️ Potential issue | 🟡 Minor

Wording in locationsWithinDistanceOf_few diverges from sibling plural forms.

The _few form uses "în {{distance}} {{unit}} din" while _one (line 50) uses "la {{distance}} {{unit}} de" and _other (line 51) uses "pe o rază de {{distance}} {{unit}} de". While some variation across plural forms can be natural, the preposition combination "în…din" vs "la…de" / "pe o rază de…de" feels inconsistent and could confuse users. Consider aligning the phrasing across plural variants.

packages/visual-editor/locales/components/ro/visual-editor.json-20-24 (1)

20-24: ⚠️ Potential issue | 🟡 Minor

Utility image alt text — translation is acceptable.

"Imagine utilitar {{number}}" conveys "Utility image {{number}}". Grammatically, "utilitară" (feminine adjective to agree with "imagine") would be more correct than "utilitar" (masculine/neuter), but this is a minor grammatical nit.

Optional grammar fix
-      "defaultAlt": "Imagine utilitar {{number}}"
+      "defaultAlt": "Imagine utilitară {{number}}"
packages/visual-editor/locales/components/lt/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Likely incorrect machine translation for "breadcrumb".

"Komprumbas" does not appear to be a valid Lithuanian word. The literal translation for "breadcrumb" would be "Duonos trupinys" (or "trupiniai" for plural). For a UI navigation context, it's common to use "Naršymo kelias" (navigation path) or simply leave it as the loanword "Breadcrumb." This looks like a Google Translate artifact from the new automated translation pipeline.

Suggested fix
-  "breadcrumb": "Duonos komprumbas",
+  "breadcrumb": "Naršymo kelias",
packages/visual-editor/locales/components/it/visual-editor.json-36-36 (1)

36-36: ⚠️ Potential issue | 🟡 Minor

Incorrect Italian word order for "hoursSection".

"Ore sezione" reverses the expected Italian noun–modifier order. Other section keys in this file follow the correct pattern — e.g., "servicesSection": "Sezione Servizi" (Line 80) and "coreInfoSection": "Sezione Informazioni fondamentali" (Line 25).

Proposed fix
-  "hoursSection": "Ore sezione",
+  "hoursSection": "Sezione orari",
packages/visual-editor/locales/components/it/visual-editor.json-43-51 (1)

43-51: ⚠️ Potential issue | 🟡 Minor

Inconsistent terminology across plural forms for location-related keys.

The _many and _other plural variants use different Italian words for the same concept:

Key _many _other
locationWithCount "posizioni" "località"
locationsNear "luoghi" "località"
locationsWithinDistanceOf "posizioni" "località"

In Italian, both _many and _other are plural forms (CLDR rules), so they should use consistent vocabulary. This looks like a machine translation artifact. Pick one term (e.g., "località" or "posizioni") and use it consistently across all plural variants.

packages/visual-editor/locales/platform/nb/visual-editor.json-445-446 (1)

445-446: ⚠️ Potential issue | 🟡 Minor

"Misligholde" is a mistranslation of "default" in a UI context.

"Misligholde" means "to default on a debt/obligation" (i.e., fail to pay). For a UI label meaning "the preset/standard option," the correct Norwegian term is "Standard". This same mistranslation appears elsewhere in the file (lines 140, 273, 563) but those are pre-existing; this changed line perpetuates the error.

Proposed fix
-  "fontSizeDefaultLabel": "Misligholde",
+  "fontSizeDefaultLabel": "Standard",
packages/visual-editor/locales/platform/nb/visual-editor.json-238-243 (1)

238-243: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation of "link" prefix across sibling keys.

linkLabel → "Koblingsetikett" and linkType → "Koblingstype" both use the Norwegian root "Kobling", but linkTarget on Line 242 uses the English loanword "Link" → "Linkmål". For consistency, this should also use "Kobling".

Proposed fix
-    "linkTarget": "Linkmål",
+    "linkTarget": "Koblingsmål",
packages/visual-editor/locales/components/zh-TW/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

New keys use Simplified Chinese–style "信息" instead of Traditional Chinese "資訊".

Lines 25 and 37 use "信息" (common in zh-CN) where zh-TW convention prefers "資訊." While the existing unchanged line 10 (businessInformation) already uses "信息," new keys added to this file are an opportunity to use the correct regional variant.

Proposed fix
-  "coreInfoSection": "核心信息部分",
+  "coreInfoSection": "核心資訊部分",
-  "informationSection": "信息部分",
+  "informationSection": "資訊部分",

Also applies to: 37-37

packages/visual-editor/locales/components/zh-TW/visual-editor.json-35-36 (1)

35-36: ⚠️ Potential issue | 🟡 Minor

"hours" is translated as the time unit ("小時") instead of business/operating hours ("營業時間").

In the context of a location page, "hours" refers to business hours (營業時間), not the time unit (小時). The same issue applies to "hoursSection" → should be "營業時間部分" rather than "小時部分". The AI summary mentions Google Translate integration for automated translation, which likely caused this mistranslation.

Proposed fix
-  "hours": "小時",
-  "hoursSection": "小時部分",
+  "hours": "營業時間",
+  "hoursSection": "營業時間部分",
packages/visual-editor/locales/components/sk/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Likely mistranslation: "Strúhanka" is the culinary term for breadcrumbs, not the UI navigation concept.

"Strúhanka" refers to food-coating breadcrumbs. For breadcrumb navigation in Slovak, a more appropriate translation would be something like "Navigačná cesta" or simply keeping it as "Breadcrumb," which is commonly used in Slovak tech/UI contexts. This looks like a machine-translation artifact.

packages/visual-editor/locales/components/fr/visual-editor.json-49-51 (1)

49-51: ⚠️ Potential issue | 🟡 Minor

Inconsistent quotation style and phrasing across plural variants.

locationsWithinDistanceOf_many uses French guillemets « » and the preposition "dans", while _one uses \"\" with "à" and _other uses \"\" with "dans un rayon de". Plural variants should only differ in grammatical number, not in punctuation style or phrasing — users will see different formatting depending on the count.

Consider aligning all three variants to use the same quote style (preferably « » for proper French typography) and consistent phrasing.

packages/visual-editor/locales/components/zh/visual-editor.json-44-45 (1)

44-45: ⚠️ Potential issue | 🟡 Minor

Inconsistent wording between locationsNear_one and locationsNear_other.

_one uses "位置" while _other uses "地点" for "location(s)." These are synonyms, but the inconsistency suggests the translations weren't reviewed for uniformity. Since _one is never resolved for zh (per CLDR), only the _other form matters here—but consider aligning them if these files are maintained by hand or used as a reference.

packages/visual-editor/locales/platform/zh/visual-editor.json-476-477 (1)

476-477: ⚠️ Potential issue | 🟡 Minor

Inconsistent wording between locationsNear_one and locationsNear_other.

_one uses "位置" (location) while _other uses "地点" (place). Since Chinese has no grammatical plural distinction, these two forms will both be displayed and should use identical wording.

Proposed fix
  "locationsNear_one": ""{{name}}"附近有 {{count}} 个位置",
- "locationsNear_other": ""{{name}}"附近有 {{count}} 个地点",
+ "locationsNear_other": ""{{name}}"附近有 {{count}} 个位置",
packages/visual-editor/locales/components/lv/visual-editor.json-80-80 (1)

80-80: ⚠️ Potential issue | 🟡 Minor

Inconsistent "section" translation: nodaļa vs sadaļa.

servicesSection uses "nodaļa" (department), while all other *Section keys in this file use "sadaļa" (section): hoursSection"Stundu sadaļa", informationSection"Informācijas sadaļa", photoGallerySection"Foto galerijas sadaļa". Use "sadaļa" for consistency.

Suggested fix
-  "servicesSection": "Pakalpojumu nodaļa",
+  "servicesSection": "Pakalpojumu sadaļa",
packages/visual-editor/locales/components/lv/visual-editor.json-35-36 (1)

35-36: ⚠️ Potential issue | 🟡 Minor

hours translated as "Laiks" (time) — likely should be "Stundas" or "Darba laiks".

"Laiks" means "time" in general, not "hours." This is a business-hours context, and inconsistently, hoursSection on the next line uses "Stundu sadaļa" (hours section). Consider "Darba laiks" (business hours) or "Stundas" for consistency.

Suggested fix
-  "hours": "Laiks",
+  "hours": "Darba laiks",
packages/visual-editor/locales/components/lv/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

"breadcrumb" translated as food item rather than navigation concept.

"Rīvmaize" is the literal Latvian word for breadcrumbs (food). In a UI navigation context, this may confuse users. Latvian web conventions typically use "Navigācijas ceļš" (navigation path) or sometimes retain "Breadcrumb" as a loanword. Please verify with a native speaker or Latvian UI localization reference.

packages/visual-editor/locales/components/lv/visual-editor.json-67-68 (1)

67-68: ⚠️ Potential issue | 🟡 Minor

Translation quality issues: redundancy and untranslated value.

Two problems in these adjacent keys:

  1. Line 67"Reklāmas reklāmkarogs" is redundant; "reklāmkarogs" already means "advertising banner." Consider just "Reklāmkarogs" or "Akciju reklāmkarogs" (promo banner).
  2. Line 68"Promo Media" is left entirely in English. All other keys in this file are translated to Latvian. This looks like a machine-translation miss.
Suggested fix
-  "promoBanner": "Reklāmas reklāmkarogs",
-  "promoMedia": "Promo Media",
+  "promoBanner": "Akciju reklāmkarogs",
+  "promoMedia": "Reklāmas mediji",
packages/visual-editor/locales/platform/ro/visual-editor.json-68-68 (1)

68-68: ⚠️ Potential issue | 🟡 Minor

Mixed-language translation: "Director Grid".

"Grid" is left in English while "Director" is Romanian. Elsewhere in this file, "grid" is translated — e.g., line 89: "gridSection": "Secțiune Grila". Consider using "Grilă Director" for consistency.

Proposed fix
-    "directoryGrid": "Director Grid",
+    "directoryGrid": "Grilă Director",
packages/visual-editor/locales/platform/fi/visual-editor.json-124-124 (1)

124-124: ⚠️ Potential issue | 🟡 Minor

Inconsistent key casing: "Video" should be "video".

All other keys in the components object use camelCase (e.g., videoSection, directoryGrid, testimonialCard). "Video" with an uppercase V breaks this convention and may cause lookup failures if consuming code expects "video".

Proposed fix
-    "Video": "Video",
+    "video": "Video",
packages/visual-editor/locales/platform/fi/visual-editor.json-445-446 (1)

445-446: ⚠️ Potential issue | 🟡 Minor

Mistranslation: "Laiminlyönti" means "neglect", not "default".

"Laiminlyönti" is the Finnish word for "neglect/default on an obligation" (legal/financial sense). The correct translation for a UI default value label is "Oletus" — which is already correctly used elsewhere in this file (e.g., Line 140: "default": "Oletus"). This looks like a Google Translate error confusing the two English meanings of "default".

The same mistranslation also exists in unchanged lines (273, 563) — worth fixing those too.

Proposed fix
- "fontSizeDefaultLabel": "Laiminlyönti",
+ "fontSizeDefaultLabel": "Oletus",
packages/visual-editor/locales/components/fi/visual-editor.json-75-75 (1)

75-75: ⚠️ Potential issue | 🟡 Minor

"Palvelusosasto" means "service department" (organizational), not a UI "services section".

In Finnish, "osasto" refers to a department (e.g., hospital ward, store department), while "osio" is the correct term for a section of a page or UI. Consider "Palvelut-osio".

🌐 Proposed fix
-  "servicesSection": "Palvelusosasto",
+  "servicesSection": "Palvelut-osio",
packages/visual-editor/locales/components/fi/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Incorrect Finnish UI term for "breadcrumb".

"Leivänmuru" is a literal translation meaning a physical bread crumb. The standard Finnish UI term for breadcrumb navigation is "murupolku" (crumb path).

🌐 Proposed fix
-  "breadcrumb": "Leivänmuru",
+  "breadcrumb": "Murupolku",
packages/visual-editor/locales/components/fi/visual-editor.json-63-63 (1)

63-63: ⚠️ Potential issue | 🟡 Minor

"Promootio" translates to "Promotion", missing the "media" aspect of promoMedia.

Consider "Promomedia" to retain both concepts.

🌐 Proposed fix
-  "promoMedia": "Promootio",
+  "promoMedia": "Promomedia",
packages/visual-editor/locales/components/fi/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Spurious space before hyphen in compound word.

Finnish compound words with a hyphen don't have a space before the hyphen. "Ydintiedot -osio" → "Ydintiedot-osio".

🌐 Proposed fix
-  "coreInfoSection": "Ydintiedot -osio",
+  "coreInfoSection": "Ydintiedot-osio",
packages/visual-editor/locales/components/cs/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Mistranslation: "breadcrumb": "Strouha" is incorrect Czech.

"Strouha" doesn't mean "breadcrumb" in the navigational sense — it appears to be a truncated/garbled machine translation. The platform file (Line 60 in components) correctly uses "Strouhanka" for "breadcrumbs". For the singular key, consider using "Drobečková navigace" (the standard Czech UI term) or at minimum "Strouhanka" to stay consistent with the plural form.

Proposed fix
-  "breadcrumb": "Strouha",
+  "breadcrumb": "Drobečková navigace",
packages/visual-editor/locales/components/hr/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Questionable Croatian translation for "breadcrumb".

"Krušnica" does not appear to be a standard Croatian term for breadcrumb navigation. In Croatian web UI, the breadcrumb trail is commonly referred to as "navigacijski put" (navigation path), "breadcrumb" (kept as-is), or "putanja" (path). This looks like it may be a machine-translation artifact. Please verify with a native Croatian speaker.

packages/visual-editor/locales/components/hr/visual-editor.json-35-37 (1)

35-37: ⚠️ Potential issue | 🟡 Minor

Translation quality issues: incorrect case and incomplete translations.

Three concerns here:

  1. "hours": "Sate" — "Sate" is the accusative form. For a standalone UI label, the nominative "Sati" is expected.
  2. "hoursSection": "Odjeljak" and "informationSection": "Odjeljak" — These translate to just "Section" with no qualifier, unlike other similar keys in this file (e.g., "servicesSection": "Odjeljak za usluge", "photoGallerySection": "Odjeljak fotogalerije"). These should include context, e.g., "Odjeljak radnog vremena" and "Odjeljak informacija".

This is consistent with the PR description mentioning Google Translate integration in the new translate script — these appear to be machine-translated without post-editing.

Suggested fix
-  "hours": "Sate",
-  "hoursSection": "Odjeljak",
-  "informationSection": "Odjeljak",
+  "hours": "Sati",
+  "hoursSection": "Odjeljak radnog vremena",
+  "informationSection": "Odjeljak informacija",
packages/visual-editor/locales/platform/da/visual-editor.json-445-446 (1)

445-446: ⚠️ Potential issue | 🟡 Minor

"Misligholdelse" is a mistranslation of "default" in UI context.

"Misligholdelse" means "default" in the legal/financial sense (breach, non-compliance). The correct Danish UI term for a preset/standard value is "Standard". This same mistranslation also appears at lines 140, 273, and 563 — likely a systematic machine-translation error.

Proposed fix (this line + pre-existing occurrences)
-  "fontSizeDefaultLabel": "Misligholdelse",
+  "fontSizeDefaultLabel": "Standard",

Also fix pre-existing occurrences outside the changed lines:

Line 140: "default": "Standard"
Line 273: "default": "Standard"  
Line 563: "spacingDefaultLabel": "Standard"
packages/visual-editor/locales/platform/es/visual-editor.json-645-646 (1)

645-646: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation: "opiniones" vs "reseñas" for reviews.

Line 645 (_many) uses "opiniones" (opinions) while line 646 (_other) uses "reseñas" (reviews). Although _many is never selected for Spanish, these should use the same term for consistency. "Reseñas" is the correct translation for "reviews" in this context.

Proposed fix
-  "totalReviews_many": "{{count}} opiniones",
+  "totalReviews_many": "{{count}} reseñas",
packages/visual-editor/locales/platform/es/visual-editor.json-124-124 (1)

124-124: ⚠️ Potential issue | 🟡 Minor

Inconsistent key casing: "Video" should be "video".

The key uses PascalCase while all sibling keys in the components object use camelCase (e.g., timestamp, videoSection, hoursStatus). Other "video" keys elsewhere in the file (lines 366, 431) also use lowercase. This inconsistency exists in the English source locale as well, so both locales should be corrected to use "video" for consistency.

packages/visual-editor/locales/platform/sk/visual-editor.json-478-481 (1)

478-481: ⚠️ Potential issue | 🟡 Minor

Inconsistent terminology in locationsNear plural forms.

The _one form uses "umiestnenie" (placement/positioning) while the _few/_many/_other forms use "miest" (from "miesto" = place/location). These should share the same root word, consistent with how locationWithCount was corrected.

Proposed fix
-  "locationsNear_one": "{{count}} umiestnenie blízko „{{name}}"",
+  "locationsNear_one": "{{count}} miesto blízko „{{name}}"",
packages/visual-editor/locales/platform/tr/visual-editor.json-480-481 (1)

480-481: ⚠️ Potential issue | 🟡 Minor

Turkish pluralization: nouns after numerals should not take the plural suffix.

In Turkish, when a noun is preceded by a number, it remains singular (e.g., "5 konum", not "5 konumlar"). The _other form should use the singular noun, same as _one. Additionally, _one capitalizes "Konum" while _other lowercases "konumlar" — these should be consistent.

Proposed fix
-  "locationWithCount_one": "{{count}} Konum",
-  "locationWithCount_other": "{{count}} konumlar",
+  "locationWithCount_one": "{{count}} konum",
+  "locationWithCount_other": "{{count}} konum",
packages/visual-editor/locales/platform/fr/visual-editor.json-480-482 (1)

480-482: ⚠️ Potential issue | 🟡 Minor

Inconsistent quoting style across locationsWithinDistanceOf plural variants.

Line 480 (_one) and line 482 (_other) wrap {{name}} in escaped double-quotes (\"{{name}}\"), but the new _many variant on line 481 uses French guillemets (« {{name}} »). This will produce visually different output depending on the count.

Proposed fix — align with sibling entries
-    "locationsWithinDistanceOf_many": "{{count}} emplacements dans {{distance}} {{unit}} de « {{name}} »",
+    "locationsWithinDistanceOf_many": "{{count}} emplacements dans {{distance}} {{unit}} de \"{{name}}\"",
packages/visual-editor/locales/platform/hu/visual-editor.json-445-446 (1)

445-446: ⚠️ Potential issue | 🟡 Minor

fontSize is mistranslated; fontSizeDefaultLabel uses a misleading word for "Default".

  • Line 445: "Betűkészlet" means "font family / font set" in Hungarian, not "font size." The correct translation is "Betűméret". The same mistranslation appears at Line 608 (theme.fontSize), which was not changed in this PR but carries the same error.
  • Line 446: "Mulasztás" literally means "negligence / omission." While it can loosely be used for "default" in legal contexts, the standard Hungarian UI term is "Alapértelmezett" (already used at Line 140). The same issue exists at Line 273 (options.default) and Line 563 (spacingDefaultLabel).
Proposed fix
-  "fontSize": "Betűkészlet",
-  "fontSizeDefaultLabel": "Mulasztás",
+  "fontSize": "Betűméret",
+  "fontSizeDefaultLabel": "Alapértelmezett",
packages/visual-editor/locales/platform/hu/visual-editor.json-124-124 (1)

124-124: ⚠️ Potential issue | 🟡 Minor

Change "Video" to "video" to match the camelCase/lowercase convention.

All other single-word component keys in this section use lowercase (address, phone, team, testimonial, timestamp), while compound keys use camelCase (aboutSection, videoSection). "Video" is the only single-word key using PascalCase and should be lowercase "video" for consistency.

packages/visual-editor/locales/platform/lv/visual-editor.json-205-205 (1)

205-205: ⚠️ Potential issue | 🟡 Minor

Use imperative verb form for "expandFooter".

Per the established Latvian translation convention, UI action labels should use the imperative form to match the English intent. "Paplašināt kājeni" is the infinitive; the imperative would be "Paplašiniet kājeni". Based on learnings, in Latvian translations for the visual editor, prefer imperative verb forms that align with the English UI (e.g., use 'Aizpildiet konteineru' for 'Fill Container').

Proposed fix
-    "expandFooter": "Paplašināt kājeni",
+    "expandFooter": "Paplašiniet kājeni",
packages/visual-editor/locales/platform/hr/visual-editor.json-124-125 (1)

124-125: ⚠️ Potential issue | 🟡 Minor

Inconsistent key casing: "Video" should be "video".

All sibling keys under components use camelCase (directoryGrid, bodyText, videoSection, etc.), but this key starts with an uppercase V. If the code references components.video (lowercase), the translation will silently miss.

Proposed fix
-    "Video": "Video",
+    "video": "Video",
packages/visual-editor/locales/platform/hr/visual-editor.json-644-646 (1)

644-646: ⚠️ Potential issue | 🟡 Minor

Inconsistent word and incorrect _few form for totalReviews.

Two issues:

  1. Word mismatch: _one uses "pregled" while _few/_other use "recenzija" — these should use the same word across all plural forms.
  2. _few grammar: if using "recenzija" (feminine), counts 2–4 require "recenzije", not "recenzija".
Proposed fix (using "recenzija" consistently)
-  "totalReviews_one": "{{count}} pregled",
-  "totalReviews_few": "{{count}} recenzija",
+  "totalReviews_one": "{{count}} recenzija",
+  "totalReviews_few": "{{count}} recenzije",
   "totalReviews_other": "{{count}} recenzija",
packages/visual-editor/locales/platform/hr/visual-editor.json-477-485 (1)

477-485: ⚠️ Potential issue | 🟡 Minor

Croatian _few plural for "lokacija" should be "lokacije".

For feminine noun "lokacija", counts 2–4 require the nominative plural "lokacije". All three _few entries currently duplicate the _other form ("lokacija"), producing incorrect grammar for counts like 2, 3, 4.

Affected keys: locationsNear_few (Line 478), locationsWithinDistanceOf_few (Line 481), locationWithCount_few (Line 484).

Proposed fix
-  "locationsNear_few": "{{count}} lokacija u blizini \"{{name}}\"",
+  "locationsNear_few": "{{count}} lokacije u blizini \"{{name}}\"",
-  "locationsWithinDistanceOf_few": "{{count}} lokacija unutar {{distance}} {{unit}} od \"{{name}}\"",
+  "locationsWithinDistanceOf_few": "{{count}} lokacije unutar {{distance}} {{unit}} od \"{{name}}\"",
-  "locationWithCount_few": "{{count}} lokacija",
+  "locationWithCount_few": "{{count}} lokacije",
packages/visual-editor/scripts/generateTranslations.ts-356-358 (1)

356-358: ⚠️ Potential issue | 🟡 Minor

Inconsistent log prefix — type is missing from the error log.

Success logs on Line 354 use [${type}/${locale}] but the error log on Line 358 uses [${locale}].

Suggested fix
-          console.error(`[${locale}] Failed to translate key "${key}":`, error);
+          console.error(`[${type}/${locale}] Failed to translate key "${key}":`, error);
packages/visual-editor/scripts/generateTranslations.ts-185-187 (1)

185-187: ⚠️ Potential issue | 🟡 Minor

Context markers may survive in translated output if the MT engine alters them.

Google Translate can transliterate or translate the [[context: …]] marker (e.g., [[contexto: dirección]] in Spanish, or bracket substitution in CJK languages). The current regex requires the literal word context and ASCII ]], so mangled markers will leak into the final translation string.

Consider using a more robust sentinel (e.g., an XML-like tag <x-ctx>…</x-ctx> which MT engines tend to pass through) or validate post-translation that no residual markers remain:

💡 Quick fallback: warn when removal is a no-op
 const removeEmbeddedContext = (text: string): string => {
-  return text.replace(/\s*\[\[\s*context:\s*[\s\S]*?\]\]/gi, "").trim();
+  const cleaned = text.replace(/\s*\[\[\s*context:\s*[\s\S]*?\]\]/gi, "").trim();
+  // Warn if markers may have been mangled by MT
+  if (cleaned.includes("[[") || cleaned.includes("]]")) {
+    console.warn(`Possible residual context marker in: "${cleaned}"`);
+  }
+  return cleaned;
 };
packages/visual-editor/locales/platform/it/visual-editor.json-462-463 (1)

462-463: ⚠️ Potential issue | 🟡 Minor

_many plural keys are unused for Italian cardinal plurals.

Italian CLDR rules define cardinal plural categories as one and other only. The _many category applies exclusively to ordinal plurals (for numbers 8, 11, 80, 800) and is not relevant in cardinal contexts. These keys—kilometer_many, locationsNear_many, locationsWithinDistanceOf_many, locationWithCount_many, mile_many, and totalReviews_many—will never be selected by i18next's plural resolver for the it locale and represent dead translations.

🧹 Nitpick comments (17)
packages/visual-editor/locales/components/ja/visual-editor.json (1)

20-24: Minor katakana spacing inconsistency.

Line 22 uses a half-width space in "ユーティリティ イメージ", while other compound katakana terms elsewhere in this file are written without spaces (e.g., "ヒーローバナー", "ヒーローヘッダー", "フォトギャラリーセクション"). Consider removing the space for consistency.

🌐 Proposed fix
-      "defaultAlt": "ユーティリティ イメージ {{number}}"
+      "defaultAlt": "ユーティリティイメージ {{number}}"
packages/visual-editor/locales/components/pt/visual-editor.json (1)

38-38: _many plural forms are unused for Portuguese.

Portuguese CLDR plural rules only define one and other categories — the _many form is never selected at runtime by i18next. These keys are harmless but effectively dead code. If the new i18next-cli tooling is auto-generating them, it may be worth configuring it to skip _many for Romance languages to keep locale files lean.

Also applies to: 43-43, 46-46, 49-49, 54-54, 96-96

packages/visual-editor/locales/components/es/visual-editor.json (1)

38-40: _many plural form is unused in Spanish.

Per CLDR plural rules, Spanish only uses one and other categories — there is no many category. Keys like kilometer_many, locationWithCount_many, mile_many, and totalReviews_many will never be selected by i18next for the es locale. They are harmless but add dead entries. If these were auto-generated by the new i18next-cli tooling across all locales, this is understandable, but worth being aware of.

Also applies to: 43-45, 54-56, 96-98

packages/visual-editor/locales/components/lt/visual-editor.json (1)

70-73: Minor translation inconsistencies in "promo" keys.

  • promoBanner: "Reklaminė reklamjuostė" is somewhat redundant ("promotional ad-banner").
  • promoMedia: "Promo žiniasklaida" mixes the untranslated English loanword "Promo" with Lithuanian, while promoBanner uses a fully Lithuanian translation.

Consider aligning both — e.g., "Reklaminė medžiaga" or "Reklaminė žiniasklaida" for promoMedia, and simplifying promoBanner to "Reklamjuostė" to avoid redundancy.

packages/visual-editor/locales/components/lv/visual-editor.json (1)

25-25: Verify coreInfoSection translation.

"Pamatinformācija" means "basic information" — which is a reasonable rendering of "core info." Just noting that other *Section keys include the word "sadaļa" (section) in their value (e.g., "Stundu sadaļa", "Informācijas sadaļa"). If this key is meant to label a section header consistently with those, consider "Pamatinformācijas sadaļa".

packages/visual-editor/locales/platform/fi/visual-editor.json (1)

238-243: Finnish grammar: "Linkki kohde" should be a compound or genitive form.

Line 243 correctly uses a compound word ("Linkkityyppi"), and Line 238 correctly uses the genitive ("Linkin etiketti"). Line 242's "Linkki kohde" (two bare nouns) is not grammatical Finnish — it should be "Linkkikohde" (compound) or "Linkin kohde" (genitive) to match the pattern.

Proposed fix
- "linkTarget": "Linkki kohde",
+ "linkTarget": "Linkin kohde",
packages/visual-editor/locales/components/fi/visual-editor.json (2)

61-61: Inconsistent "section" suffix across keys.

photoGallerySection uses "osa" (part) — "Valokuvagalleriaosa" — while other section keys like hoursSection ("Tuntien osio") and the corrected servicesSection / coreInfoSection use "osio". Consider using "osio" consistently: "Valokuvagalleria-osio".


1-97: Consider a native-speaker review pass on machine-translated strings.

Multiple translations in this file exhibit patterns typical of automated translation (literal translations, incorrect compound words, semantic drift). The informationSection → "Tiedonsiirto" error is the most critical, but several others (breadcrumb, servicesSection, promoMedia, coreInfoSection spacing) also need correction. If these translations were generated via the new Google Translate integration, a native Finnish speaker review pass would catch these before they reach users.

packages/visual-editor/locales/platform/da/visual-editor.json (1)

322-323: Inconsistent capitalization: "Timer Status" vs "Timer tabel".

Danish doesn't use title case — only the first word is capitalized. Line 323 is correct ("Timer tabel"), but line 322 should follow the same convention.

Proposed fix
-      "hoursStatus": "Timer Status",
+      "hoursStatus": "Timer status",
packages/visual-editor/locales/platform/es/visual-editor.json (1)

462-462: _many plural forms are unused for Spanish.

Spanish (per CLDR/Unicode) only has two plural categories: one and other. i18next will never resolve the _many key for the es locale. These entries at lines 462, 478, 481, 484, 490, and 645 are dead weight. If the new i18next-cli is auto-generating them, consider configuring it to only emit plural forms relevant to the target language.

Also applies to: 478-478, 481-481, 483-485, 490-490, 645-645

packages/visual-editor/locales/platform/tr/visual-editor.json (1)

238-243: Minor casing inconsistency across sibling field translations.

linkLabel → "Bağlantı Etiketi", linkTarget → "Bağlantı Hedefi" (both title-cased), but linkType → "Bağlantı türü" (lowercase). Consider aligning to the same convention.

Proposed fix (align to title case)
-    "linkType": "Bağlantı türü",
+    "linkType": "Bağlantı Türü",
packages/visual-editor/locales/platform/ja/visual-editor.json (1)

28-28: Breadcrumb translation corrected to proper UI term.

パンくずリスト is the correct Japanese term for breadcrumb navigation. However, note that on line 60 (unchanged), components.breadcrumbs is still "パン粉" — which literally means "panko" (food breadcrumbs), not a navigation breadcrumb. Consider updating that value in a follow-up to maintain consistency.

packages/visual-editor/locales/platform/en-GB/visual-editor.json (1)

124-124: Same PascalCase "Video" inconsistency as in the sv locale.

This is the root source locale — the key here propagates to all other platform locale files. Renaming to "video" here will need a corresponding update to any code referencing components.Video and to the propagation/extraction config so this doesn't resurface.

Proposed fix
-    "Video": "Video",
+    "video": "Video",
packages/visual-editor/locales/platform/sv/visual-editor.json (1)

124-124: "Video" is PascalCase while all other keys in the components section use camelCase.

The inconsistency is confirmed: every sibling key uses camelCase (directoryGrid, hoursStatus, videoSection, etc.). For consistency with the rest of the components section, rename this to "video".

Note: A search of the codebase found no references to this key, so it may be unused or orphaned. Renaming will not break existing code, but consider whether it should be retained at all.

Proposed fix
-    "Video": "Video",
+    "video": "Video",
packages/visual-editor/locales/platform/lv/visual-editor.json (1)

1-656: Several other translations appear to be machine-generated with semantic errors.

A few examples beyond the changed lines (but worth a pass during this tooling migration):

  • Line 44: "close": "Tuvs" — "Tuvs" means "near" (proximity), not "close" (to shut). Should be "Aizvērt".
  • Line 47: "closeMenu": "Aizvērt ēdienkarti" — "ēdienkarte" means "food menu", not a navigation menu. Should be "Aizvērt izvēlni".
  • Line 503: "openMenu": "Atvērta ēdienkarte" — same "food menu" issue.
  • Line 635: "uppercase": "Lielie cilvēki" — "Big people" instead of "Lielie burti" (uppercase letters).

These aren't on changed lines so they may pre-date this PR, but since the PR is swapping i18n tooling and touching this file, it may be a good opportunity to run a quality check on the Latvian translations.

packages/visual-editor/scripts/generateTranslations.ts (1)

241-266: No timeout or retry logic on translation requests.

fetch has no timeout, so a hanging request will block the script indefinitely. Additionally, there's no retry for transient network/API failures — a single 429 or 5xx will permanently skip that key.

Consider adding an AbortSignal.timeout() and a simple retry with backoff:

💡 Suggested improvement
 const translateText = async (
   text: string,
-  targetLang: string
+  targetLang: string,
+  retries = 2
 ): Promise<string> => {
   const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${DEFAULT_LANGUAGE}&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}`;
-  const response = await fetch(url);
+  const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
 
   if (!response.ok) {
+    if (retries > 0 && (response.status === 429 || response.status >= 500)) {
+      await new Promise((r) => setTimeout(r, 1000 * (3 - retries)));
+      return translateText(text, targetLang, retries - 1);
+    }
     throw new Error(
       `Google Translate API error: ${response.status} for text: "${text}"`
     );
   }

Also note that translate.googleapis.com with client=gtx is an unofficial, undocumented API that may be rate-limited or discontinued without notice. If this script is part of CI or runs frequently, consider switching to the official Cloud Translation API.

packages/visual-editor/locales/platform/pt/visual-editor.json (1)

462-462: Remove unnecessary _many plural forms from Portuguese locale — they are never used by CLDR rules.

Portuguese only has two CLDR plural categories: one (for 0 and 1) and other (for all other values). The many category does not exist for Portuguese. These keys will never be resolved at runtime, even though i18next silently ignores them.

While not a functional issue, they add noise to the locale file and can confuse translators. Consider checking if the i18next-cli extraction tooling is unconditionally emitting _many forms for all languages regardless of CLDR support.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/components/fi/visual-editor.json`:
- Line 63: The translation for the locale key promoMedia currently reads
"Promootio" which omits the "media" meaning; update the value for promoMedia in
the visual-editor JSON to a Finnish string that includes media (e.g.,
"Promootiomedia" or "Markkinointimedia") so the key accurately reflects
promotional media content; ensure you only change the RHS string for the
promoMedia key and keep JSON formatting intact.
- Line 9: Replace the incorrect Finnish string value for the "breadcrumb" key in
the visual editor locale (packages/visual-editor locales file) from "Leivänmuru"
to the established UI term "Murupolku"; also update the same "breadcrumb" key in
the platform locale file where the same incorrect value appears so both locale
entries use "Murupolku" consistently.

In `@packages/visual-editor/locales/components/fr/visual-editor.json`:
- Around line 49-51: The three plural keys locationsWithinDistanceOf_many,
locationsWithinDistanceOf_one and locationsWithinDistanceOf_other use
inconsistent quoting and wording; update all three to the same French phrasing
and quote style (for example: use guillemets « {{name}} » consistently) and
standardize the preposition/phrase (e.g. "{{count}} emplacement(s) à
{{distance}} {{unit}} de « {{name}} »" or "{{count}} emplacements dans un rayon
de {{distance}} {{unit}} de « {{name}} »") so the displayed message is identical
across plural forms.

In `@packages/visual-editor/locales/components/hr/visual-editor.json`:
- Around line 35-37: Update the Croatian translations for the keys "hours",
"hoursSection", and "informationSection": replace the nominative form for
"hours" from "Sate" to "Sati", and make the two section labels unambiguous by
changing "hoursSection" to "Odjeljak radnog vremena" and "informationSection" to
"Odjeljak s informacijama" so each key clearly matches its English meaning.
- Line 9: Replace the incorrect Croatian translation value for the "breadcrumb"
key in visual-editor.json: change "Krušnica" to the correct standard term
"Krušne mrvice" (or the exact string used elsewhere in the codebase for the
component label) so the breadcrumb label is consistent and accurate across
locales.

In `@packages/visual-editor/locales/platform/fi/visual-editor.json`:
- Line 242: The Finnish translation for the JSON key "linkTarget" is
grammatically incorrect; replace the value "Linkki kohde" with a correct form
(use the compound "Linkkikohde" to match the style of "Linkkityyppi") so the
"linkTarget" entry reads the proper Finnish compound word.
- Line 446: The Finnish translation uses "Laiminlyönti" incorrectly for default
settings; update the keys fontSizeDefaultLabel and spacingDefaultLabel to use
"Oletus" instead of "Laiminlyönti", and fix the options.default entry (the JSON
key "default") to "Oletus" as well so all default-setting labels use the correct
Finnish word; locate the entries by their JSON keys (fontSizeDefaultLabel,
spacingDefaultLabel, options.default) and replace the value string with
"Oletus".
- Line 124: The "Video" JSON key uses PascalCase while sibling keys use
camelCase; rename the "Video" key to camelCase (e.g., "video") in this file and
the corresponding English locale so it matches siblings like "videoSection",
"aboutSection", and "address", and update any code references that read the old
"Video" key (search for "Video" in the codebase) to use the new "video" key.

In `@packages/visual-editor/locales/platform/fr/visual-editor.json`:
- Around line 478-482: The translations for the plural key
locationsWithinDistanceOf_many are inconsistent: replace the French guillemets
and the phrasing so it matches the other variants (locationsWithinDistanceOf_one
and locationsWithinDistanceOf_other); specifically, change
locationsWithinDistanceOf_many to use escaped double quotes around {{name}}
(\"{{name}}\") and include the phrase "dans un rayon de {{distance}} {{unit}}
de" so all plural forms use the same wording and quoting style.
- Line 124: The "Video" key in the components object is using PascalCase while
its siblings use camelCase; rename the key "Video" to "video" in the components
object (e.g., in packages/visual-editor/locales/platform/fr/visual-editor.json)
and mirror the same change across the other locale files where the PascalCase
copy exists so the localization keys are consistently camelCase; verify and
update any code or tests that reference the old "Video" key to use "video".

In `@packages/visual-editor/locales/platform/hr/visual-editor.json`:
- Line 462: The locale entry for the key "kilometer_few" is incorrect: replace
its value "kilometara" with the correct Croatian few-form "kilometra" (so
"kilometer_few" = "kilometra") and ensure the _few form now differs from the
genitive plural used in "kilometer_other"/"_other" to match the components file
fix.
- Around line 322-323: The translation for components.hoursTable is inconsistent
and grammatically incorrect ("Sate stol"); update the components.hoursTable
entry to match the correct and consistent translation used by options.hoursTable
("Tablica sati") so both keys (components.hoursTable and options.hoursTable) use
the same phrase and correct grammar.
🧹 Nitpick comments (3)
packages/visual-editor/locales/platform/it/visual-editor.json (1)

462-463: _many plural keys are unused for Italian locale.

Italian's CLDR plural rules only define one and other categories — there is no many category. Keys like kilometer_many, locationsNear_many, locationsWithinDistanceOf_many, locationWithCount_many, mile_many, and totalReviews_many will never be selected by i18next for the it locale. These are likely artifacts of the new i18next-cli extraction/propagation tooling.

Not a bug (they're silently ignored), but they add noise to the locale file. Consider whether the propagation script should be locale-aware for plural categories.

Also applies to: 478-479, 481-482, 483-485, 490-491, 645-646

packages/visual-editor/locales/platform/hr/visual-editor.json (2)

242-242: linkTarget now translated — minor style note.

The past-review concern about this value being English is resolved. The neighboring keys follow a "<noun> veze" pattern ("linkLabel": "Oznaka veze", "linkType": "Vrsta veze"), while linkTarget is just "Odredište". For consistency, "Odredište veze" would align better, but this is a nitpick.


124-124: Update the translation key from "Video" to "video" to match camelCase convention.

The "Video" key is explicitly defined in the Video component (src/components/contentBlocks/Video.tsx, line 53) with uppercase casing, which breaks the camelCase naming convention used throughout the components section (e.g., videoSection, directoryGrid, heroImage, gallery, footer). Change "components.Video" to "components.video" in the component configuration and update all locale files accordingly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/platform/de/visual-editor.json`:
- Line 211: The translation for the key footerSocialIcons uses "Ikonen" which is
uncommon in German UI; update the value for footerSocialIcons to use the more
appropriate term "Symbole" (e.g., "Footer soziale Symbole") or "Icons" to match
UI terminology and be consistent with the other key named icons.
- Line 96: The translation for components.hoursTable ("Geschäftszeiten") is
inconsistent with fields.options.hoursTable ("Stundentabelle"); update
fields.options.hoursTable to match components.hoursTable by replacing
"Stundentabelle" with "Geschäftszeiten" (or intentionally choose a different
term if the UI context requires a distinction), ensuring both keys
(components.hoursTable and fields.options.hoursTable) use the same German string
for consistency.
🧹 Nitpick comments (3)
packages/visual-editor/scripts/checkInterpolationVariables.ts (3)

122-132: Static analysis ReDoS warning — low risk here but worth a minor hardening.

The leafKey is derived from translation JSON keys (not arbitrary user input), and escapeRegex neutralises special characters, so the practical ReDoS risk is negligible. Still, since findLineNumberForKey is only used for diagnostic line numbers, a simple indexOf-based approach would sidestep the concern entirely and be slightly simpler.

♻️ Suggested simplification
 const findLineNumberForKey = (fileContent: string, key: string): number => {
   const leafKey = key.split(".").pop() ?? key;
-  const keyPattern = new RegExp(`"${escapeRegex(leafKey)}"\\s*:`, "g");
-  const match = keyPattern.exec(fileContent);
-
-  if (!match) {
+  const needle = `"${leafKey}"`;
+  const idx = fileContent.indexOf(needle);
+  if (idx === -1) {
     return 1;
   }
-
-  return fileContent.slice(0, match.index).split("\n").length;
+  return fileContent.slice(0, idx).split("\n").length;
 };

This trades the strict \s*: suffix match for a simpler substring lookup, which is fine for a best-effort line hint. If you need the colon check, the current code is acceptable given the controlled input.


193-200: Potential undefined access after array guards — add non-null assertions or destructure.

unexpectedIndexes[0] and missing[0] are typed as potentially undefined in strict TypeScript, even though the length-1 guard at lines 172 and 189 makes them safe at runtime. Downstream usage on lines 199–200 (actualExpressions[targetIndex], replacementVariable) would propagate undefined silently if the invariant were ever broken.

♻️ Suggested hardening
-  const targetIndex = unexpectedIndexes[0];
-  const replacementVariable = missing[0];
+  const targetIndex = unexpectedIndexes[0]!;
+  const replacementVariable = missing[0]!;

Or use a runtime assertion:

const targetIndex = unexpectedIndexes[0];
const replacementVariable = missing[0];
if (targetIndex === undefined || replacementVariable === undefined) {
  return null; // defensive: shouldn't happen given prior guards
}

255-258: English locale is validated against itself — skip it to avoid wasted I/O.

getSubdirectoryNames(instanceDir) returns all locale subdirectories including "en". The comparison will always yield mismatchCount === 0 for English vs. English, so it's harmless, but it reads and parses the file unnecessarily and makes the intent less clear.

Also, the locale file is read twice: once as raw text (line 257) and once parsed via loadJsonSafe (line 258). You could avoid the duplicate I/O by parsing the raw content directly.

♻️ Suggested changes
+  const locales = (await getSubdirectoryNames(instanceDir)).filter(
+    (l) => l !== PRIMARY_LOCALE
+  );
-  const locales = await getSubdirectoryNames(instanceDir);

To deduplicate the file read:

     const localeRaw = await fs.readFile(localePath, "utf-8").catch(() => "");
-    const localeFlat = flatten(await loadJsonSafe(localePath));
+    const localeFlat = flatten(
+      localeRaw ? JSON.parse(localeRaw) : {}
+    );

(Adjust error handling to taste — loadJsonSafe may have additional safety you want to preserve.)

benlife5
benlife5 previously approved these changes Feb 9, 2026
jwartofsky-yext
jwartofsky-yext previously approved these changes Feb 9, 2026
briantstephan
briantstephan previously approved these changes Feb 12, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/visual-editor/locales/platform/ro/visual-editor.json (1)

92-92: ⚠️ Potential issue | 🟡 Minor

"headingText" is mistranslated as "Text de îndreptare" (text of straightening/correction).

This should be "Text de titlu" or "Text de rubrică" to match the heading/title context used elsewhere in the file.

Proposed fix
-    "headingText": "Text de îndreptare",
+    "headingText": "Text de titlu",
packages/visual-editor/locales/platform/es/visual-editor.json (1)

80-80: ⚠️ Potential issue | 🟡 Minor

Pre-existing: "Campo de golf" (golf course) for "Links" is a machine-translation error.

This appears on lines 80, 250, and 654. "Links" (hyperlinks) was mistranslated as "links" (golf). The correct translation is "Enlaces" (which is already correctly used elsewhere, e.g., line 76 "expandedLinks": "Enlaces ampliados"). While not introduced by this PR, these will confuse Spanish-speaking users.

Also applies to: 250-250

packages/visual-editor/locales/platform/pl/visual-editor.json (1)

28-28: ⚠️ Potential issue | 🟡 Minor

Typo: "Breatcrumb" → "Breadcrumb"

This key (and "breadcrumbs" on line 60) contains Breatcrumb instead of Breadcrumb. While these are unchanged lines, the misspelling is present in the committed file.

🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/components/es/visual-editor.json`:
- Around line 47-49: The three keys locationsNear_many, locationsNear_one, and
locationsNear_other have inconsistent word order for the count; update
locationsNear_many to use the same ordering as locationsNear_one/_other (place
the {{count}} before the noun and keep the rest of the phrase identical) so all
plural forms produce consistent output, making sure to preserve the quoted
\"{{name}}\" placeholder and appropriate plural wording for Spanish.

In `@packages/visual-editor/locales/platform/de/visual-editor.json`:
- Line 23: The translation for key ariaLabelGooglePlay is missing a space
between the interpolation and the word "herunterladen", causing concatenated
text like "Google Playherunterladen"; update the value for ariaLabelGooglePlay
to insert a space after the {{serviceName}} interpolation so it reads correctly
(i.e., ensure there is a space between {{serviceName}} and herunterladen).

In `@packages/visual-editor/locales/platform/fr/visual-editor.json`:
- Line 684: The translation value for the JSON key "videoThumbnail" is corrupted
("Vide-gigantes"); update the value for the "videoThumbnail" key to the correct
French translation "Miniature vidéo" in the visual-editor locale JSON so the UI
shows a proper French label for video thumbnails.
🟡 Minor comments (57)
packages/visual-editor/locales/components/tr/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

"Ekmek kırıntısı" is a literal food translation of "breadcrumb" — consider using a standard Turkish UI/navigation term.

In Turkish UI/UX, breadcrumb navigation is commonly referred to as "İçerik haritası" (content map) or simply kept as "Breadcrumb". "Ekmek kırıntısı" literally means a bread crumb (the food), which may confuse users expecting standard navigation terminology. Please verify with your localization team.

packages/visual-editor/locales/components/lt/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Likely mistranslation: "komprumbas" is not a valid Lithuanian word.

"Duonos komprumbas" does not appear to be correct Lithuanian. The word "komprumbas" doesn't exist in the language. For a navigation breadcrumb, a common Lithuanian translation would be "Naršymo kelias" (navigation path) or the literal "Duonos trupiniai." Please verify with a native speaker or translation service.

packages/visual-editor/locales/components/cs/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

"Strouha" appears to be a mistranslation for navigation breadcrumb.

"Strouha" refers to a literal food breadcrumb/crumb in Czech. The standard Czech term for UI breadcrumb navigation is "Drobečková navigace" (or simply "Navigace"). Since this key is used for a navigation component, the translation should reflect the UI concept, not the literal food meaning.

Proposed fix
-  "breadcrumb": "Strouha",
+  "breadcrumb": "Drobečková navigace",
packages/visual-editor/locales/components/nb/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Spurious space before the hyphen in coreInfoSection.

"Kjerneinfo -seksjon" has an extra space before the hyphen. It should be "Kjerneinfo-seksjon" (or "Kjerneinformasjonsseksjon" as a single compound word).

Proposed fix
-  "coreInfoSection": "Kjerneinfo -seksjon",
+  "coreInfoSection": "Kjerneinfo-seksjon",
packages/visual-editor/locales/components/nb/visual-editor.json-79-80 (1)

79-80: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation: services vs servicesSection.

Line 79 translates "services" as the Norwegian "Tjenester", but line 80 uses the English loanword in "Serviceseksjonen". For consistency, consider "Tjenesteseksjonen".

Proposed fix
-  "servicesSection": "Serviceseksjonen",
+  "servicesSection": "Tjenesteseksjonen",
packages/visual-editor/locales/components/nl/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Spurious space before the hyphen in coreInfoSection.

"Core Info -sectie" has an extra space before the hyphen. This looks like a translation/extraction artifact. It should likely be "Core Info-sectie".

-  "coreInfoSection": "Core Info -sectie",
+  "coreInfoSection": "Core Info-sectie",
packages/visual-editor/locales/components/sk/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Identical translations for distinct section keys may hurt accessibility.

coreInfoSection, informationSection, and servicesSection all translate to the generic "Sekcia" ("Section"). If these are used as ARIA labels or screen-reader-visible headings, users won't be able to distinguish between them. Consider adding more descriptive translations (e.g., "Sekcia základných informácií", "Sekcia informácií", "Sekcia služieb").

Also applies to: 38-38, 90-90

packages/visual-editor/locales/components/et/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

"Riivsaia" is a literal (food) translation of "breadcrumb", not the UI navigation concept.

"Riivsaia" means grated bread/breadcrumbs (the food item) in Estonian. For a navigation breadcrumb component, this should use the appropriate UI term — typically something like "Lingirada" (link trail) or a term aligned with Estonian web UI conventions. Please verify with a native speaker or your localization team.

packages/visual-editor/locales/components/es/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Incorrect translation for "breadcrumb" in navigation context.

"Migaja de pan" is a literal translation meaning a physical crumb of bread. For UI navigation breadcrumbs, the standard Spanish translation is "Ruta de navegación" or "Migas de pan" (plural).

Proposed fix
-  "breadcrumb": "Migaja de pan",
+  "breadcrumb": "Ruta de navegación",
packages/visual-editor/locales/components/es/visual-editor.json-100-102 (1)

100-102: ⚠️ Potential issue | 🟡 Minor

Inconsistent terminology: totalReviews_many uses "opiniones" while totalReviews_other uses "reseñas".

Both plural forms should use the same word for "reviews" to avoid confusing output. "Reseñas" is more standard for reviews in this context.

Proposed fix
-  "totalReviews_many": "{{count}} opiniones",
+  "totalReviews_many": "{{count}} reseñas",
packages/visual-editor/locales/components/da/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Minor: Unusual spacing in translated string.

"Kerneinfo -sektion" has a space before the hyphen, which looks like a machine-translation artifact. The same pattern exists in pre-existing strings (e.g., Line 15 "Luk header -menu", Line 56 "Åben header -menu"), so this isn't a regression — but it may be worth a follow-up pass to clean up these spacing quirks across all locales if they aren't intentional.

packages/visual-editor/locales/components/sv/visual-editor.json-36-37 (1)

36-37: ⚠️ Potential issue | 🟡 Minor

Several translations appear to be low-quality machine translations — worth a native review pass.

A few examples in the added keys:

  • Line 36: "hours": "Timme" — "Timme" is singular ("hour"). For a section label referring to business hours, "Öppettider" is idiomatic Swedish; at minimum the plural "Timmar" would be more appropriate.
  • Line 37: "hoursSection": "Timmarssektion" — awkward compound; "Öppettidssektion" or similar would be more natural.
  • Line 66: "promoMedia": "Promo media" — left untranslated/anglicism; may be intentional but inconsistent with other translated keys.
  • Line 80: "servicesSection": "Serviceavdelning" — uses "avdelning" (department), while other section keys use "sektion" (line 37) or "avsnitt" (lines 38, 62), creating inconsistency.

If these translations are auto-generated by i18next-cli, consider having a native speaker review the output across all locales.

Also applies to: 61-62, 65-66, 79-80

packages/visual-editor/locales/components/sv/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Typo: "Brödsmum" is not a valid Swedish word.

The Swedish word for "breadcrumb" is "brödsmula" (singular) or "brödsmulor" (plural). "Brödsmum" appears to be a machine-translation error.

Proposed fix
-  "breadcrumb": "Brödsmum",
+  "breadcrumb": "Brödsmula",
packages/visual-editor/locales/components/lv/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

"Rīvmaize" is a literal (food) translation of "breadcrumb", not the UI navigation concept.

"Rīvmaize" means grated bread / breadcrumbs (the food). For the UI navigation element, a more appropriate Latvian translation would be something like "Navigācijas ceļš" (navigation path) or simply the transliterated term. This likely came from machine translation.

packages/visual-editor/locales/components/ja/visual-editor.json-76-77 (1)

76-77: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation of "secondary" between these two keys.

secondaryHeaderLinks uses katakana "セカンダリ" while secondaryHeaderLinksMenu uses native Japanese "二次". The primary pair (lines 63–64) is consistent ("プライマリ" in both), so this pair should follow the same pattern.

🌐 Proposed fix
   "secondaryHeaderLinks": "セカンダリヘッダーリンク",
-  "secondaryHeaderLinksMenu": "二次ヘッダー リンク (メニュー)",
+  "secondaryHeaderLinksMenu": "セカンダリヘッダーリンク (メニュー)",
packages/visual-editor/locales/components/zh/visual-editor.json-45-46 (1)

45-46: ⚠️ Potential issue | 🟡 Minor

Inconsistent wording between _one and _other plural forms.

Chinese doesn't have grammatical plurals, so locationsNear_one and locationsNear_other should normally have identical text. However, _one uses "位置" while _other uses "地点". All other plural pairs in this file consistently use "位置". This looks like an oversight—consider aligning them.

Proposed fix
-  "locationsNear_other": ""{{name}}"附近有 {{count}} 个地点",
+  "locationsNear_other": ""{{name}}"附近有 {{count}} 个位置",
packages/visual-editor/locales/components/pl/visual-editor.json-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Typo: "Breatcrumb" → "Breadcrumb"

Missing the letter 'd'. This is user-facing text.

Proposed fix
-  "breadcrumb": "Breatcrumb",
+  "breadcrumb": "Breadcrumb",
packages/visual-editor/locales/components/pl/visual-editor.json-86-87 (1)

86-87: ⚠️ Potential issue | 🟡 Minor

Inconsistent terminology: "linki" vs "łącza"

secondaryHeaderLinks uses "linki nagłówkowe" but secondaryHeaderLinksMenu uses "łącza nagłówkowe". The primary header equivalents on lines 73–74 consistently use "linki". This should be consistent.

Proposed fix
   "secondaryHeaderLinks": "Dodatkowe linki nagłówkowe",
-  "secondaryHeaderLinksMenu": "Dodatkowe łącza nagłówkowe (menu)",
+  "secondaryHeaderLinksMenu": "Dodatkowe linki nagłówkowe (menu)",
packages/visual-editor/locales/platform/nb/visual-editor.json-249-254 (1)

249-254: ⚠️ Potential issue | 🟡 Minor

Inconsistent Norwegian translation for linkTarget.

Line 253 uses the English-rooted prefix "Link" in "Linkmål", while the adjacent keys use the Norwegian "Kobling" prefix — linkLabel → "Koblingsetikett" (line 249) and linkType → "Koblingstype" (line 254). For consistency, this should also use "Kobling".

Proposed fix
-    "linkTarget": "Linkmål",
+    "linkTarget": "Koblingsmål",
packages/visual-editor/locales/platform/lt/visual-editor.json-253-253 (1)

253-253: ⚠️ Potential issue | 🟡 Minor

Grammatically incorrect Lithuanian: use genitive case.

"Nuoroda Tikslas" has the same issue — two nominative nouns side by side. It should be "Nuorodos tikslas" (genitive of "Nuoroda" + lowercase "tikslas").

Proposed fix
-    "linkTarget": "Nuoroda Tikslas",
+    "linkTarget": "Nuorodos tikslas",
packages/visual-editor/locales/platform/lt/visual-editor.json-138-138 (1)

138-138: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation of "data attribute" vs "data attributes".

Line 138 translates dataAttribute as simply "Atributas" (dropping "Data"), while Line 200 translates dataAttributes as "Duomenų atributai" ("Data attributes"). The singular form should match: "Duomenų atributas".

Proposed fix
-  "dataAttribute": "Atributas",
+  "dataAttribute": "Duomenų atributas",
packages/visual-editor/locales/platform/lt/visual-editor.json-168-168 (1)

168-168: ⚠️ Potential issue | 🟡 Minor

Grammatically incorrect Lithuanian: use genitive case.

"Atsakymas Spalva" translates literally as two separate nouns ("Answer Color") rather than a proper Lithuanian compound. It should be "Atsakymo spalva" (genitive of "Atsakymas" + lowercase "spalva") to read as "Answer's Color" / "Answer Color".

Proposed fix
-    "answerColor": "Atsakymas Spalva",
+    "answerColor": "Atsakymo spalva",
packages/visual-editor/locales/platform/zh-TW/visual-editor.json-641-641 (1)

641-641: ⚠️ Potential issue | 🟡 Minor

Mistranslation: "字體重量" means physical weight, not font weight.

The correct term in Traditional Chinese for typographic font weight is "字體粗細" (or "字重", which is already used at Line 462 for fields.weight). This should be consistent.

Proposed fix
-      "fontWeight": "字體重量"
+      "fontWeight": "字體粗細"
packages/visual-editor/locales/platform/zh-TW/visual-editor.json-272-272 (1)

272-272: ⚠️ Potential issue | 🟡 Minor

Mistranslation: "大膽" means "bold/daring" (personality), not typographic bold.

In a font/typography context, "bold" should be translated as "粗體" in Traditional Chinese. "大膽" is a common machine-translation error.

Proposed fix
-      "bold": "大膽",
+      "bold": "粗體",
packages/visual-editor/locales/components/ro/visual-editor.json-68-69 (1)

68-69: ⚠️ Potential issue | 🟡 Minor

Minor inconsistency between primary and secondary header link translations.

Line 68 uses "Linkuri antet primare" (no preposition) while Line 81 uses "Linkuri de antet secundare" (with "de"). The same discrepancy applies to the menu variants on Lines 69 and 82. These should follow the same grammatical pattern for consistency.

Proposed fix (add "de" to primary variants for consistency)
-  "primaryHeaderLinks": "Linkuri antet primare",
-  "primaryHeaderLinksMenu": "Linkuri antet primare (meniu)",
+  "primaryHeaderLinks": "Linkuri de antet primare",
+  "primaryHeaderLinksMenu": "Linkuri de antet primare (meniu)",

Also applies to: 81-82

packages/visual-editor/locales/platform/nl/visual-editor.json-215-215 (1)

215-215: ⚠️ Potential issue | 🟡 Minor

Inconsistent use of English "Footer" instead of Dutch "voettekst".

Other keys in this file consistently translate "footer" as "voettekst" (e.g., expandedFooter → "Uitgebreide voettekst", expandedFooterLinks → "Uitgebreide voettekst links"). This key mixes languages.

Proposed fix
-    "expandFooter": "Footer uitbreiden",
+    "expandFooter": "Voettekst uitbreiden",
packages/visual-editor/locales/platform/fi/visual-editor.json-168-168 (1)

168-168: ⚠️ Potential issue | 🟡 Minor

Finnish compound word: "Vastaus Väri" → "Vastausväri".

In Finnish, "answer color" should be a single compound word "Vastausväri", not two separate words with a capitalized second word. Compare with similar compounds in this file like "Taustaväri" (line 172) and "Linkkityyppi" (line 254).

Proposed fix
-    "answerColor": "Vastaus Väri",
+    "answerColor": "Vastausväri",
packages/visual-editor/locales/platform/sv/visual-editor.json-272-272 (1)

272-272: ⚠️ Potential issue | 🟡 Minor

Incorrect Swedish translation for typographic "bold".

"Djärv" means brave/daring in Swedish. The correct typographic term for bold text is "Fet".

Proposed fix
-      "bold": "Djärv",
+      "bold": "Fet",
packages/visual-editor/locales/platform/sv/visual-editor.json-138-138 (1)

138-138: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation: dataAttribute vs dataAttributes.

Line 138 translates dataAttribute as "Attribut" (dropping the "Data" prefix), while line 200 translates dataAttributes as "Dataattribut". These should be consistent.

Proposed fix
-  "dataAttribute": "Attribut",
+  "dataAttribute": "Dataattribut",
packages/visual-editor/locales/platform/pt/visual-editor.json-357-357 (1)

357-357: ⚠️ Potential issue | 🟡 Minor

Pre-existing untranslated string: right_direction is in English.

"right_direction": "Right" appears to be untranslated. Other directional terms in this file are translated (e.g., "left_direction": "Esquerda", "top_direction": "Topo", "bottom_direction": "Parte inferior"). This should likely be "Direita".

Not introduced by this PR, but worth fixing while the locale file is being reorganized.

packages/visual-editor/locales/platform/pt/visual-editor.json-513-515 (1)

513-515: ⚠️ Potential issue | 🟡 Minor

Inconsistent plural translation for locationWithCount.

locationWithCount_many (Line 514) uses "locais" while locationWithCount_other (Line 515) uses "localizações". The other plural groups in this file (locationsNear, locationsWithinDistanceOf) consistently use "locais" for both _many and _other. This should be unified.

Proposed fix
   "locationWithCount_one": "{{count}} localização",
   "locationWithCount_many": "{{count}} locais",
-  "locationWithCount_other": "{{count}} localizações",
+  "locationWithCount_other": "{{count}} locais",
packages/visual-editor/locales/platform/fr/visual-editor.json-28-28 (1)

28-28: ⚠️ Potential issue | 🟡 Minor

Good fix: breadcrumb now correctly uses "Fil d'Ariane".

This is the standard French term for navigation breadcrumbs. However, note that line 60 (components.breadcrumbs) still uses "Chapelure" (food breadcrumbs), creating an inconsistency. Consider updating line 60 as well.

Proposed fix for line 60
-    "breadcrumbs": "Chapelure",
+    "breadcrumbs": "Fil d'Ariane",
packages/visual-editor/locales/platform/tr/visual-editor.json-456-457 (1)

456-457: ⚠️ Potential issue | 🟡 Minor

value and values have identical translations.

Both keys translate to "Değer" (singular). The plural key values should likely be "Değerler".

Proposed fix
     "value": "Değer",
-    "values": "Değer",
+    "values": "Değerler",
packages/visual-editor/locales/platform/tr/visual-editor.json-510-511 (1)

510-511: ⚠️ Potential issue | 🟡 Minor

Turkish plural form after a numeral is grammatically incorrect.

In Turkish, nouns following a numeral remain singular (e.g., "5 konum", not "5 konumlar"). The _other form should match the _one form for Turkish.

Proposed fix
  "locationWithCount_one": "{{count}} Konum",
- "locationWithCount_other": "{{count}} konumlar",
+ "locationWithCount_other": "{{count}} Konum",
packages/visual-editor/locales/platform/tr/visual-editor.json-171-171 (1)

171-171: ⚠️ Potential issue | 🟡 Minor

"Aria" mistranslated as "Arya".

"ARIA" (Accessible Rich Internet Applications) is a technical accessibility term and should not be phonetically transliterated. The translation "Arya Etiketi" should be "Aria Etiketi" (or kept as "ARIA Etiketi").

Proposed fix
-    "ariaLabel": "Arya Etiketi",
+    "ariaLabel": "ARIA Etiketi",
packages/visual-editor/locales/components/de/visual-editor.json-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Missing space before "herunterladen".

Lines 6 and 7 correctly use {{serviceName}} herunterladen (with a space), but line 8 is missing the space. At runtime this will render as e.g. "Bei Google Playherunterladen".

🐛 Proposed fix
-  "ariaLabelGooglePlay": "Bei {{serviceName}}herunterladen",
+  "ariaLabelGooglePlay": "Bei {{serviceName}} herunterladen",
packages/visual-editor/locales/components/de/visual-editor.json-78-78 (1)

78-78: ⚠️ Potential issue | 🟡 Minor

German grammatical error: wrong article gender.

"Distanz" is feminine in German, so the accusative article should be "eine", not "einen" (which is masculine accusative).

🐛 Proposed fix
-  "selectDistanceLessThan": "Wähle einen Distanz kleiner als",
+  "selectDistanceLessThan": "Wähle eine Distanz kleiner als",
packages/visual-editor/locales/components/de/visual-editor.json-98-98 (1)

98-98: ⚠️ Potential issue | 🟡 Minor

German case error: accusative should be dative.

"in deine Nähe" (accusative) implies motion toward the user's vicinity. The intended meaning is a location that is near the user, which requires the dative: "in deiner Nähe".

🐛 Proposed fix
-  "useOurLocatorToFindALocationNearYou": "Nutze unseren Locator, um einen Ort in deine Nähe zu finden",
+  "useOurLocatorToFindALocationNearYou": "Nutze unseren Locator, um einen Ort in deiner Nähe zu finden",
packages/visual-editor/locales/platform/sk/visual-editor.json-462-462 (1)

462-462: ⚠️ Potential issue | 🟡 Minor

Mistranslation: "Hmotnosť" (physical mass) should be "Váha" (weight) for font context.

"Hmotnosť" refers to physical mass/weight. In the context of font styling, "Váha" is the correct Slovak term — and is already used on line 651 for theme.fontWeight.fontWeight.

Proposed fix
-  "weight": "Hmotnosť",
+  "weight": "Váha",
packages/visual-editor/locales/platform/sk/visual-editor.json-138-138 (1)

138-138: ⚠️ Potential issue | 🟡 Minor

Inconsistent translation: dataAttribute vs dataAttributes.

Line 138 translates dataAttribute as just "Atribút", while line 200 translates dataAttributes as "Atribúty údajov". The singular form should be "Atribút údajov" for consistency.

Proposed fix
-  "dataAttribute": "Atribút",
+  "dataAttribute": "Atribút údajov",
packages/visual-editor/locales/platform/da/visual-editor.json-272-272 (1)

272-272: ⚠️ Potential issue | 🟡 Minor

Incorrect Danish translation for typographic "bold".

"Dristig" means "daring/audacious" in Danish. The correct typographic term for bold text is "Fed".

🌐 Proposed fix
-      "bold": "Dristig",
+      "bold": "Fed",
packages/visual-editor/locales/platform/da/visual-editor.json-475-476 (1)

475-476: ⚠️ Potential issue | 🟡 Minor

"Misligholdelse" is the wrong sense of "default" throughout the file.

"Misligholdelse" means "default" as in failing to meet an obligation (e.g., loan default). The correct UI/settings term in Danish is "Standard". This mistranslation also appears on lines 141, 286, and 594 (spacingDefaultLabel).

🌐 Proposed fix (line 476 shown; apply the same to lines 141, 286, 594)
-  "fontSizeDefaultLabel": "Misligholdelse",
+  "fontSizeDefaultLabel": "Standard",
packages/visual-editor/locales/platform/cs/visual-editor.json-516-519 (1)

516-519: ⚠️ Potential issue | 🟡 Minor

Inconsistent Czech word for "location" across plural forms.

locationWithCount_one (Line 516) and locationWithCount_other (Line 519) use "umístění," while _few (Line 517) and _many (Line 518) use "míst." Compare with locationsWithinDistanceOf_one (Line 512) which uses "místo" instead. If these are intentional due to Czech grammar, no action needed — but worth a quick sanity check with your translators.

packages/visual-editor/locales/components/it/visual-editor.json-36-38 (1)

36-38: ⚠️ Potential issue | 🟡 Minor

"Ore sezione" is grammatically incorrect Italian and uses the wrong word for business hours.

In Italian, the modifier follows the noun: "Sezione Orari" not "Ore sezione". Additionally, "Ore" means hours as time units, whereas business hours is "Orari". The same pattern issue applies to informationSection — while passable, "Sezione informazioni" would be more natural than "Sezione di informazioni".

Proposed fix
  "hours": "Ore",
- "hoursSection": "Ore sezione",
- "informationSection": "Sezione di informazioni",
+ "hoursSection": "Sezione Orari",
+ "informationSection": "Sezione Informazioni",
packages/visual-editor/locales/components/it/visual-editor.json-44-52 (1)

44-52: ⚠️ Potential issue | 🟡 Minor

Inconsistent terminology across plural forms for location-related keys.

The _many and _other variants use different Italian words for "locations" within the same key family:

  • locationWithCount_many: "posizioni" vs _other: "località"
  • locationsNear_many: "luoghi" vs _other: "località"
  • locationsWithinDistanceOf_many: "posizioni" vs _other: "località"

Each key's plural forms should use the same term consistently. Pick one (e.g., "località" throughout) and align all variants.

Proposed fix (using "località" consistently)
- "locationWithCount_many": "{{count}} posizioni",
+ "locationWithCount_many": "{{count}} località",
  "locationWithCount_one": "{{count}} posizione",
  "locationWithCount_other": "{{count}} località",
- "locationsNear_many": "{{count}} luoghi vicino a \"{{name}}\"",
+ "locationsNear_many": "{{count}} località vicino a \"{{name}}\"",
  "locationsNear_one": "{{count}} posizione vicino a \"{{name}}\"",
  "locationsNear_other": "{{count}} località vicino a \"{{name}}\"",
- "locationsWithinDistanceOf_many": "{{count}} posizioni all'interno di {{distance}} {{unit}} di \"{{name}}\"",
+ "locationsWithinDistanceOf_many": "{{count}} località entro {{distance}} {{unit}} di \"{{name}}\"",
  "locationsWithinDistanceOf_one": "{{count}} posizione entro {{distance}} {{unit}} di \"{{name}}\"",
  "locationsWithinDistanceOf_other": "{{count}} località entro {{distance}} {{unit}} di \"{{name}}\"",

Note: locationsNear_one (line 48, unchanged) also uses "posizione" rather than the singular of "località" — consider aligning that too for full consistency.

packages/visual-editor/locales/platform/hu/visual-editor.json-243-243 (1)

243-243: ⚠️ Potential issue | 🟡 Minor

key mistranslated as "Kulcsfontosságú" (crucial/important) — should be "Kulcs" (key in a key-value context).

"Kulcsfontosságú" is the adjective meaning "crucial." In the context of data attributes (key-value pairs), the correct Hungarian term is "Kulcs".

Proposed fix
-    "key": "Kulcsfontosságú",
+    "key": "Kulcs",
packages/visual-editor/locales/platform/hu/visual-editor.json-272-272 (1)

272-272: ⚠️ Potential issue | 🟡 Minor

bold mistranslated as "Merész" (brave/daring) — should be "Félkövér" (typographic bold).

"Merész" refers to a bold personality trait. The standard Hungarian typographic term for bold text weight is "Félkövér".

Proposed fix
-      "bold": "Merész",
+      "bold": "Félkövér",
packages/visual-editor/locales/platform/hu/visual-editor.json-475-476 (1)

475-476: ⚠️ Potential issue | 🟡 Minor

fontSize mistranslated as "Betűkészlet" (font family/set) instead of "Betűméret" (font size).

"Betűkészlet" means "font set" or "font family" in Hungarian. The correct translation for "Font Size" is "Betűméret". The same issue appears in the theme section at line 639. Also, fontSizeDefaultLabel uses "Mulasztás" which means "negligence/failure" — the correct word for "Default" (as a preset value) is "Alapértelmezett" (already used correctly on line 141).

Proposed fix
-  "fontSize": "Betűkészlet",
-  "fontSizeDefaultLabel": "Mulasztás",
+  "fontSize": "Betűméret",
+  "fontSizeDefaultLabel": "Alapértelmezett",
packages/visual-editor/locales/platform/ro/visual-editor.json-168-168 (1)

168-168: ⚠️ Potential issue | 🟡 Minor

Grammatically incorrect Romanian for "answerColor".

"Răspuns Culoare" is a literal word-by-word rendering. In Romanian, this should use the genitive form.

Proposed fix
-    "answerColor": "Răspuns Culoare",
+    "answerColor": "Culoarea răspunsului",
packages/visual-editor/locales/platform/ro/visual-editor.json-272-272 (1)

272-272: ⚠️ Potential issue | 🟡 Minor

"Îndrăzneţ" means "daring/courageous", not typographic bold.

In a text-formatting context, the correct Romanian term for bold weight is "Aldin" or "Îngroșat".

Proposed fix
-      "bold": "Îndrăzneţ",
+      "bold": "Îngroșat",
packages/visual-editor/locales/platform/ro/visual-editor.json-334-335 (1)

334-335: ⚠️ Potential issue | 🟡 Minor

Inconsistency: components.hoursTable (line 96) is "Ore de masă" ("meal hours") while fields.options.hoursTable here is correctly "Tabelul orelor".

Line 96's value is a mistranslation — "Ore de masă" means "meal hours", not "hours table". It should match this correct translation.

Proposed fix for line 96
-    "hoursTable": "Ore de masă",
+    "hoursTable": "Tabelul orelor",
packages/visual-editor/locales/platform/es/visual-editor.json-272-272 (1)

272-272: ⚠️ Potential issue | 🟡 Minor

"bold" → "Atrevido" is a mistranslation for font-weight context.

"Atrevido" means "daring/bold" (personality trait). The correct Spanish term for bold font weight is "Negrita". This same type of error also appears in the German locale (line 272: "Deutlich").

Proposed fix
-      "bold": "Atrevido",
+      "bold": "Negrita",
packages/visual-editor/locales/components/fi/visual-editor.json-25-25 (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Spurious space before hyphen in "Ydintiedot -osio".

Finnish compound words with a hyphen shouldn't have a space: "Ydintiedot-osio".

Proposed fix
-  "coreInfoSection": "Ydintiedot -osio",
+  "coreInfoSection": "Ydintiedot-osio",
packages/visual-editor/locales/components/fi/visual-editor.json-80-80 (1)

80-80: ⚠️ Potential issue | 🟡 Minor

Typo: "Palvelusosasto" should be "Palveluosio" (services section).

"Palvelusosasto" contains an extra 's' and uses "osasto" (department) rather than "osio" (section), which is used consistently elsewhere in the file (e.g., line 37 "Tuntien osio", line 38 "Tieto-osio").

Proposed fix
-  "servicesSection": "Palvelusosasto",
+  "servicesSection": "Palveluosio",
packages/visual-editor/locales/platform/de/visual-editor.json-55-55 (1)

55-55: ⚠️ Potential issue | 🟡 Minor

Spurious space before hyphen in compound noun.

"Über uns- Modul" has a space between the hyphen and "Modul". In German compound nouns the hyphen attaches directly: "Über-uns-Modul" or "Über uns-Modul".

Proposed fix
-    "aboutSection": "Über uns- Modul",
+    "aboutSection": "Über uns-Modul",
packages/visual-editor/locales/platform/de/visual-editor.json-272-274 (1)

272-274: ⚠️ Potential issue | 🟡 Minor

"bold" → "Deutlich" and "button" → "Taste" are mistranslations for UI/typography context.

  • bold in font-weight context should be "Fett", not "Deutlich" (which means "clear/distinct").
  • button as a UI element type should be "Button" or "Schaltfläche", not "Taste" (which means keyboard key). Note that buttonText on line 176 already uses "Schaltflächen-" as the base.
Proposed fix
-      "bold": "Deutlich",
+      "bold": "Fett",
...
-      "button": "Taste",
+      "button": "Button",
packages/visual-editor/locales/platform/lv/visual-editor.json-475-476 (1)

475-476: ⚠️ Potential issue | 🟡 Minor

fontSizeDefaultLabel uses questionable translation "Nepildīt" for "Default".

Line 476 introduces fontSizeDefaultLabel with the value "Nepildīt", which doesn't appear to be a standard Latvian word for "Default". Note that default on line 141 correctly uses "Noklusējums". This same value ("Nepildīt") also appears on lines 286 and 599 (pre-existing), but since line 476 is newly added, it's worth aligning it with the established translation.

Proposed fix
-  "fontSizeDefaultLabel": "Nepildīt",
+  "fontSizeDefaultLabel": "Noklusējums",
🧹 Nitpick comments (6)
packages/visual-editor/locales/components/fr/visual-editor.json (1)

47-49: Minor phrasing inconsistency across locationsNear plural forms.

_one uses "près de" while _many/_other use "à proximité de". Both are valid French, but the difference means the sentence structure changes depending on count. Consider aligning all three for a consistent user experience (e.g., all using "à proximité de" or all using "près de").

packages/visual-editor/locales/components/nl/visual-editor.json (1)

36-80: Inconsistent Dutch translation style for "section" keys.

The section-related keys use varying translation patterns:

  • hoursSection"Uren sectie" (two words)
  • servicesSection"Dienstensectie" (compound)
  • informationSection"Informatiegedeelte" (compound, different suffix)
  • photoGallerySection"Sectie Fotogalerij" (reversed word order)

Dutch compound nouns are typically written as one word. Consider normalizing these (e.g., "Urensectie", "Fotogalerijsectie") for a consistent user experience. This may apply to other language files as well if they were machine-translated.

packages/visual-editor/locales/platform/hr/visual-editor.json (1)

253-254: Nit: linkTarget is less specific than neighboring keys.

linkLabel → "Oznaka veze" (lit. "Link label"), linkType → "Vrsta veze" (lit. "Link type"), but linkTarget → "Odredište" (just "Destination") rather than "Odredište veze" ("Link destination"). This is minor — "Odredište" is clear in context — but noting it for consistency if you want to align the pattern.

packages/visual-editor/locales/platform/en-GB/visual-editor.json (1)

177-177: Nit: en-GB locale uses American English "Color" spelling.

Newly added keys "cardTitleColor" (value: "Card Title Color") and "textColor" (value: "Text Color") continue the existing pattern of using "Color" rather than the British English "Colour". This is consistent within the file (existing keys like "backgroundColor", "color", "recommendedColor" all use the same spelling), so no action is strictly required—but if there's ever a sweep to correct en-GB spellings, these would be included.

Also applies to: 450-450

packages/visual-editor/locales/platform/da/visual-editor.json (1)

171-171: "Aria Label" appears to be untranslated English.

If this is intended to remain as the technical HTML attribute name, consider keeping it as-is. Otherwise it could be localized (e.g., "Aria-etiket"). Just flagging for awareness.

packages/visual-editor/locales/platform/it/visual-editor.json (1)

492-493: Italian cardinal plurals don't use the _many category — these keys are dead.

Per CLDR and i18next's Intl.PluralRules implementation, Italian only defines one and other for cardinal plurals. The _many suffix (used for languages like Arabic, Polish, and ordinal plurals in some languages) will never be selected by i18next for the it locale. These keys are harmless but unnecessary.

If auto-generated by i18next-cli for all locales, safe to ignore. Otherwise, consider removing the _many keys to keep the file lean.

Applies to lines: 492, 508, 511, 514, 520, 676

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants