Skip to content

Conversation

@mkilpatrick
Copy link
Collaborator

Before this change all translations were bundled and ultimately loaded on the frontend even though only a single locale is ever needed at a time.

benlife5
benlife5 previously approved these changes Oct 28, 2025
@mkilpatrick mkilpatrick added the create-dev-release Triggers dev release workflow label Oct 28, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 28, 2025

commit: 7031a03

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

This PR reorganizes localization into separate components and platform paths, updates the i18next scanner config to read/write platform resources under locales/platform/..., and adds many new locale JSON files under locales/components/ and locales/platform/. Tooling and scripts were updated for the two-tier directory layout (generate, copy, sort, check-empty). Runtime i18n initialization moved to on-demand loading with new APIs loadComponentTranslations, loadPlatformTranslations, and injectTranslations; templates now export transformProps that calls injectTranslations, and editor UI code awaits translation loading before changing languages.

Sequence Diagram(s)

sequenceDiagram
    %% Styling: light-highlight for loader and i18n steps
    participant User
    participant Template as Template (directory/locator/main)
    participant Transform as transformProps
    participant Injector as injectTranslations
    participant Loader as Translation Loader
    participant FSys as File System
    participant i18n as i18next Instance
    participant Component as Rendered Component

    User->>Template: Request page (with locale)
    Template->>Transform: transformProps(data)
    Transform->>Injector: injectTranslations(data)
    Injector->>Loader: loadComponentTranslations(locale) / loadPlatformTranslations(locale)
    Loader->>FSys: read locales/components|platform/{locale}/visual-editor.json
    alt locale file exists
        FSys-->>Loader: JSON resource
        Loader->>i18n: addResourceBundle / addResources
    else file missing
        FSys-->>Loader: EN fallback or error
        Loader->>i18n: addResourceBundle (fallback)
    end
    Injector-->>Transform: augmented props (with translations)
    Transform-->>Template: transformed props
    Template->>Component: render with i18n instance
    Component-->>User: localized UI
Loading

Possibly related PRs

Suggested reviewers

  • asanehisa

Pre-merge checks

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: only load necessary translations' directly aligns with the main objective of the PR to load only locale-specific translations instead of bundling all translations upfront.
Description check ✅ Passed The description explains that translations were previously bundled and loaded entirely, and the PR addresses loading only necessary translations for the active locale.

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2acbfa and 7031a03.

📒 Files selected for processing (1)
  • packages/visual-editor/locales/components/zh/visual-editor.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/visual-editor/locales/components/zh/visual-editor.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: call_unit_test / unit_tests (22.x)
  • GitHub Check: call_unit_test / unit_tests (24.x)
  • GitHub Check: call_unit_test / unit_tests (20.x)
  • GitHub Check: semgrep/ci
  • GitHub Check: create-dev-release

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: 18

Caution

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

⚠️ Outside diff range comments (1)
packages/visual-editor/src/utils/VisualEditorProvider.tsx (1)

44-52: Race condition: translations may not load before language change.

loadComponentTranslations is async but not awaited (line 45). When normalizedTemplateProps?.translations is undefined, the function will asynchronously fetch translations via getTranslations(), but i18nComponentsInstance.changeLanguage() executes immediately on line 49 without waiting. This can cause the language to change before translations are available, resulting in missing or fallback text.

Consider one of these solutions:

Option 1: Await inside useEffect

+ React.useEffect(() => {
    if (normalizedTemplateProps?.document?.locale) {
-     loadComponentTranslations(
+     loadComponentTranslations(
        normalizedTemplateProps.document.locale,
        normalizedTemplateProps?.translations
-     );
-     i18nComponentsInstance.changeLanguage(
-       normalizedTemplateProps.document.locale
-     );
+     ).then(() => {
+       i18nComponentsInstance.changeLanguage(
+         normalizedTemplateProps.document.locale
+       );
+     });
    }
+ }, [normalizedTemplateProps?.document?.locale]);

Option 2: Make the provider async-aware with state

+ const [translationsLoaded, setTranslationsLoaded] = React.useState(false);
+
+ React.useEffect(() => {
    if (normalizedTemplateProps?.document?.locale) {
-     loadComponentTranslations(
+     loadComponentTranslations(
        normalizedTemplateProps.document.locale,
        normalizedTemplateProps?.translations
-     );
-     i18nComponentsInstance.changeLanguage(
-       normalizedTemplateProps.document.locale
-     );
+     ).then(() => {
+       i18nComponentsInstance.changeLanguage(
+         normalizedTemplateProps.document.locale
+       );
+       setTranslationsLoaded(true);
+     });
    }
+ }, [normalizedTemplateProps?.document?.locale]);
🧹 Nitpick comments (5)
packages/visual-editor/src/utils/i18n/fallbacks.ts (1)

31-31: Good refactor: removed redundant double negation.

The truthiness check is cleaner without !! while preserving the same behavior.

starter/src/templates/dev.tsx (1)

131-135: Consider stronger typing for transformProps.

The use of TemplateProps<any> loses type safety. While this works, consider constraining the type parameter if the document structure is known, or at minimum using TemplateProps<unknown> to signal the uncertainty.

Example improvement:

-export const transformProps: TransformProps<TemplateProps<any>> = async (
+export const transformProps: TransformProps<TemplateProps<unknown>> = async (
   data
 ) => {
   return await injectTranslations(data);
 };
packages/visual-editor/src/vite-plugin/templates/locator.tsx (1)

1-1: Autogenerated file - consider updating generator for type safety.

Line 1 indicates this is autogenerated. If TemplateProps<any> at lines 95-99 is a concern, the fix should be applied to the template generator rather than this file.

packages/visual-editor/src/utils/i18n/platform.ts (1)

22-53: Consider documenting race condition potential.

While the hasResourceBundle check in loadPlatformTranslations prevents duplicate loading, concurrent calls with the same locale before the first completes could still cause race conditions. The error handling correctly falls back to "en", but this behavior should be documented.

Consider adding a loading state map to prevent concurrent loads:

const loadingLocales = new Set<string>();

const getTranslations = async (
  locale: string,
  isRetry = false
): Promise<Record<string, string>> => {
  if (!locale) {
    return {};
  }
  
  // Wait if already loading
  while (loadingLocales.has(locale)) {
    await new Promise(resolve => setTimeout(resolve, 50));
  }
  
  loadingLocales.add(locale);
  try {
    const module = await import(
      `../../../locales/platform/${locale}/visual-editor.json`
    );
    return module.default;
  } catch (e) {
    // existing error handling...
  } finally {
    loadingLocales.delete(locale);
  }
};
packages/visual-editor/src/utils/i18n/components.ts (1)

81-94: Allow refreshing an existing resource bundle

Once a bundle for a locale exists, this early return prevents us from merging any new or overridden keys that arrive later (e.g., when transformProps starts supplying additional strings). Dropping the guard and using addResourceBundle(..., true, true) keeps the fast path but still lets us refresh data when needed.

 export const loadComponentTranslations = async (
   locale: string,
   translations?: Record<string, string>
 ) => {
-  if (i18nComponentsInstance.hasResourceBundle(locale, NAMESPACE)) {
-    return;
-  }
-
-  const translationsToInject = translations || (await getTranslations(locale));
-
-  if (translationsToInject && Object.keys(translationsToInject).length > 0) {
-    i18nComponentsInstance.addResourceBundle(
-      locale,
-      NAMESPACE,
-      translationsToInject
-    );
-  }
+  const translationsToInject =
+    translations ?? (await getTranslations(locale));
+
+  if (!translationsToInject || Object.keys(translationsToInject).length === 0) {
+    return;
+  }
+
+  i18nComponentsInstance.addResourceBundle(
+    locale,
+    NAMESPACE,
+    translationsToInject,
+    true,
+    i18nComponentsInstance.hasResourceBundle(locale, NAMESPACE)
+  );
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 012c91a and 4b2ee0a.

📒 Files selected for processing (43)
  • packages/visual-editor/i18next-scanner.config.cjs (1 hunks)
  • packages/visual-editor/locales/components/cs/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/da/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/de/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/en-GB/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/en/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/es/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/et/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/fi/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/fr/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/hr/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/hu/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/it/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/ja/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/lt/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/lv/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/nb/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/nl/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/pl/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/pt/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/ro/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/sk/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/sv/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/tr/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json (1 hunks)
  • packages/visual-editor/locales/components/zh/visual-editor.json (1 hunks)
  • packages/visual-editor/scripts/checkEmptyTranslations.ts (1 hunks)
  • packages/visual-editor/scripts/generateTranslations.ts (5 hunks)
  • packages/visual-editor/scripts/sortTranslations.ts (2 hunks)
  • packages/visual-editor/src/editor/Editor.tsx (2 hunks)
  • packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (3 hunks)
  • packages/visual-editor/src/utils/VisualEditorProvider.tsx (2 hunks)
  • packages/visual-editor/src/utils/i18n/components.ts (1 hunks)
  • packages/visual-editor/src/utils/i18n/fallbacks.ts (1 hunks)
  • packages/visual-editor/src/utils/i18n/index.ts (1 hunks)
  • packages/visual-editor/src/utils/i18n/platform.ts (3 hunks)
  • packages/visual-editor/src/utils/resolveComponentData.tsx (1 hunks)
  • packages/visual-editor/src/utils/resolveYextEntityField.ts (1 hunks)
  • packages/visual-editor/src/vite-plugin/plugin.ts (1 hunks)
  • packages/visual-editor/src/vite-plugin/templates/directory.tsx (3 hunks)
  • packages/visual-editor/src/vite-plugin/templates/locator.tsx (3 hunks)
  • packages/visual-editor/src/vite-plugin/templates/main.tsx (3 hunks)
  • starter/src/templates/dev.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (2)
packages/visual-editor/src/utils/i18n/components.ts (2)
  • loadComponentTranslations (77-94)
  • i18nComponentsInstance (6-6)
packages/visual-editor/src/utils/i18n/platform.ts (2)
  • loadPlatformTranslations (58-73)
  • i18nPlatformInstance (7-7)
packages/visual-editor/src/vite-plugin/templates/locator.tsx (4)
packages/visual-editor/src/vite-plugin/templates/directory.tsx (1)
  • transformProps (96-100)
packages/visual-editor/src/vite-plugin/templates/main.tsx (1)
  • transformProps (97-101)
starter/src/templates/dev.tsx (1)
  • transformProps (131-135)
packages/visual-editor/src/utils/i18n/components.ts (1)
  • injectTranslations (22-34)
packages/visual-editor/scripts/generateTranslations.ts (1)
scripts/releaseUtils.ts (1)
  • isDryRun (17-17)
starter/src/templates/dev.tsx (4)
packages/visual-editor/src/vite-plugin/templates/directory.tsx (1)
  • transformProps (96-100)
packages/visual-editor/src/vite-plugin/templates/locator.tsx (1)
  • transformProps (95-99)
packages/visual-editor/src/vite-plugin/templates/main.tsx (1)
  • transformProps (97-101)
packages/visual-editor/src/utils/i18n/components.ts (1)
  • injectTranslations (22-34)
packages/visual-editor/src/vite-plugin/templates/main.tsx (4)
packages/visual-editor/src/vite-plugin/templates/directory.tsx (1)
  • transformProps (96-100)
packages/visual-editor/src/vite-plugin/templates/locator.tsx (1)
  • transformProps (95-99)
starter/src/templates/dev.tsx (1)
  • transformProps (131-135)
packages/visual-editor/src/utils/i18n/components.ts (1)
  • injectTranslations (22-34)
packages/visual-editor/src/vite-plugin/templates/directory.tsx (4)
packages/visual-editor/src/vite-plugin/templates/locator.tsx (1)
  • transformProps (95-99)
packages/visual-editor/src/vite-plugin/templates/main.tsx (1)
  • transformProps (97-101)
starter/src/templates/dev.tsx (1)
  • transformProps (131-135)
packages/visual-editor/src/utils/i18n/components.ts (1)
  • injectTranslations (22-34)
packages/visual-editor/src/utils/VisualEditorProvider.tsx (1)
packages/visual-editor/src/utils/i18n/components.ts (1)
  • loadComponentTranslations (77-94)
packages/visual-editor/src/editor/Editor.tsx (1)
packages/visual-editor/src/utils/i18n/platform.ts (2)
  • loadPlatformTranslations (58-73)
  • i18nPlatformInstance (7-7)
packages/visual-editor/src/utils/i18n/platform.ts (1)
packages/visual-editor/src/utils/i18n/fallbacks.ts (2)
  • applyI18nFallbacks (26-39)
  • defaultI18nFallbacks (6-15)
🔇 Additional comments (30)
packages/visual-editor/locales/components/sk/visual-editor.json (1)

1-14: JSON structure and Slovak translations look good.

The file is properly formatted and contains semantically appropriate translations for location/business hours status indicators and weekday names. The nested directory structure (locales/components/sk/) aligns with the PR's goal of supporting granular, dynamic translation loading.

Verify that this locale file is properly integrated into the new loadComponentTranslations() runtime loading function so it's only bundled and loaded when the Slovak locale is needed.

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

1-14: Locale resource file looks good.

The JSON structure is valid, all keys are present with non-empty translations, and the camelCase naming convention is consistent with typical i18n patterns. The translations cover status states and day-of-week labels as expected.

One minor observation: "closed" and "closesAt" both map to the same translation "關閉". This is likely intentional, but if they should convey slightly different meanings in the UI, consider whether separate translations are needed.

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

1-14: JSON structure is valid and properly integrated into the new locale hierarchy.

The file is well-formed, contains 12 UI translation keys for Danish, and correctly uses the new locales/components/{locale}/visual-editor.json path structure as part of the runtime translation loading system. Danish characters are properly encoded.

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

1-14: JSON structure and formatting are valid.

The translation file is properly formatted JSON with no syntax errors. However, I cannot verify the accuracy of Dutch translations or completeness of the key set without examining reference locale files or domain expertise.

Consider running the following to verify consistency with other locale files:

  • Ensure all keys in this file match those in companion locale files (e.g., en/visual-editor.json)
  • Have Dutch translations reviewed by a native speaker or translation expert to confirm accuracy
  • Verify that the key order is intentional or apply consistent alphabetical sorting across all locale files
packages/visual-editor/src/utils/resolveComponentData.tsx (1)

4-7: LGTM! Type-only imports correctly applied.

Converting these imports to type-only is a good TypeScript practice that reduces the runtime bundle size. All four types (RichText, TranslatableRichText, TranslatableString, YextEntityField) are used exclusively as type annotations throughout the file, making this change appropriate and aligned with the PR's goal of loading only necessary code.

packages/visual-editor/src/utils/resolveYextEntityField.ts (1)

1-3: LGTM! Consistent type-only imports.

The conversion to type-only imports is correct and follows the same pattern as the changes in resolveComponentData.tsx. All three types (StreamDocument, YextEntityField, YextStructEntityField) are used exclusively for type annotations, making this refactor safe and beneficial for reducing the runtime bundle size.

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

1-14: All required keys are present and consistent across locale files.

The Hungarian locale file contains all required keys matching the English baseline (13 keys: location status and weekdays). The file is properly structured and integrated into the new two-tier locale hierarchy supporting granular component translation loading.

To complete validation, verify:

  1. Hungarian translations are accurate for the intended use context (location/hours display).
  2. The runtime loadComponentTranslations() function properly loads and references this file.
packages/visual-editor/locales/components/ro/visual-editor.json (1)

1-14: ✓ Translation key consistency verified.

All 13 translation keys in the Romanian locale (closed, closesAt, friday, monday, open24Hours, openNow, saturday, sunday, temporarilyClosed, thursday, tuesday, wednesday) match exactly across all 25 locale files in the components namespace. The JSON structure is valid and properly formatted. No issues detected.

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

1-14: Translation content is accurate and properly integrated into the dynamic loading system.

The Croatian locale file is correctly positioned at packages/visual-editor/locales/components/hr/visual-editor.json, following the naming convention of all 24 other component translations. The loadComponentTranslations() function dynamically imports component locales via import(\../../../locales/components/${locale}/visual-editor.json`)`, which correctly resolves to this file. The system uses runtime lazy loading—component translations are not processed by the i18next-scanner (which handles platform translations separately) but are loaded on-demand when the Croatian locale is selected, with automatic fallback to English if needed.

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

1-14: Norwegian translations look reasonable.

The translation keys and values are consistent with other locale files. The use of "Lukket" for closed status and "Åpent 24 timer" for 24-hour operation appears appropriate.

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

1-14: English baseline translations are correct.

All translations use appropriate grammatical forms for status indicators and are consistent across keys.

packages/visual-editor/src/vite-plugin/templates/directory.tsx (3)

12-12: LGTM: Required import added.

The TransformProps type import is necessary for the new transformProps function.


27-27: LGTM: Translation injection utility imported.

The injectTranslations import enables runtime translation loading based on document locale.


96-100: LGTM: Translation injection follows established pattern.

The transformProps implementation correctly delegates to injectTranslations and matches the pattern used in other templates (locator.tsx, main.tsx). This enables dynamic loading of only the necessary translations for each locale, aligning with the PR objective.

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

1-14: Czech translations look reasonable.

The translations use appropriate grammatical forms. Note that "ZAVŘENO" (line 2) is in all caps, which may be intentional for emphasis on closed status.

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

1-14: LGTM! Estonian translations are complete and properly localized.

All required keys are translated and the structure is correct.

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

1-14: LGTM! Spanish translations are complete and properly localized.

All required keys are translated correctly.

packages/visual-editor/src/utils/i18n/index.ts (1)

1-1: LGTM! Export addition supports runtime translation injection.

Adding injectTranslations to the public API aligns with the PR objective to load translations dynamically.

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

1-14: LGTM! Portuguese translations are complete and properly localized.

All required keys including weekdays are fully translated.

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

1-14: LGTM! Latvian translations are complete and properly localized.

All required keys are fully translated.

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

1-14: LGTM!

The UK English translations are correct and consistent with standard localization practices.

packages/visual-editor/src/vite-plugin/templates/main.tsx (1)

97-101: LGTM!

The transformProps implementation correctly awaits the async injectTranslations call and follows the same pattern used in other template files (directory.tsx, locator.tsx, dev.tsx). This ensures translations are loaded before template rendering.

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

1-14: Structure looks good; verify translation accuracy.

The JSON structure and formatting are correct. However, translation accuracy should be verified by a Lithuanian speaker to ensure the translations are natural and appropriate for the UI context.

packages/visual-editor/i18next-scanner.config.cjs (1)

55-56: LGTM! Path restructuring aligns with the two-tier locale hierarchy.

The updated resource paths correctly scope translations under locales/platform/, enabling separate handling of platform vs. component translations.

packages/visual-editor/src/vite-plugin/plugin.ts (1)

154-158: LGTM! Cleanup now properly scoped to build mode.

The conditional cleanup ensures generated files persist during dev mode while being cleaned up after builds. This aligns with the discussion in past review comments about buildStart running for both server and build modes.

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

15-50: LGTM! Improved resilience with two-tier structure support.

The updated logic correctly handles the nested locale structure (locales/<subfolder>/<locale>/visual-editor.json) and gracefully warns about missing files instead of failing. The two-tier traversal aligns with the PR's restructuring goals.


52-60: Good addition of explicit exit code handling.

The post-processing check ensures the script exits with the correct code based on validation results, improving CI/CD integration.

packages/visual-editor/src/utils/i18n/platform.ts (2)

7-7: LGTM! Instance now exported for direct usage.

Exporting i18nPlatformInstance enables components like LayoutHeader to directly control language changes after loading translations.


9-17: Good shift to runtime translation loading.

Starting with empty resources and loading on-demand reduces bundle size and enables locale-specific loading, directly addressing the PR objective.

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

39-71: Add error handling around file I/O operations.

The original review comment correctly identified missing error handling, but its structural assumptions do not match the actual directory layout. The locale structure is strictly locales/{components,platform}/{language}/visual-editor.json with no mixed-content directories or nested JSON files at intermediate levels. The algorithm handles this structure correctly.

However, error handling is genuinely missing from file operations. Add try-catch blocks around JSON.parse, fs.readFile, and fs.writeFile:

           if (file.isFile() && file.name.endsWith(".json")) {
             const filePath = path.join(fullPath, file.name);
-            const data = JSON.parse(await fs.readFile(filePath, "utf8"));
-            const sorted = sortObject(data);
-            await fs.writeFile(
-              filePath,
-              JSON.stringify(sorted, null, 2) + "\n"
-            );
+            try {
+              const data = JSON.parse(await fs.readFile(filePath, "utf8"));
+              const sorted = sortObject(data);
+              await fs.writeFile(
+                filePath,
+                JSON.stringify(sorted, null, 2) + "\n"
+              );
+            } catch (error) {
+              console.error(`Error processing ${filePath}:`, error);
+              throw error;
+            }
           }

Likely an incorrect or invalid review comment.

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: 0

🧹 Nitpick comments (1)
packages/visual-editor/src/vite-plugin/plugin.ts (1)

151-158: Update the comment to reflect the new cleanup behavior.

The comment at lines 95-96 states "Created files will be marked for deletion on buildEnd," but with the new conditional logic, files are only cleaned up on buildEnd during build mode. In dev mode, cleanup is deferred to the SIGINT/SIGTERM handlers (lines 136-144).

Apply this diff to update the comment:

   /**
    * generateFiles generates the template files and .temlpate-manifest.json file
    *
    * Does not overwrite files that already exists
    *
-   * Created files will be marked for deletion on buildEnd
+   * Created files will be marked for deletion on buildEnd (build mode) or process termination (dev mode)
    */
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b2ee0a and ff7610a.

📒 Files selected for processing (6)
  • packages/visual-editor/src/utils/resolveYextEntityField.ts (1 hunks)
  • packages/visual-editor/src/vite-plugin/plugin.ts (1 hunks)
  • packages/visual-editor/src/vite-plugin/templates/directory.tsx (3 hunks)
  • packages/visual-editor/src/vite-plugin/templates/locator.tsx (3 hunks)
  • packages/visual-editor/src/vite-plugin/templates/main.tsx (3 hunks)
  • starter/src/templates/dev.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • starter/src/templates/dev.tsx
  • packages/visual-editor/src/vite-plugin/templates/main.tsx
  • packages/visual-editor/src/utils/resolveYextEntityField.ts
  • packages/visual-editor/src/vite-plugin/templates/locator.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
packages/visual-editor/src/vite-plugin/templates/directory.tsx (4)
packages/visual-editor/src/vite-plugin/templates/main.tsx (1)
  • transformProps (97-101)
starter/src/templates/dev.tsx (1)
  • transformProps (133-137)
packages/visual-editor/src/vite-plugin/templates/locator.tsx (1)
  • transformProps (95-99)
packages/visual-editor/src/utils/i18n/components.ts (1)
  • injectTranslations (22-34)
🔇 Additional comments (1)
packages/visual-editor/src/vite-plugin/templates/directory.tsx (1)

96-100: LGTM! Translation injection is correctly implemented.

The transformProps implementation correctly delegates to injectTranslations and is consistent with the pattern used in other template files (main.tsx, locator.tsx). This aligns with the PR objective to load only necessary translations based on the document locale.

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: 1

🧹 Nitpick comments (5)
packages/visual-editor/scripts/generateTranslations.ts (4)

64-84: Update TSDoc to document the type parameter.

The ENOENT handling from the previous review has been correctly implemented. However, the function documentation doesn't describe the new type parameter.

Apply this diff to complete the documentation:

 /**
- * Reads all directories under localesDir and returns them as target languages.
+ * Reads all directories under localesDir/{type} and returns them as target languages.
+ * @param type - The translation type to get languages for ("components" or "platform")
+ * @returns Array of language directory names, or empty array if type directory doesn't exist
  */
 async function getTargetLanguages(
   type: "components" | "platform"
 ): Promise<string[]> {

194-198: Update TSDoc to document the type parameter.

The function documentation doesn't describe the new type parameter.

Apply this diff:

 /**
  * Loads the base English translation file, compares it to each target language file,
  * translates missing or empty keys using Google Translate, and optionally writes them back.
+ * @param type - The translation type to process ("components" or "platform")
  */
 async function translateFile(type: "components" | "platform"): Promise<void> {

256-256: Make error logging consistent with other log messages.

All other log messages in this function use the [${type}/${lng}] format, but this error log uses only [${lng}].

Apply this diff:

         } catch (e) {
           failCount++;
-          console.error(`[${lng}] ❌ Failed to translate key "${key}":`, e);
+          console.error(`[${type}/${lng}] ❌ Failed to translate key "${key}":`, e);
         }

273-274: Await translation promises to ensure proper completion and error handling.

The script invokes both translateFile calls without awaiting them. While Node.js keeps the process alive for pending async operations, this pattern has drawbacks: if either translation fails, the error is logged but the process may exit with code 0, causing CI/CD pipelines to incorrectly report success.

Apply this diff to run both in parallel with proper exit code handling:

-// Kick off the translation process
-translateFile("components").catch(console.error);
-translateFile("platform").catch(console.error);
+(async () => {
+  try {
+    await Promise.all([
+      translateFile("components"),
+      translateFile("platform")
+    ]);
+  } catch (error) {
+    console.error(error);
+    process.exit(1);
+  }
+})();

Or, if you prefer sequential execution:

-// Kick off the translation process
-translateFile("components").catch(console.error);
-translateFile("platform").catch(console.error);
+(async () => {
+  try {
+    await translateFile("components");
+    await translateFile("platform");
+  } catch (error) {
+    console.error(error);
+    process.exit(1);
+  }
+})();
packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (1)

224-239: Consider adding error handling for translation loading.

The race conditions from previous reviews have been correctly addressed by making the handlers async and awaiting the translation loaders. However, for improved developer experience in local dev mode, consider adding error handling:

      <Button
        onClick={async () => {
          const locale = prompt("Enter components locale:") || "en";
-         await loadComponentTranslations(locale);
-         i18nComponentsInstance.changeLanguage(locale);
+         try {
+           await loadComponentTranslations(locale);
+           i18nComponentsInstance.changeLanguage(locale);
+         } catch (error) {
+           console.error('Failed to load component translations:', error);
+           alert(`Failed to load translations for locale: ${locale}`);
+         }
        }}
        variant="outline"
        className="ve-ml-4"
      >
        Set Components Locale
      </Button>
      <Button
        onClick={async () => {
          const locale = prompt("Enter platform locale:") || "en";
-         await loadPlatformTranslations(locale);
-         i18nPlatformInstance.changeLanguage(locale);
+         try {
+           await loadPlatformTranslations(locale);
+           i18nPlatformInstance.changeLanguage(locale);
+         } catch (error) {
+           console.error('Failed to load platform translations:', error);
+           alert(`Failed to load translations for locale: ${locale}`);
+         }
        }}
        variant="outline"
        className="ve-ml-4"
      >
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff7610a and 0dddf27.

📒 Files selected for processing (3)
  • packages/visual-editor/scripts/generateTranslations.ts (5 hunks)
  • packages/visual-editor/src/editor/Editor.tsx (2 hunks)
  • packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/visual-editor/src/editor/Editor.tsx (1)
packages/visual-editor/src/utils/i18n/platform.ts (2)
  • loadPlatformTranslations (58-73)
  • i18nPlatformInstance (7-7)
packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (2)
packages/visual-editor/src/utils/i18n/components.ts (2)
  • loadComponentTranslations (77-94)
  • i18nComponentsInstance (6-6)
packages/visual-editor/src/utils/i18n/platform.ts (2)
  • loadPlatformTranslations (58-73)
  • i18nPlatformInstance (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: call_unit_test / unit_tests (18.x)
  • GitHub Check: call_unit_test / unit_tests (20.x)
  • GitHub Check: semgrep/ci
  • GitHub Check: create-dev-release
🔇 Additional comments (2)
packages/visual-editor/src/editor/Editor.tsx (1)

19-22: LGTM! Imports correctly support the new translation loading flow.

The addition of loadPlatformTranslations enables the pre-loading of platform translations before language changes.

packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (1)

16-19: LGTM! Imports correctly support the dev override buttons.

The translation loading utilities are properly imported and enable the locale-switching functionality in LocalDevOverrideButtons.

Also applies to: 24-24

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: 11

♻️ Duplicate comments (1)
packages/visual-editor/locales/components/zh/visual-editor.json (1)

4-5: Complete the weekday translations.

The weekday names remain in English instead of Chinese, creating an inconsistent localization experience. Other locale files in this PR have properly translated weekdays.

🔎 Proposed fix
-  "friday": "Friday",
-  "monday": "Monday",
+  "friday": "星期五",
+  "monday": "星期一",
-  "saturday": "Saturday",
-  "sunday": "Sunday",
+  "saturday": "星期六",
+  "sunday": "星期日",
-  "thursday": "Thursday",
-  "tuesday": "Tuesday",
-  "wednesday": "Wednesday",
+  "thursday": "星期四",
+  "tuesday": "星期二",
+  "wednesday": "星期三",

Also applies to: 8-9, 11-13

🧹 Nitpick comments (4)
packages/visual-editor/locales/components/da/visual-editor.json (1)

1-24: Verify translation accuracy with a native Danish speaker.

While the JSON structure is valid and all keys are translated, consider having these translations reviewed by a native Danish speaker to ensure accuracy, natural phrasing, and appropriate capitalization conventions for Danish.

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

23-23: Consider more idiomatic navigation terminology.

While "Obtener instrucciones" is correct, "Cómo llegar" or "Obtener indicaciones" are more commonly used in Spanish navigation/mapping contexts.

🔎 Suggested alternatives
-  "getDirections": "Obtener instrucciones"
+  "getDirections": "Cómo llegar"

Or:

-  "getDirections": "Obtener instrucciones"
+  "getDirections": "Obtener indicaciones"
packages/visual-editor/scripts/copyPlatformTranslations.ts (2)

1-1: Update comment to match actual filename.

The comment references copyTranslations.ts but the file is named copyPlatformTranslations.ts.

🔎 Proposed fix
-// scripts/copyTranslations.ts
+// scripts/copyPlatformTranslations.ts

108-120: Consider key ordering after updates.

The script adds new keys to the component translations, but they may not be in alphabetical order. While there's an i18n:sort script available, users might benefit from a reminder to run it after this script completes.

Suggested improvement

Add a note to the final console output reminding users to run the sort script:

   }
 
-  console.log("\nDone!");
+  console.log("\nDone!");
+  console.log("Tip: Run 'pnpm run i18n:sort' to alphabetize the updated translations.");
 };
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5232d4e and 6a5ab29.

📒 Files selected for processing (53)
  • .gitattributes
  • packages/visual-editor/locales/components/cs/visual-editor.json
  • packages/visual-editor/locales/components/da/visual-editor.json
  • packages/visual-editor/locales/components/de/visual-editor.json
  • packages/visual-editor/locales/components/en-GB/visual-editor.json
  • packages/visual-editor/locales/components/en/visual-editor.json
  • packages/visual-editor/locales/components/es/visual-editor.json
  • packages/visual-editor/locales/components/et/visual-editor.json
  • packages/visual-editor/locales/components/fi/visual-editor.json
  • packages/visual-editor/locales/components/fr/visual-editor.json
  • packages/visual-editor/locales/components/hr/visual-editor.json
  • packages/visual-editor/locales/components/hu/visual-editor.json
  • packages/visual-editor/locales/components/it/visual-editor.json
  • packages/visual-editor/locales/components/ja/visual-editor.json
  • packages/visual-editor/locales/components/lt/visual-editor.json
  • packages/visual-editor/locales/components/lv/visual-editor.json
  • packages/visual-editor/locales/components/nb/visual-editor.json
  • packages/visual-editor/locales/components/nl/visual-editor.json
  • packages/visual-editor/locales/components/pl/visual-editor.json
  • packages/visual-editor/locales/components/pt/visual-editor.json
  • packages/visual-editor/locales/components/ro/visual-editor.json
  • packages/visual-editor/locales/components/sk/visual-editor.json
  • packages/visual-editor/locales/components/sv/visual-editor.json
  • packages/visual-editor/locales/components/tr/visual-editor.json
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json
  • packages/visual-editor/locales/components/zh/visual-editor.json
  • packages/visual-editor/locales/platform/cs/visual-editor.json
  • packages/visual-editor/locales/platform/da/visual-editor.json
  • packages/visual-editor/locales/platform/de/visual-editor.json
  • packages/visual-editor/locales/platform/en-GB/visual-editor.json
  • packages/visual-editor/locales/platform/en/visual-editor.json
  • packages/visual-editor/locales/platform/es/visual-editor.json
  • packages/visual-editor/locales/platform/et/visual-editor.json
  • packages/visual-editor/locales/platform/fi/visual-editor.json
  • packages/visual-editor/locales/platform/fr/visual-editor.json
  • packages/visual-editor/locales/platform/hr/visual-editor.json
  • packages/visual-editor/locales/platform/hu/visual-editor.json
  • packages/visual-editor/locales/platform/it/visual-editor.json
  • packages/visual-editor/locales/platform/ja/visual-editor.json
  • packages/visual-editor/locales/platform/lt/visual-editor.json
  • packages/visual-editor/locales/platform/lv/visual-editor.json
  • packages/visual-editor/locales/platform/nb/visual-editor.json
  • packages/visual-editor/locales/platform/nl/visual-editor.json
  • packages/visual-editor/locales/platform/pl/visual-editor.json
  • packages/visual-editor/locales/platform/pt/visual-editor.json
  • packages/visual-editor/locales/platform/ro/visual-editor.json
  • packages/visual-editor/locales/platform/sk/visual-editor.json
  • packages/visual-editor/locales/platform/sv/visual-editor.json
  • packages/visual-editor/locales/platform/tr/visual-editor.json
  • packages/visual-editor/locales/platform/zh-TW/visual-editor.json
  • packages/visual-editor/locales/platform/zh/visual-editor.json
  • packages/visual-editor/package.json
  • packages/visual-editor/scripts/copyPlatformTranslations.ts
💤 Files with no reviewable changes (1)
  • packages/visual-editor/locales/platform/en/visual-editor.json
✅ Files skipped from review due to trivial changes (1)
  • packages/visual-editor/locales/components/hr/visual-editor.json
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/visual-editor/locales/components/en/visual-editor.json
  • packages/visual-editor/locales/components/et/visual-editor.json
  • packages/visual-editor/locales/components/cs/visual-editor.json
  • packages/visual-editor/locales/components/sv/visual-editor.json
  • packages/visual-editor/locales/components/fr/visual-editor.json
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json
  • packages/visual-editor/locales/components/nb/visual-editor.json
  • packages/visual-editor/locales/components/de/visual-editor.json
  • packages/visual-editor/locales/components/hu/visual-editor.json
  • packages/visual-editor/locales/components/sk/visual-editor.json
  • packages/visual-editor/locales/components/pl/visual-editor.json
  • packages/visual-editor/locales/components/en-GB/visual-editor.json
  • packages/visual-editor/locales/components/ja/visual-editor.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-23T16:36:42.670Z
Learnt from: benlife5
Repo: yext/visual-editor PR: 958
File: packages/visual-editor/locales/ro/visual-editor.json:394-394
Timestamp: 2025-12-23T16:36:42.670Z
Learning: In Romanian locale files (ro), "Top" is an acceptable translation for directional terms like "top_direction" rather than the native Romanian "Sus". The maintainer benlife5 confirmed this is the preferred translation in packages/visual-editor/locales/ro/visual-editor.json.

Applied to files:

  • packages/visual-editor/locales/components/ro/visual-editor.json
🧬 Code graph analysis (1)
packages/visual-editor/scripts/copyPlatformTranslations.ts (1)
packages/visual-editor/scripts/generateFontRegistry.js (2)
  • dir (216-216)
  • data (42-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: call_unit_test / unit_tests (20.x)
  • GitHub Check: semgrep/ci
🔇 Additional comments (10)
packages/visual-editor/locales/components/it/visual-editor.json (1)

2-4: Most translations are correct.

The majority of the Italian translations are accurate and idiomatic. The weekdays (Venerdì, Sabato, Domenica, Giovedì, Martedì, Mercoledì) have correct accents, and the UI strings (Chiuso, Chiude a, Temporaneamente chiuso, Ricerca, Filtro, Distanza, etc.) are properly translated.

However, please address the previously flagged issues at lines 5-7 before merging.

Also applies to: 8-24

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

1-24: Portuguese translations are complete and accurate; they match the English locale with all 22 keys present.

The Portuguese locale file contains all required translation keys and matches the English reference locale exactly. The JSON structure is valid and the translations are correct.

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

1-24: No action needed. All component locale files (packages/visual-editor/locales/components/*/visual-editor.json) across all 25 language versions contain the same 22 keys with consistent structure, including the reviewed Dutch (nl) file.

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

1-24: No issues to address. These translations are copied from the established platform/ro source, which already contains both "openNow": "Deschide acum" and "filter": "Filtra". The verb forms used are consistent with the existing platform translations and have already been reviewed. This PR is a mechanical copy operation between locale organizational tiers.

Likely an incorrect or invalid review comment.

packages/visual-editor/package.json (1)

58-59: LGTM!

The new i18n scripts are properly formatted and follow the established naming convention. The i18n:copy-platform-translations script aligns with the PR's objective to manage translations more efficiently.

.gitattributes (1)

4-5: LGTM!

The updated linguist-generated markers correctly reflect the new platform/components locale structure. Marking English locale files as non-generated ensures they're properly tracked as source files.

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

1-24: LGTM!

The Latvian locale file is properly formatted with valid JSON structure and follows the established key naming conventions used in other locale files.

packages/visual-editor/scripts/copyPlatformTranslations.ts (3)

20-47: LGTM!

The helper functions are well-structured with appropriate error handling. The loadJson function gracefully handles missing files and parse errors, while saveJson ensures directories exist before writing and includes a trailing newline for clean git diffs.


87-127: LGTM!

The main processing logic correctly copies missing translation keys from platform to component locale files. The conditional check ensures only missing keys are added, and files are only written when updates are made.


129-134: LGTM!

The top-level error handling properly catches and reports unexpected errors with appropriate exit codes.

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

🧹 Nitpick comments (2)
packages/visual-editor/scripts/dedupeTranslations.ts (2)

55-56: Verify JSON.stringify comparison reliability for object values.

Using JSON.stringify(value) to compare values can produce false conflicts if the same object has keys in different orders. While this may be acceptable for primitive values (strings, numbers, booleans, null), objects with reordered keys would be flagged as conflicts even though they're semantically identical.

💡 Consider a deep-equality comparison for objects

If translation values can contain nested objects, consider using a deep-equality comparison instead of string comparison, or normalize object key ordering before comparison:

-          const stringValue = JSON.stringify(value);
+          const stringValue = typeof value === 'object' && value !== null
+            ? JSON.stringify(value, Object.keys(value).sort())
+            : JSON.stringify(value);

Alternatively, use a library like lodash.isEqual for semantic equality checks.


99-106: Object reconstruction assumes no arrays in JSON structure.

The rebuild logic at lines 99-106 assumes all intermediate values are objects. If translation JSON contains arrays, they would be overwritten with empty objects on line 103. While translation files typically use nested objects rather than arrays, consider adding a guard if arrays are possible.

💡 Add array handling if needed
       const parts = keyPath.split(".");
       let obj = cleaned;
       for (let i = 0; i < parts.length - 1; i++) {
         const part = parts[i];
-        if (!obj[part]) obj[part] = {};
+        if (!obj[part] || typeof obj[part] !== 'object') obj[part] = {};
         obj = obj[part];
       }
       obj[parts[parts.length - 1]] = value;
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a5ab29 and a96b0b0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • packages/visual-editor/locales/components/es/visual-editor.json
  • packages/visual-editor/locales/components/fi/visual-editor.json
  • packages/visual-editor/locales/components/nl/visual-editor.json
  • packages/visual-editor/locales/components/tr/visual-editor.json
  • packages/visual-editor/locales/platform/en/visual-editor.json
  • packages/visual-editor/locales/platform/es/visual-editor.json
  • packages/visual-editor/locales/platform/fi/visual-editor.json
  • packages/visual-editor/locales/platform/nl/visual-editor.json
  • packages/visual-editor/locales/platform/tr/visual-editor.json
  • packages/visual-editor/package.json
  • packages/visual-editor/scripts/copyPlatformTranslations.ts
  • packages/visual-editor/scripts/dedupeTranslations.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/visual-editor/locales/platform/nl/visual-editor.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/visual-editor/locales/components/es/visual-editor.json
  • packages/visual-editor/locales/components/tr/visual-editor.json
  • packages/visual-editor/locales/components/nl/visual-editor.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: call_unit_test / unit_tests (20.x)
  • GitHub Check: semgrep/ci
🔇 Additional comments (7)
packages/visual-editor/locales/platform/fi/visual-editor.json (1)

484-484: LGTM! Improved Finnish translation.

The change from "Suodattaa" (infinitive) to "Suodata" (imperative) is appropriate for UI context. The imperative form is more idiomatic for action labels and buttons in Finnish.

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

1-24: LGTM! All previous issues have been addressed.

The Finnish translations look correct and consistent. All issues flagged in previous reviews have been successfully resolved:

  • Proper time indicator "kello" for closesAt
  • Consistent lowercase weekday names
  • Correct imperative verb form "Suodata" for the filter action
packages/visual-editor/locales/platform/tr/visual-editor.json (1)

616-616: LGTM - Minor localization consistency improvement.

The capitalization change from title case to sentence case for "hassaslaştırın" improves consistency with modern UI conventions for action labels. While this change appears incidental to the PR's main objective of optimizing translation loading, it's a reasonable localization refinement.

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

555-555: LGTM! Translation quality improvement.

The change from "Abrir 24 horas" to "Abierto 24 horas" is grammatically correct. "Abierto" (open/opened) is the appropriate adjective form for indicating business hours status, rather than the infinitive "Abrir" (to open).

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

143-148: LGTM: Error handling is appropriate for a CLI script.

The top-level error handler with process.exit(1) is suitable for a build/maintenance script.

packages/visual-editor/package.json (2)

58-60: LGTM: New i18n scripts align with the translation tooling additions.

The new npm scripts correctly reference the corresponding TypeScript files added in this PR and follow the existing naming convention.


119-119: The AI summary was incorrect. oboe and @types/oboe are only in devDependencies, not in both dependencies and devDependencies. There is no duplication to address.

Likely an incorrect or invalid review comment.

@github-actions
Copy link
Contributor

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.

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

♻️ Duplicate comments (7)
packages/visual-editor/locales/components/it/visual-editor.json (1)

18-20: Italian translation errors still present.

The previously flagged issues remain unaddressed:

  1. Line 18: "Lunedi" is missing the accent and should be "Lunedì"
  2. Lines 19-20: "Apri" is the imperative (command) form, but should be "Aperto" (adjective for status)

These corrections are necessary for grammatically correct Italian.

🔎 Apply these corrections
- "monday": "Lunedi",
- "open24Hours": "Apri 24 ore",
- "openNow": "Apri ora",
+ "monday": "Lunedì",
+ "open24Hours": "Aperto 24 ore",
+ "openNow": "Aperto ora",
packages/visual-editor/locales/components/nl/visual-editor.json (1)

39-39: Zero-width space character still present in translation.

The translation still contains an invisible zero-width space character between "een" and "locatie" which was flagged in a previous review. This can cause text processing, search, or display issues.

🔎 Proposed fix
-  "useOurLocatorToFindALocationNearYou": "Gebruik onze locator om een ​​locatie bij u in de buurt te vinden",
+  "useOurLocatorToFindALocationNearYou": "Gebruik onze locator om een locatie bij u in de buurt te vinden",
packages/visual-editor/locales/components/de/visual-editor.json (1)

4-4: Incorrect preposition for time expression.

The preposition "bei" is used for locations, but closing times require "um" in German.

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

39-39: Correct the inconsistent formality in the imperative verb.

The translation still mixes formal and informal forms: "Use" (formal imperative for usted) with "ti" (informal pronoun). Since the rest of the file uses informal forms ("Refina tu" on Line 21, "Busca" on Line 25), this should use the informal imperative "Usa" for consistency.

🔎 Proposed fix
-  "useOurLocatorToFindALocationNearYou": "Use nuestro localizador para encontrar una ubicación cerca de ti",
+  "useOurLocatorToFindALocationNearYou": "Usa nuestro localizador para encontrar una ubicación cerca de ti",
packages/visual-editor/locales/components/fr/visual-editor.json (1)

19-20: Use adjective form for status indicators (previously flagged, still unresolved).

These lines still use infinitive verb forms ("Ouvrir") which read as commands rather than status descriptions. For UI status indicators, the adjective form "Ouvert" should be used.

🔎 Apply this fix to use proper status adjectives
-  "open24Hours": "Ouvrir 24 heures",
-  "openNow": "Ouvrir maintenant",
+  "open24Hours": "Ouvert 24h/24",
+  "openNow": "Ouvert actuellement",
packages/visual-editor/locales/components/en/visual-editor.json (1)

1-42: Verify completeness of component translations.

The past review comment mentioned missing translations like openMenu from ExpandedHeader. While searchThisArea is now present (line 25), other component-level keys may still be missing from this component locale file.

Run the following script to identify component translations that may be missing from this English component locale:

#!/bin/bash
# Description: Find translation keys used in component files that might be missing from the English component locale

# Search for translation key usage in component files (t('keyName') or i18n.t('keyName') patterns)
echo "=== Searching for translation keys in components ==="
rg -n --type tsx --type ts "\.t\(['\"]([^'\"]+)['\"]" packages/visual-editor/src/components/ -o -r '$1' | sort -u

echo ""
echo "=== Keys in English component locale ==="
jq -r 'keys[]' packages/visual-editor/locales/components/en/visual-editor.json

echo ""
echo "=== Comparing keys ==="
# This will help identify if there are obvious gaps
packages/visual-editor/locales/components/tr/visual-editor.json (1)

19-20: Status strings still use imperative verbs instead of adjectives.

Despite the past review comment indicating this was addressed in commit 7695f51, the current code still shows imperative verb forms:

  • Line 19: "açın" (open as command)
  • Line 20: "aç" (open as command)

These should be status indicators using the adjective form "açık" (open as state):

  • "24 saat açık" (open 24 hours as a state)
  • "Şu anda açık" (currently open as a state)
🔎 Suggested fix
-  "open24Hours": "24 saat açın",
-  "openNow": "Şimdi aç",
+  "open24Hours": "24 saat açık",
+  "openNow": "Şu anda açık",
🧹 Nitpick comments (12)
packages/visual-editor/locales/platform/fi/visual-editor.json (1)

494-502: Consider consolidating duplicate social link translations.

Two nearly identical objects (footerSocialLinks and socialLinks) contain the same social media translations with only one key difference: footerSocialLinks uses "twitter": "Seuraa meitä Twitterissä" while socialLinks uses "xLink": "Seuraa meitä X:ssä (Twitter)". This duplication could create maintenance challenges.

If these objects serve different UI contexts, please document the distinction. Otherwise, consider:

  • Consolidating into a single object to reduce duplication
  • Establishing a consistent naming convention for Twitter/X across all locale objects
Example consolidation approach

If the distinction isn't necessary, you could maintain a single socialLinks object and reference it from both contexts, or clearly document why both are needed (e.g., footer uses legacy Twitter branding while other components use X branding).

Also applies to: 659-667

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

501-509: Verify the need for separate footerSocialLinks and socialLinks blocks.

The translations are accurate, but this block is nearly identical to socialLinks (lines 666-674) with one key difference: this uses twitter while the other uses xLink. This duplication could lead to maintenance issues.

Please confirm:

  1. Is having both blocks intentional for different UI contexts?
  2. Should the twitter vs xLink inconsistency be unified, or does each serve a specific purpose?

If both are needed, consider adding a comment explaining their distinct purposes to aid future maintainers.

packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (2)

294-299: Race condition resolved correctly.

The handler now properly awaits translation loading before changing the language, addressing the previous issue flagged in past reviews.

Consider adding error handling to provide feedback if translation loading fails, though this is lower priority given the dev-only context:

Optional: Add error handling
-      onClick={async () => {
-        const locale = prompt("Enter components locale:") || "en";
-        await loadComponentTranslations(locale);
-        i18nComponentsInstance.changeLanguage(locale);
+      onClick={async () => {
+        try {
+          const locale = prompt("Enter components locale:") || "en";
+          await loadComponentTranslations(locale);
+          i18nComponentsInstance.changeLanguage(locale);
+        } catch (error) {
+          console.error("Failed to load component translations:", error);
+          alert("Failed to load translations for locale: " + locale);
+        }
       }}

305-310: Race condition resolved correctly.

The handler now properly awaits translation loading before changing the language, matching the fix applied to the component locale button.

Consider adding error handling similar to the component locale button:

Optional: Add error handling
-      onClick={async () => {
-        const locale = prompt("Enter platform locale:") || "en";
-        await loadPlatformTranslations(locale);
-        i18nPlatformInstance.changeLanguage(locale);
+      onClick={async () => {
+        try {
+          const locale = prompt("Enter platform locale:") || "en";
+          await loadPlatformTranslations(locale);
+          i18nPlatformInstance.changeLanguage(locale);
+        } catch (error) {
+          console.error("Failed to load platform translations:", error);
+          alert("Failed to load translations for locale: " + locale);
+        }
       }}
packages/visual-editor/src/components/Locator.tsx (3)

1224-1236: Use i18next's built-in pluralization instead of manual key selection.

i18next automatically handles pluralization when you pass a count parameter. The manual ternary selection of _one vs _other keys is unnecessary and non-idiomatic.

🔎 Refactor to idiomatic i18next pluralization
           <div>
             {t(
-              resultCount === 1
-                ? "locationWithinDistanceOf_one"
-                : "locationsWithinDistanceOf_other",
-              resultCount === 1
-                ? '{{count}} location within {{distance}} miles of "{{name}}"'
-                : '{{count}} locations within {{distance}} miles of "{{name}}"',
+              "locationWithinDistanceOf",
+              '{{count}} location within {{distance}} miles of "{{name}}"',
               {
                 count: resultCount,
                 distance: selectedDistanceMiles,
                 name: filterDisplayName,
               }
             )}
           </div>

When i18next receives the count parameter, it automatically appends _one, _other, etc. to the base key based on the count value. The translation files should contain both locationWithinDistanceOf_one and locationWithinDistanceOf_other keys.


1241-1250: Use i18next's built-in pluralization instead of manual key selection.

Same issue as above—manual selection defeats i18next's automatic pluralization feature.

🔎 Refactor to idiomatic i18next pluralization
           <div>
             {t(
-              resultCount === 1 ? "locationNear_one" : "locationsNear_other",
-              resultCount === 1
-                ? '{{count}} location near "{{name}}"'
-                : '{{count}} locations near "{{name}}"',
+              "locationNear",
+              '{{count}} location near "{{name}}"',
               {
                 count: resultCount,
                 name: filterDisplayName,
               }
             )}
           </div>

1257-1265: Use i18next's built-in pluralization instead of manual key selection.

Third occurrence of manual plural handling. i18next handles this automatically.

🔎 Refactor to idiomatic i18next pluralization
         <div>
           {t(
-            resultCount === 1
-              ? "locationWithCount_one"
-              : "locationWithCount_other",
-            resultCount === 1 ? "{{count}} location" : "{{count}} locations",
+            "locationWithCount",
+            "{{count}} location",
             {
               count: resultCount,
             }
           )}
         </div>
packages/visual-editor/locales/platform/zh/visual-editor.json (1)

494-502: The inconsistency between footerSocialLinks.twitter and socialLinks.xLink appears intentional.

Both objects exist across all locale files (en, zh, zh-TW, etc.) with the same pattern: footerSocialLinks uses the "twitter" key while socialLinks uses "xLink". This is a deliberate design choice, likely for backward compatibility or different UI contexts. Additionally, no code in the repository directly accesses these locale keys, so the structural inconsistency poses no runtime risk.

If standardization is desired for maintainability, both objects should use "xLink" consistently. Otherwise, this is acceptable as-is.

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

659-667: Consider consolidating duplicate social link translations.

The socialLinks block (lines 659-667) contains translations that are nearly identical to footerSocialLinks (lines 494-502), with only the Twitter/X key differing. This duplication could increase maintenance burden when translations need to be updated.

Consider refactoring to:

  1. Use a single shared social links object with the Twitter/X distinction handled programmatically
  2. Or clearly document why both blocks are necessary if they serve different UI contexts
💡 Potential consolidation approach

If both blocks are truly necessary, at least add a comment explaining the distinction:

+ // Social links for footer component (uses legacy 'twitter' key)
  "footerSocialLinks": {
    "facebook": "Følg oss på Facebook",
    ...
  },
  ...
+ // Social links for general use (uses modern 'xLink' for X/Twitter)
  "socialLinks": {
    "facebook": "Følg oss på Facebook",
    ...
  }

Alternatively, consider a structure that eliminates duplication:

"socialLinks": {
  "shared": {
    "facebook": "Følg oss på Facebook",
    "instagram": "Følg oss på Instagram",
    "linkedIn": "Følg oss på LinkedIn",
    "pinterest": "Følg oss på Pinterest",
    "tiktok": "Følg oss på TikTok",
    "youtube": "Abonner på vår YouTube-kanal"
  },
  "twitter": "Følg oss på Twitter",
  "xLink": "Følg oss på X (Twitter)"
}

494-502: Document the intentional use of twitter vs xLink keys in different contexts.

The footerSocialLinks block uses the key twitter (line 500), while the socialLinks block uses xLink (line 665). This distinction is intentional—the Footer component references footerSocialLinks.twitter, while other components (SocialLinksSlot) reference socialLinks.xLink as part of the Twitter → X rebrand migration. This pattern is consistent across all 28+ language files.

To reduce potential confusion for maintainers, add inline documentation (comments) explaining:

  1. Why footerSocialLinks retains "twitter" (legacy/backwards compatibility context)
  2. Why socialLinks uses "xLink" (new X branding context)
  3. Which keys are used by which components
packages/visual-editor/locales/components/cs/visual-editor.json (1)

1-42: Component translations are well-structured for runtime use.

This new component-level Czech translation file is well-organized and contains an appropriate focused subset of translations for frontend components (locator, search, social links, etc.). The JSON structure is valid and the translations follow consistent Czech patterns.

Note: The duplication concern regarding footerSocialLinks and socialLinks also appearing in the platform file has been flagged in the platform file review.

Optional: Consider native speaker verification

While the translations appear well-formed and consistent, consider having a native Czech speaker verify the accuracy and natural phrasing of these translations, particularly for:

  • Social link call-to-actions ("Sledujte nás na..." / "Přihlaste se k odběru...")
  • Locator-specific phrases ("Pomocí našeho lokátoru najdete místo ve vašem okolí")
packages/visual-editor/src/components/footer/FooterSocialLinksSlot.tsx (1)

28-34: Consider extracting the socialLink type to a shared location.

The socialLink type definition is similar to the one in Footer.tsx. If these components evolve together, extracting this type to a shared types file could improve maintainability and ensure consistency.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a96b0b0 and 1464253.

📒 Files selected for processing (57)
  • packages/visual-editor/locales/components/cs/visual-editor.json
  • packages/visual-editor/locales/components/da/visual-editor.json
  • packages/visual-editor/locales/components/de/visual-editor.json
  • packages/visual-editor/locales/components/en-GB/visual-editor.json
  • packages/visual-editor/locales/components/en/visual-editor.json
  • packages/visual-editor/locales/components/es/visual-editor.json
  • packages/visual-editor/locales/components/et/visual-editor.json
  • packages/visual-editor/locales/components/fi/visual-editor.json
  • packages/visual-editor/locales/components/fr/visual-editor.json
  • packages/visual-editor/locales/components/hr/visual-editor.json
  • packages/visual-editor/locales/components/hu/visual-editor.json
  • packages/visual-editor/locales/components/it/visual-editor.json
  • packages/visual-editor/locales/components/ja/visual-editor.json
  • packages/visual-editor/locales/components/lt/visual-editor.json
  • packages/visual-editor/locales/components/lv/visual-editor.json
  • packages/visual-editor/locales/components/nb/visual-editor.json
  • packages/visual-editor/locales/components/nl/visual-editor.json
  • packages/visual-editor/locales/components/pl/visual-editor.json
  • packages/visual-editor/locales/components/pt/visual-editor.json
  • packages/visual-editor/locales/components/ro/visual-editor.json
  • packages/visual-editor/locales/components/sk/visual-editor.json
  • packages/visual-editor/locales/components/sv/visual-editor.json
  • packages/visual-editor/locales/components/tr/visual-editor.json
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json
  • packages/visual-editor/locales/components/zh/visual-editor.json
  • packages/visual-editor/locales/platform/cs/visual-editor.json
  • packages/visual-editor/locales/platform/da/visual-editor.json
  • packages/visual-editor/locales/platform/de/visual-editor.json
  • packages/visual-editor/locales/platform/en-GB/visual-editor.json
  • packages/visual-editor/locales/platform/en/visual-editor.json
  • packages/visual-editor/locales/platform/es/visual-editor.json
  • packages/visual-editor/locales/platform/et/visual-editor.json
  • packages/visual-editor/locales/platform/fi/visual-editor.json
  • packages/visual-editor/locales/platform/fr/visual-editor.json
  • packages/visual-editor/locales/platform/hr/visual-editor.json
  • packages/visual-editor/locales/platform/hu/visual-editor.json
  • packages/visual-editor/locales/platform/it/visual-editor.json
  • packages/visual-editor/locales/platform/ja/visual-editor.json
  • packages/visual-editor/locales/platform/lt/visual-editor.json
  • packages/visual-editor/locales/platform/lv/visual-editor.json
  • packages/visual-editor/locales/platform/nb/visual-editor.json
  • packages/visual-editor/locales/platform/nl/visual-editor.json
  • packages/visual-editor/locales/platform/pl/visual-editor.json
  • packages/visual-editor/locales/platform/pt/visual-editor.json
  • packages/visual-editor/locales/platform/ro/visual-editor.json
  • packages/visual-editor/locales/platform/sk/visual-editor.json
  • packages/visual-editor/locales/platform/sv/visual-editor.json
  • packages/visual-editor/locales/platform/tr/visual-editor.json
  • packages/visual-editor/locales/platform/zh-TW/visual-editor.json
  • packages/visual-editor/locales/platform/zh/visual-editor.json
  • packages/visual-editor/package.json
  • packages/visual-editor/scripts/copyPlatformTranslations.ts
  • packages/visual-editor/src/components/Locator.tsx
  • packages/visual-editor/src/components/footer/Footer.tsx
  • packages/visual-editor/src/components/footer/FooterSocialLinksSlot.tsx
  • packages/visual-editor/src/components/pageSections/NearbyLocations/NearbyLocationsCardsWrapper.tsx
  • packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx
✅ Files skipped from review due to trivial changes (1)
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/visual-editor/locales/platform/tr/visual-editor.json
  • packages/visual-editor/locales/components/ro/visual-editor.json
  • packages/visual-editor/locales/components/pl/visual-editor.json
  • packages/visual-editor/locales/components/pt/visual-editor.json
  • packages/visual-editor/locales/components/lt/visual-editor.json
  • packages/visual-editor/locales/components/sk/visual-editor.json
  • packages/visual-editor/locales/components/hr/visual-editor.json
  • packages/visual-editor/locales/components/da/visual-editor.json
  • packages/visual-editor/locales/platform/nl/visual-editor.json
  • packages/visual-editor/locales/components/en-GB/visual-editor.json
  • packages/visual-editor/locales/components/ja/visual-editor.json
  • packages/visual-editor/locales/components/zh/visual-editor.json
  • packages/visual-editor/locales/components/sv/visual-editor.json
  • packages/visual-editor/scripts/copyPlatformTranslations.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-23T16:36:42.670Z
Learnt from: benlife5
Repo: yext/visual-editor PR: 958
File: packages/visual-editor/locales/ro/visual-editor.json:394-394
Timestamp: 2025-12-23T16:36:42.670Z
Learning: In Romanian locale files (ro), "Top" is an acceptable translation for directional terms like "top_direction" rather than the native Romanian "Sus". The maintainer benlife5 confirmed this is the preferred translation in packages/visual-editor/locales/ro/visual-editor.json.

Applied to files:

  • packages/visual-editor/locales/platform/ro/visual-editor.json
  • packages/visual-editor/locales/platform/et/visual-editor.json
📚 Learning: 2025-12-15T20:59:25.571Z
Learnt from: benlife5
Repo: yext/visual-editor PR: 943
File: packages/visual-editor/src/components/contentBlocks/image/Image.tsx:175-191
Timestamp: 2025-12-15T20:59:25.571Z
Learning: In the ImageWrapper component at packages/visual-editor/src/components/contentBlocks/image/Image.tsx, when an Image is wrapped in a MaybeLink, the aria-label should be omitted because the image's alt text serves as the accessible name for the link. Adding an aria-label would override the image's alt text.

Applied to files:

  • packages/visual-editor/src/components/footer/Footer.tsx
  • packages/visual-editor/src/components/footer/FooterSocialLinksSlot.tsx
📚 Learning: 2025-10-29T22:00:03.843Z
Learnt from: mkouzel-yext
Repo: yext/visual-editor PR: 833
File: packages/visual-editor/src/components/Locator.tsx:1050-1057
Timestamp: 2025-10-29T22:00:03.843Z
Learning: In packages/visual-editor/src/components/Locator.tsx, the AppliedFilters component is intentionally rendered in two locations (inside the filter modal and outside it) as per the design requirements. This dual rendering should not be flagged as a duplicate issue.

Applied to files:

  • packages/visual-editor/src/components/Locator.tsx
🧬 Code graph analysis (1)
packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (3)
packages/visual-editor/src/utils/i18n/components.ts (2)
  • loadComponentTranslations (77-94)
  • i18nComponentsInstance (6-6)
packages/visual-editor/src/utils/i18n/index.ts (3)
  • i18nComponentsInstance (1-1)
  • i18nPlatformInstance (3-3)
  • pt (6-6)
packages/visual-editor/src/utils/i18n/platform.ts (3)
  • loadPlatformTranslations (58-73)
  • i18nPlatformInstance (7-7)
  • pt (100-141)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: call_unit_test / unit_tests (20.x)
  • GitHub Check: semgrep/ci
🔇 Additional comments (53)
packages/visual-editor/locales/platform/ro/visual-editor.json (1)

494-502: LGTM! Romanian translations are accurate and consistent.

The social media link translations are correctly formatted and use appropriate Romanian phrasing:

  • "Urmărește-ne pe [Platform]" (Follow us on [Platform]) for most social media
  • "Abonați-vă la canalul nostru YouTube" (Subscribe to our YouTube channel) for YouTube

The distinction between footerSocialLinks.twitter and socialLinks.xLink appropriately handles the Twitter→X rebrand for different contexts.

Also applies to: 659-667

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

1-42: The remaining translations are accurate.

The rest of the Italian translations appear grammatically correct and appropriately localized, including:

  • Days of the week with proper accents (Venerdì, Martedì, Mercoledì, Giovedì, Sabato, Domenica)
  • Social media links with correct phrasing ("Seguici su..." / "Iscriviti al nostro canale...")
  • UI strings and search-related phrases
packages/visual-editor/src/components/pageSections/NearbyLocations/NearbyLocationsCardsWrapper.tsx (1)

91-91: LGTM! Capitalization improves consistency.

The label change from "styles" to "Styles" aligns with the capitalization pattern used by all other field labels in this component (e.g., "Data", "Radius (Miles)", "Limit", "Background Color"), improving UI consistency.

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

484-484: Verify the translation change is correct.

The translation changed from "Suodattaa" (infinitive: "to filter") to "Suodata" (imperative: "filter"). For UI actions, the imperative form is typically more appropriate, so this change appears correct. However, since translation accuracy is critical for user experience, please verify with a Finnish native speaker or locale expert.

packages/visual-editor/package.json (2)

58-58: LGTM! Good formatting practice.

The trailing comma addition is a minor formatting improvement that makes future additions cleaner and follows JSON best practices.


59-59: Script file exists and follows established patterns.

The new i18n:copy-platform-translations script is well-structured, with consistent naming convention and command structure matching other i18n scripts in the configuration.

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

666-674: LGTM! Translations are accurate.

The Danish translations are correct and follow a consistent pattern. The use of xLink with "Følg os på X (Twitter)" appropriately handles Twitter's rebrand while maintaining user clarity.

Note: This block duplicates footerSocialLinks (lines 501-509) except for the twitter/xLink difference—see comment on that section regarding verification.

packages/visual-editor/src/internal/puck/components/LayoutHeader.tsx (2)

16-25: LGTM! Imports correctly updated for dynamic translation loading.

The addition of loadComponentTranslations and loadPlatformTranslations imports aligns with the PR objective to load translations on-demand rather than bundling all locales upfront.


348-354: LGTM! Correctly maintains uppercase convention for category labels.

Applying .toUpperCase() to the translated strings ensures consistency with the original uppercase format of "PAGE SECTIONS" and "OTHER" labels in the UI.

packages/visual-editor/locales/platform/es/visual-editor.json (4)

493-501: LGTM! Well-structured social link translations.

The Spanish translations for footer social links are grammatically correct and follow appropriate conventions. The use of "Síguenos en" (Follow us on) for most platforms and "Suscríbete a nuestro canal de YouTube" (Subscribe to our YouTube channel) for YouTube is contextually appropriate.


564-564: Good grammar correction.

The change from "Abrir 24 horas" (infinitive form) to "Abierto 24 horas" (adjective form) is grammatically correct and more natural in Spanish for describing business hours.


658-666: LGTM! Social links properly reflect platform updates.

The translations are correct and appropriately differentiate from footerSocialLinks by using xLink ("Síguenos en X (Twitter)") instead of twitter, reflecting the platform rebrand while maintaining clarity for Spanish-speaking users.


759-759: Previously flagged issue has been resolved.

The past review comment mentioned that the translation for useOurLocatorToFindALocationNearYou was empty. This has been addressed—the key now contains a proper Spanish translation.

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

1-38: LGTM! Translation structure and most strings are correct.

The JSON structure is well-formed, and the translations are accurate and natural. The previous issue with "Abierto 24 horas" (Line 19) has been correctly addressed using the adjective form.

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

7-15: Social links translations are well-structured.

The translations appropriately use "Suivez-nous sur..." (Follow us on...) for social platforms and "Abonnez-vous à notre chaîne YouTube" (Subscribe to our YouTube channel) for YouTube, which is more natural in French. The distinction between "twitter" and "xLink" keys properly reflects Twitter's rebranding to X.

Also applies to: 26-34

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

493-501: LGTM! Social links additions maintain consistency.

The new footerSocialLinks and socialLinks blocks use appropriate French translations that are consistent with the component-level locale file. The translations follow proper French conventions and maintain the appropriate distinction between Twitter-branded and X-branded links.

Also applies to: 659-667

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

1-42: JSON structure looks good.

The file structure is valid, well-organized with nested objects for social link translations, and follows the expected pattern for locale resources in this i18n refactoring effort.


7-15: This is an intentional pattern, not an inconsistency.

The naming difference between footerSocialLinks.twitter and socialLinks.xLink is consistent across all 26 locale files and reflects Twitter's rebrand to X. The xLink translation clarifies the mapping (e.g., "Kövess minket az X-en (Twitter)"). Different components use different key names by design—this is not a bug and will not cause runtime issues if components are properly mapped to their respective keys.

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

495-503: This inconsistency is intentional and by design.

The footerSocialLinks object with the "twitter" key is used by the legacy Footer component (packages/visual-editor/src/components/footer/Footer.tsx), while the socialLinks object with the "xLink" key is used by the newer FooterSocialLinksSlot component (packages/visual-editor/src/components/footer/FooterSocialLinksSlot.tsx). The migration file 0042_expanded_footer_slots.ts indicates a deliberate transition to the expanded footer slots implementation. Both translations are needed to support both the legacy and modern footer components.

packages/visual-editor/locales/components/fi/visual-editor.json (5)

1-6: Previous translation issues successfully resolved.

The previously flagged issues for "closesAt" (Line 4: now correctly uses "Sulkeutuu kello" instead of the inappropriate "jhk" abbreviation) and "filter" (Line 6: now correctly uses the imperative "Suodata" instead of infinitive "Suodattaa") have been properly addressed. The translations in this section are now accurate and follow Finnish UI conventions.


7-15: LGTM! Social media translations are accurate.

The footerSocialLinks translations correctly use "Seuraa meitä" (Follow us) with appropriate Finnish locative case endings, and YouTube appropriately uses "Tilaa" (Subscribe) instead of "Follow". All translations are natural and grammatically correct.


16-25: Weekday capitalization consistency achieved.

The previously flagged capitalization inconsistency (Line 22: "Lauantai") has been corrected to "lauantai", ensuring all weekday names follow consistent lowercase formatting. All other translations in this section (directions, hours, search terms) are accurate and natural Finnish.


26-34: LGTM! socialLinks translations are consistent and up-to-date.

The socialLinks structure appropriately mirrors footerSocialLinks with consistent translations. The "xLink" translation correctly acknowledges the Twitter to X platform transition with "Seuraa meitä X:ssä (Twitter)", maintaining clarity for Finnish users.


35-42: LGTM! Remaining translations are accurate.

All translations in this section are grammatically correct and natural Finnish. The weekday names maintain consistent lowercase formatting, and UI labels like "temporarilyClosed" and "visitPage" are appropriately translated.

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

494-502: LGTM! Footer social links translations added.

The footerSocialLinks group provides appropriate Hungarian translations for footer social media links. The use of "subscribe" for YouTube instead of "follow" is contextually correct.


494-502: No action needed. The footerSocialLinks.twitter and socialLinks.xLink keys serve different components by design:

  • Footer.tsx uses footerSocialLinks.twitter for the legacy footer implementation
  • FooterSocialLinksSlot.tsx uses socialLinks.xLink with updated X/Twitter branding

Both groups are actively used in separate components, and the naming difference is intentional to track the platform's branding transition. This is not an inconsistency requiring standardization.

Likely an incorrect or invalid review comment.

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

1-42: All locale files maintain consistent structure.

Verification confirms all 25 locale files contain the same 36 keys with no mismatches, missing keys, or extra keys. This ensures consistent UI behavior across all supported languages.

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

499-507: Clarify intent of key naming split: "twitter" vs "xLink" across social link objects.

The German translations are accurate. However, both footerSocialLinks and socialLinks objects exist across all 25 platform locales with a consistent pattern: footerSocialLinks uses the "twitter" key while socialLinks uses "xLink". This naming split appears intentional (not a one-off oversight), but the purpose should be clarified:

  • Are these objects designed for different UI contexts where separate key names are appropriate?
  • Or should the keys be unified for consistency?
packages/visual-editor/locales/platform/sk/visual-editor.json (2)

660-668: LGTM! Social links structure correctly reflects the X (Twitter) rebrand.

The socialLinks block properly uses the "xLink" key and includes "X (Twitter)" in the translation text, which correctly reflects the platform's rebrand. The translations follow the consistent Slovak pattern "Sledujte nás na [platform]" used throughout the file.


495-503: The inconsistency between "twitter" and "xLink" keys is intentional and correct.

The footerSocialLinks.twitter key is used by the legacy Footer component, while socialLinks.xLink is used by the newer FooterSocialLinksSlot component. Both components are active in the codebase with different data structures and translation requirements. The locale file correctly reflects this: Footer.tsx references footerSocialLinks.twitter (using the FaTwitter icon), while FooterSocialLinksSlot.tsx references socialLinks.xLink with the FaXTwitter icon. The Slovak translations are accurate for their respective components and require no changes.

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

501-509: Address systematic duplication of social media translation keys across all 26 languages.

Both footerSocialLinks and socialLinks objects are present in both platform and component files for all 26 language variants. This systematic duplication contradicts the PR's goal to "only load necessary translations for the active locale."

Please clarify:

  • Should these social link translations exist only in platform/, only in components/, or in both?
  • If both locations are needed, does the loading mechanism prevent redundant bundling?

Approve once the separation strategy is clarified.

Also applies to: 666-674

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

495-503: Translations look correct; duplication appears intentional for different contexts.

The Polish translations for social links are accurate and properly formatted:

  • "Śledź nas na [platform]" (Follow us on [platform]) for most platforms
  • "Subskrybuj nasz kanał YouTube" (Subscribe to our YouTube channel) for YouTube

The duplication between footerSocialLinks and socialLinks appears intentional to support different UI contexts (footer-specific vs. general social links), which is a common i18n pattern that allows for context-specific customization.

Also applies to: 660-668


495-503: No changes needed. The "twitter" and "xLink" keys serve different components: Footer.tsx uses footerSocialLinks.twitter for the legacy footer, while FooterSocialLinksSlot.tsx uses socialLinks.xLink for the newer slot component. This is an intentional separation with properly localized translations for each context.

Likely an incorrect or invalid review comment.

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

494-502: LGTM! Social link translations added.

The footerSocialLinks block provides Lithuanian translations for social platforms. All translations follow a consistent pattern.

Note: This block uses the twitter key, while the socialLinks block below uses xLink. This appears to be an intentional distinction based on the PR-wide pattern.


659-667: LGTM! Social links group added with X branding.

The socialLinks block mirrors footerSocialLinks but uses xLink (with explicit "X (Twitter)" branding) instead of twitter. This naming distinction appears intentional across the PR's locale structure.

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

1-42: LGTM! Estonian component translations added.

The Estonian component locale file mirrors the structure of the English component locale with proper Estonian translations. All keys are consistently translated.

Note: This file may have the same completeness concerns as the English component locale regarding potentially missing component-level translation keys.

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

494-502: LGTM! Portuguese social link translations added.

Both footerSocialLinks and socialLinks blocks provide proper Portuguese translations. The translations follow natural Portuguese phrasing with "Siga-nos" (follow us) for most platforms and "Inscreva-se" (subscribe) for YouTube.

The expected twitter vs xLink key distinction is properly maintained between the two blocks.

Also applies to: 659-667

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

7-15: LGTM! Turkish social link translations added.

The footerSocialLinks and socialLinks blocks provide proper Turkish translations following the established pattern. Translations use "Bizi [Platform]'ta/de takip edin" (Follow us on [Platform]) consistently.

Also applies to: 26-34

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

495-503: LGTM! Swedish social link translations added.

Both footerSocialLinks and socialLinks blocks provide proper Swedish translations. The translations use "Följ oss på [Platform]" (Follow us on [Platform]) for most entries and "Prenumerera på vår YouTube-kanal" (Subscribe to our YouTube channel) for YouTube.

The expected twitter vs xLink key distinction is maintained.

Also applies to: 660-668

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

494-502: LGTM! Italian social link translations added.

Both footerSocialLinks and socialLinks blocks provide proper Italian translations. The translations use "Seguici su [Platform]" (Follow us on [Platform]) for most entries and "Iscriviti al nostro canale YouTube" (Subscribe to our YouTube channel) for YouTube.

The expected twitter vs xLink key distinction is maintained.

Also applies to: 659-667

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

494-502: LGTM! Estonian platform social link translations added.

Both footerSocialLinks and socialLinks blocks provide proper Estonian translations with correct case endings. The translations use "Jälgi meid [Platform]is" (Follow us on [Platform]) with appropriate Estonian inessive case endings (-is) and "Tellige meie YouTube'i kanal" (Subscribe to our YouTube channel) for YouTube.

The expected twitter vs xLink key distinction is maintained.

Also applies to: 659-667

packages/visual-editor/src/components/footer/FooterSocialLinksSlot.tsx (2)

42-92: LGTM! Translation keys are well-structured.

The ariaLabel values are properly populated using translation keys that match the locale files. The consistent pattern (socialLinks.{platform}) makes the translations easy to maintain across locales.


116-116: Improved accessibility pattern.

Using the pre-computed ariaLabel from the link object is cleaner than constructing it at render time and provides better screen reader support for social media links.

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

1-42: LGTM! Well-structured locale file.

The Latvian translations follow the established pattern with both footerSocialLinks and socialLinks groups. The distinction between twitter (in footerSocialLinks) and xLink (in socialLinks) appears intentional to support both legacy and updated Twitter/X branding.

packages/visual-editor/src/components/footer/Footer.tsx (3)

27-33: Public type extended with ariaLabel field.

The addition of ariaLabel: string to the socialLink type is a public API change. Since socialLink objects are constructed internally and not passed via props, the impact is minimal, but consumers importing this type should be aware of the change.


97-147: Translation integration looks good.

The translation keys follow the footerSocialLinks.* pattern and match the locale files. All translations have appropriate fallback strings, and the hook is properly initialized.


223-223: Improved accessibility pattern.

Delegating ariaLabel generation to the socialLink construction (where translations are loaded) is cleaner than handling it within the FooterSocialIcons component.

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

494-502: LGTM! Consistent locale additions.

The footerSocialLinks and socialLinks translation groups are properly structured and follow the established pattern across locales.

Also applies to: 659-667

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

493-501: LGTM! Properly structured locale additions.

The translation groups are correctly added with appropriate British English localization.

Also applies to: 658-666

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

494-502: LGTM! Consistent platform-level translations.

The Latvian platform translations for social links are properly structured and align with the component-level translations.

Also applies to: 659-667

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

26-26: Minor capitalization improvements.

The updates to applyAll (sentence case) and link (capitalization) improve consistency in the UI text styling.

Also applies to: 517-517


493-501: LGTM! Translation groups properly added.

The footerSocialLinks and socialLinks groups are correctly structured and provide the translations used by Footer.tsx and FooterSocialLinksSlot.tsx.

Also applies to: 649-657


532-537: Removal of English plural variants is safe and correct.

No code explicitly references the removed _few, _many, or _zero variants. These variants are appropriately removed from the English locale since English pluralization only requires _one and _other forms. i18next's default behavior will fall back to _other if any of these forms are requested, so there is no functional risk. Other language files (non-English) correctly retain their plural variants where needed.

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

♻️ Duplicate comments (8)
packages/visual-editor/locales/components/nl/visual-editor.json (1)

43-43: Invisible character still present in translation.

The zero-width space between "een" and "locatie" flagged in the previous review has not been addressed. This invisible character can cause display or text-processing issues.

🔎 Proposed fix
-  "useOurLocatorToFindALocationNearYou": "Gebruik onze locator om een ​​locatie bij u in de buurt te vinden",
+  "useOurLocatorToFindALocationNearYou": "Gebruik onze locator om een locatie bij u in de buurt te vinden",
packages/visual-editor/locales/components/pl/visual-editor.json (1)

24-24: Use declarative form for status indicator, not imperative.

The translation "Otwórz teraz" is in the imperative mood (command), but "openNow" is a status label indicating a location is currently open, not an action button. This should use the adjective/declarative form like other status indicators in this file ("Zamknięte" on line 3, "Otwarte 24 godziny" on line 23).

🔎 Suggested fix
-  "openNow": "Otwórz teraz",
+  "openNow": "Otwarte teraz",

Alternative: "Obecnie otwarte" if you prefer emphasizing "currently."

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

4-4: Incorrect preposition for time expression (previously flagged).

This issue was already identified in a previous review: "Schließt bei" should be "Schließt um" for closing times in German.

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

23-24: Status labels still use imperative verbs instead of adjectives.

Despite being marked as addressed in a previous review, these lines still contain imperative verb forms ("açın" = "open [command]", "aç" = "open [command]") rather than the adjective form needed for status indicators.

Status labels should describe state, not give commands.

🔎 Proposed fix
-  "open24Hours": "24 saat açın",
-  "openNow": "Şimdi aç",
+  "open24Hours": "24 saat açık",
+  "openNow": "Şu anda açık",
packages/visual-editor/locales/components/lt/visual-editor.json (1)

23-24: Replace imperative verb forms with descriptive status indicators.

Lines 23-24 use the imperative verb "Atidarykite" (command form "Open!"), which is grammatically incorrect for status labels. These should use descriptive forms instead:

  • Line 23 "open24Hours": Use "Atvira visą parą" or "Atidaryta 24 valandas"
  • Line 24 "openNow": Use "Atvira dabar" or "Atidaryta dabar"

Status indicators should describe the current state, not issue commands to the user.

🔎 Proposed fix
-  "open24Hours": "Atidarykite 24 valandas",
-  "openNow": "Atidarykite dabar",
+  "open24Hours": "Atvira visą parą",
+  "openNow": "Atvira dabar",
packages/visual-editor/locales/components/ja/visual-editor.json (3)

3-3: Incorrect tense for status indicator (previously flagged).

This translation still uses "閉じた" (past tense "was closed"). For a status indicator, use "閉店" or "休業中" to indicate current state.

🔎 Proposed fix
-  "closed": "閉じた",
+  "closed": "閉店",

24-24: Use status description, not imperative command (previously flagged).

This translation still uses "今開いてください" which means "please open now" (a command). For a status indicator, use "営業中" to show the business is currently open.

🔎 Proposed fix
-  "openNow": "今開いてください",
+  "openNow": "営業中",

40-40: Use present continuous tense for temporary status (previously flagged and reportedly fixed).

This translation still uses "一時的に閉じた" (past tense). The previous review comment indicated this was addressed, but the file still contains the incorrect translation. For an active temporary closure status, use "一時休業中".

🔎 Proposed fix
-  "temporarilyClosed": "一時的に閉じた",
+  "temporarilyClosed": "一時休業中",

Please verify whether the previous fix was properly merged, as the past review indicated this was addressed in commits 8d394ba to 4fd1075.

🧹 Nitpick comments (6)
packages/visual-editor/locales/components/lt/visual-editor.json (1)

18-19: Use consistent prepositions for singular and plural forms.

Lines 18 and 19 are singular/plural variants of the same phrase but use different prepositions:

  • Line 18: "prie" (near/by)
  • Line 19: "šalia" (near/beside)

For consistency, use the same preposition in both forms. Recommend using "šalia" in both as it's more commonly used in location contexts.

🔎 Proposed fix
-  "locationsNear_one": "{{count}} vieta prie „{{name}}"",
+  "locationsNear_one": "{{count}} vieta šalia „{{name}}"",
   "locationsNear_other": "{{count}} vietos šalia „{{name}}"",
packages/visual-editor/locales/components/ja/visual-editor.json (5)

7-15: Inconsistent spacing in social media translations.

Lines 9 and 12 lack a space after the platform name, while other entries have consistent spacing (e.g., "Facebook で", "LinkedIn で"). Consider standardizing spacing for visual consistency.

🔎 Proposed fix
-    "instagram": "Instagramでフォローしてください",
+    "instagram": "Instagram でフォローしてください",
-    "tiktok": "TikTokでフォローしてください",
+    "tiktok": "TikTok でフォローしてください",

20-20: Inconsistent spacing in variable interpolation.

The {{ distance}} has a space before the closing braces but not after the opening braces. Standardize to either {{distance}} or {{ distance }}.

🔎 Proposed fix
-  "locationsWithinDistanceOf_one": "「{{name}}」から {{ distance}} マイル以内の {{count}} 件の場所",
+  "locationsWithinDistanceOf_one": "「{{name}}」から {{distance}} マイル以内の {{count}} 件の場所",

23-23: Use half-width numbers for numeric values.

The translation uses full-width numbers "24" instead of the more standard half-width "24" for numeric values in Japanese text.

🔎 Proposed fix
-  "open24Hours": "24時間営業",
+  "open24Hours": "24時間営業",

29-29: Simplify verb form for button label.

The translation "このエリアを検索します" uses a statement form ("will search"). For a button label, the more concise "このエリアを検索" is more natural and appropriate.

🔎 Proposed fix
-  "searchThisArea": "このエリアを検索します",
+  "searchThisArea": "このエリアを検索",

30-38: Inconsistent spacing in social media translations.

Similar to the footerSocialLinks section, lines 32 and 35 lack spacing after the platform name. Consider standardizing for consistency.

🔎 Proposed fix
-    "instagram": "Instagramでフォローしてください",
+    "instagram": "Instagram でフォローしてください",
-    "tiktok": "TikTokでフォローしてください",
+    "tiktok": "TikTok でフォローしてください",
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1464253 and e2acbfa.

📒 Files selected for processing (25)
  • packages/visual-editor/locales/components/cs/visual-editor.json
  • packages/visual-editor/locales/components/da/visual-editor.json
  • packages/visual-editor/locales/components/de/visual-editor.json
  • packages/visual-editor/locales/components/en-GB/visual-editor.json
  • packages/visual-editor/locales/components/en/visual-editor.json
  • packages/visual-editor/locales/components/es/visual-editor.json
  • packages/visual-editor/locales/components/et/visual-editor.json
  • packages/visual-editor/locales/components/fi/visual-editor.json
  • packages/visual-editor/locales/components/fr/visual-editor.json
  • packages/visual-editor/locales/components/hr/visual-editor.json
  • packages/visual-editor/locales/components/hu/visual-editor.json
  • packages/visual-editor/locales/components/it/visual-editor.json
  • packages/visual-editor/locales/components/ja/visual-editor.json
  • packages/visual-editor/locales/components/lt/visual-editor.json
  • packages/visual-editor/locales/components/lv/visual-editor.json
  • packages/visual-editor/locales/components/nb/visual-editor.json
  • packages/visual-editor/locales/components/nl/visual-editor.json
  • packages/visual-editor/locales/components/pl/visual-editor.json
  • packages/visual-editor/locales/components/pt/visual-editor.json
  • packages/visual-editor/locales/components/ro/visual-editor.json
  • packages/visual-editor/locales/components/sk/visual-editor.json
  • packages/visual-editor/locales/components/sv/visual-editor.json
  • packages/visual-editor/locales/components/tr/visual-editor.json
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json
  • packages/visual-editor/locales/components/zh/visual-editor.json
✅ Files skipped from review due to trivial changes (1)
  • packages/visual-editor/locales/components/pt/visual-editor.json
🚧 Files skipped from review as they are similar to previous changes (15)
  • packages/visual-editor/locales/components/ro/visual-editor.json
  • packages/visual-editor/locales/components/sk/visual-editor.json
  • packages/visual-editor/locales/components/es/visual-editor.json
  • packages/visual-editor/locales/components/hr/visual-editor.json
  • packages/visual-editor/locales/components/zh/visual-editor.json
  • packages/visual-editor/locales/components/da/visual-editor.json
  • packages/visual-editor/locales/components/fi/visual-editor.json
  • packages/visual-editor/locales/components/en/visual-editor.json
  • packages/visual-editor/locales/components/lv/visual-editor.json
  • packages/visual-editor/locales/components/cs/visual-editor.json
  • packages/visual-editor/locales/components/fr/visual-editor.json
  • packages/visual-editor/locales/components/sv/visual-editor.json
  • packages/visual-editor/locales/components/nb/visual-editor.json
  • packages/visual-editor/locales/components/et/visual-editor.json
  • packages/visual-editor/locales/components/zh-TW/visual-editor.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-23T16:36:42.670Z
Learnt from: benlife5
Repo: yext/visual-editor PR: 958
File: packages/visual-editor/locales/ro/visual-editor.json:394-394
Timestamp: 2025-12-23T16:36:42.670Z
Learning: In Romanian locale files (ro), "Top" is an acceptable translation for directional terms like "top_direction" rather than the native Romanian "Sus". The maintainer benlife5 confirmed this is the preferred translation in packages/visual-editor/locales/ro/visual-editor.json.

Applied to files:

  • packages/visual-editor/locales/components/lt/visual-editor.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: call_unit_test / unit_tests (24.x)
  • GitHub Check: call_unit_test / unit_tests (22.x)
  • GitHub Check: call_unit_test / unit_tests (20.x)
  • GitHub Check: create-dev-release
  • GitHub Check: semgrep/ci
🔇 Additional comments (3)
packages/visual-editor/locales/components/en-GB/visual-editor.json (1)

7-15: No action required—the social link key inconsistency is intentional.

The difference between footerSocialLinks.twitter and socialLinks.xLink is consistent across all locale files (en, en-GB, de, etc.), indicating this is a deliberate design pattern. The two groups serve distinct UI contexts: footerSocialLinks maintains the "twitter" key while socialLinks uses the newer "xLink" key with X (Twitter) branding. This is not a maintenance concern or integration issue—the keys are accessed dynamically through i18next at runtime.

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

18-18: Verify article placement in Hungarian.

The structure "{{count}} A hely közelében" places the definite article "A" after the count. Please verify with a native Hungarian speaker that this word order is grammatically correct for the singular form, as Hungarian article usage can be nuanced.


20-21: The use of miles ("mérföldön") is consistent across all locale files in the application, not a Hungarian-specific issue. Every locale—regardless of whether the country uses the metric system—standardizes on miles for distance measurements. This appears to be an intentional design decision by the application.

Likely an incorrect or invalid review comment.

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

Labels

create-dev-release Triggers dev release workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants