Skip to content

feat: Adapts CP client to fetch content for corresponding locale#3165

Merged
hellofanny merged 46 commits intofeat/multilanguagefrom
feat/cp-fetch-content-locale
Feb 3, 2026
Merged

feat: Adapts CP client to fetch content for corresponding locale#3165
hellofanny merged 46 commits intofeat/multilanguagefrom
feat/cp-fetch-content-locale

Conversation

@hellofanny
Copy link
Copy Markdown
Contributor

@hellofanny hellofanny commented Jan 8, 2026

What's the purpose of this pull request?

This PR introduces multi-locale support for content fetching via the Content Platform (CP). It enables the store to fetch localized content dynamically based on the user's current locale.

content-switching.mov

Content Platform Locale Support

Updated the CP client version to @vtex/client-cp: 0.4.0

The ContentService now accepts a locale parameter that gets passed to the Content Platform client, allowing it to fetch locale-specific content:

// packages/core/src/server/content/service.ts
private getClientCP(locale?: string): ClientCP {
  const currentLocale = locale ?? config.localization.defaultLocale
  
  return new ClientCP({
    tenant: config.api.storeId,
    locale: currentLocale, // 👈 Locale-aware client
  })
}

Key Changes:

Content Platform

  • Schema & CMS Updates: Updated schema.json, cms/faststore/components, and cms/faststore/pages with the latest multi-language changes (new localization components and removal of hardcoded labels).
  • ContentParams: Added locale parameter support.
  • Routing & Sections: Passed the locale parameter to Pages, GlobalSections, and LandingPage.
    Note: "My Account" pages were intentionally skipped; a follow-up task will be created for this.

🎗️: When merging the multilanguage branch, run the following in the content account: vtex content generate-schema cms/faststore/components cms/faststore/pages -o cms/faststore/schema.json -l cms/faststore/base.jsonc. Current changes are applied only to brandless acc.

TODO: Testing add a new locale in content platform after default values issues fixed.

Localization Updates

  • Some improvements to useLocalizationConfig.tsx file:
    • Fixed salesChannel type to avoid duplicate queries.
    • Atempts to fix race condition with validateSession in order to testing the languages-switch content (I'll probably create a task to properly handle this issue)

CLI Localization/CP settings

  • Verify when localization is enabled, the contentSource should be "CP"
    • updates packages/cli/src/commands/generate-i18n.ts to reflect this requirement.

How to test it?

Note: There are current limitations being addressed with the CP team.
discovery.config has been committed with a mock for testing.

Setup:

  1. In faststore/packages, run pnpm i and pnpm build. 😬
  2. Ensure the localization flag is enabled.
  3. Run the core locally.
  4. Access the Brandless Admin to make changes.

Content Switching

You should be seeing the homepage like this:
image

  • The default locale is pt-BR.
  • Switch locales using the UI selector or by appending the locale to the URL.
image - Expected Behavior: Content should update based on the locale. If no localized content exists, it should fallback to the default (pt-BR).

Here are the list of the pages/content type that you should verify:

  • Global Section (Avoid changing LocalizationButton settings until we fix the issue - [details]
    For example:
    the Buy now link has the same content when switching.
image image

It's correct, because is using the default Português (Brasil) (Default) for the link text.

You can change it and click in Salvar na main
image

after publishing it, reload the page and verify if the changes were reflected.

  • Homepage
  • LandingPage (can try /teste-landing-page or change/create a new one)
  • PDP
  • PLP (it's breaking because of sortBy section missing in UI/schema - still checking this issue)
  • Search Page (it's breaking because of sortBySelector missing in UI/schema - still checking this issue)
    (https://github.com/vtex/faststore/pull/3165/changes#r2748069043))
  • 404
  • 500

Configuration Validation - Localization/CP settings
in the discovery.config file:

  • Change the contentSource flag to "CMS" or "" while keeping localization.enabled: true.
contentSource: {
    type: "",
  },
 localization: {
    enabled: true,
    defaultLocale: "pt-BR",
    ....
  }

Run node packages/cli/bin/run.js generate-i18n ./packages/core

Expected Behavior: The CLI should throw an error regarding the contentSource requirement.
image

Starters Deploy Preview

[WIP]

Reference:

Jira Task

Summary by CodeRabbit

  • New Features

    • US localization (en‑US + USD) and richer region/locale settings
    • Scroll-to-top button component
    • SEO title templates for Home, Landing, PDP, PLP and Search
  • Improvements

    • Locale-aware content fetching across pages (multi-language support)
    • Navbar: localization button/selector and improved search labels/titles
    • Breadcrumb fallback label and Cart sidebar empty-state texts
    • Product Gallery: new sort options; Product Details: loading/ARIA texts
    • Component schemas expanded with richer metadata/configuration

@codesandbox-ci
Copy link
Copy Markdown

codesandbox-ci Bot commented Jan 8, 2026

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Comment thread packages/core/src/server/content/service.ts Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 21, 2026

Walkthrough

Threads locale through data fetching and content services, adds per-locale ClientCP caching, enriches discovery config and CMS schemas (including ScrollToTopButton), consolidates CLI localization validation, and updates getStaticProps/page fetchers to be locale-aware across the codebase.

Changes

Cohort / File(s) Summary
CLI localization
packages/cli/src/commands/generate-i18n.ts, packages/cli/src/commands/build.ts, packages/cli/src/commands/dev.ts, packages/cli/src/utils/config.ts
Consolidates runtime check into checkAndValidateLocalization(). build/dev now spawn generate-i18n unconditionally and rely on internal validation; config loader reads discovery config, validates localization.enabled, and enforces contentSource.type === 'CP' when localization is enabled.
Discovery config & deps
packages/core/discovery.config.default.js, packages/core/package.json
Expands localization (regions/locales/currencies), switches contentSource to CP, adds cachedOperations, adjusts preview redirects and lighthouse server; bumps @vtex/client-cp.
Content service & server
packages/core/src/server/content/service.ts, packages/core/src/server/content/types.ts, packages/core/src/server/cms/global.ts
Adds per-locale ClientCP cache (clientCPCache + getClientCP(locale)), makes content fetches locale-aware, treats header/footer sections as optional, suppresses some warnings, and adds minimal-global-sections early-return. Adds locale?: string to content params.
Core locale propagation (pages & templates)
packages/core/src/pages/*.tsx, packages/core/src/components/templates/.../LandingPage.tsx, packages/core/src/experimental/searchServerSideFunctions/*, packages/core/src/components/cms/GlobalSections.tsx
getStaticProps and page-level fetchers accept and forward locale; global sections and contentService calls receive locale and locale is included in returned props where applicable. LandingPage and global sections APIs updated to accept optional locale.
CMS component schemas
packages/core/cms/faststore/components/*.jsonc
Adds standard metadata flags (readOnly, writeOnly, deprecated, $abstract) across many component schemas; several components receive new UI/default fields and labels (Breadcrumb, CartSidebar, Navbar, ProductGallery, ProductDetails, etc.).
New component & sections
packages/core/cms/faststore/components/cms_component__scrolltotopbutton.jsonc, packages/core/cms/faststore/sections.json, packages/core/cms/faststore/content-types.json, packages/core/cms/faststore/pages/*.jsonc
Introduces ScrollToTopButton schema; adds SEO titleTemplate fields to multiple page types, slug config entries, explicit icon enums/defaults, and references to ScrollToTopButton in relevant page section anyOf lists.
SDK & product vars
packages/core/src/sdk/localization/useLocalizationConfig.tsx, packages/core/src/sdk/product/useLocalizedVariables.ts
Changes Settings.salesChannel to string, coerces pagination cursor to string, adds sessionStore subscription to re-sync locale/currency/salesChannel bindings and logs session locale for debugging.

Sequence Diagram(s)

sequenceDiagram
    participant Page as Next.js Page
    participant Global as GlobalSections
    participant Service as ContentService
    participant Cache as ClientCP Cache
    participant CP as ClientCP

    Page->>Global: getGlobalSectionsData(previewData, locale)
    Global->>Service: getSingleContent(contentType, { previewData, locale })
    Service->>Cache: getClientCP(locale)
    alt cached
        Cache-->>Service: ClientCP instance
    else create
        Cache->>CP: instantiate ClientCP(locale)
        CP-->>Cache: ClientCP instance
        Cache-->>Service: ClientCP instance
    end
    Service->>CP: getEntry(..., locale)
    CP-->>Service: entry data
    Service-->>Global: resolved locale-aware content
    Global-->>Page: global sections (locale-specific)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • lemagnetic
  • lariciamota
  • renatomaurovtex

"Locale threads through each page and store,
ClientCP caches hum by region and more.
Schemas gain flags, a button springs to top,
Pages now fetch the language you opt.
Quick changes, global reach — FastStore on the floor."

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adapting the CP client to fetch content for the corresponding locale, which is the core objective of this multilingual support PR.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/cp-fetch-content-locale

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.

@hellofanny hellofanny force-pushed the feat/cp-fetch-content-locale branch from 26182a3 to afd76c1 Compare January 27, 2026 02:24
const currentConfig = discoveryConfig?.default ?? discoveryConfig

// Validate contentSource configuration for localization
const shouldUseCP = currentConfig.localization.enabled
Copy link
Copy Markdown
Contributor Author

@hellofanny hellofanny Jan 30, 2026

Choose a reason for hiding this comment

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

If localization is enabled, we will check if the contentSource is CP, if not we will break the build with the message, so the merchant can fix it. :)
Besides, we need to add this as requirement.

thread

}
}
},
"localizationButton": {
Copy link
Copy Markdown
Contributor Author

@hellofanny hellofanny Jan 30, 2026

Choose a reason for hiding this comment

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

⚠️ Do not change the order of 'localizationButton' and 'localizationSelector'. We are waiting for a fix from CP (default values issue). Currently using a workaround to test. [thread]

<symbol id="Ellipsis" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 18" ><circle opacity="0.6" cx="2" cy="11" r="2" fill="currentColor"/><circle opacity="0.6" cx="10" cy="11" r="2" fill="currentColor"/><circle opacity="0.6" cx="18" cy="11" r="2" fill="currentColor"/></symbol>

<symbol id="Envelop" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 256 256"><path fill="none" d="M0 0h256v256H0z"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m224 56-96 88-96-88"/><path d="M32 56h192v136a8 8 0 0 1-8 8H40a8 8 0 0 1-8-8V56h0Zm78.5 72-76 69.7m187 0-76-69.7" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="Envelope" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 256 256"><path fill="none" d="M0 0h256v256H0z"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m224 56-96 88-96-88"/><path d="M32 56h192v136a8 8 0 0 1-8 8H40a8 8 0 0 1-8-8V56h0Zm78.5 72-76 69.7m187 0-76-69.7" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/></symbol>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think we might have missed this change somewhere.
But we have rename this icon id to Envelope

locale: string
currency: { code: string; symbol: string }
salesChannel: number
salesChannel: string
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed because channel value is being serialized inconsistently, causing duplicate ClientManyProductsQuery queries.
re-rending {"salesChannel":"2","regionId":""} then {"salesChannel":2,"regionId":""}

Image

// generated by @faststore/cli when localization is enabled
enabled: true,
defaultLocale: 'pt-BR',
regions: {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adding this mock for testing, since we are testing other binding settings.
I added 2 locales to test:

  • pt-BR and en-US (the pt-BR as defaultLocale)
  • changed the binding url to : http://localhost:3000/pt-BR and http://localhost:3000/en-US to better test locally. I haven't tried with subdomains.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

⚠️ Before committing - undo this changes and leave the default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question: are you going to revert all changes in this file? I ask because there were a lot of changes besides the localization object and that I don't think we should do in this PR -- but if the idea is to revert all changes, then ok!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yess!! I will revert! I just wanted the bindings for pt-BR and en-US to test :)

@hellofanny hellofanny self-assigned this Jan 31, 2026
@hellofanny hellofanny added the enhancement New feature or request label Jan 31, 2026
@hellofanny hellofanny marked this pull request as ready for review January 31, 2026 04:47
@hellofanny hellofanny requested a review from a team as a code owner January 31, 2026 04:47
@hellofanny hellofanny requested review from lemagnetic and ommeirelles and removed request for a team January 31, 2026 04:47
Copy link
Copy Markdown
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: 4

Caution

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

⚠️ Outside diff range comments (2)
packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts (1)

64-73: ⚠️ Potential issue | 🟠 Major

Missing locale in fallback content fetch.

The fallback path omits locale in the getSingleContent call, while the CMS data path (lines 36-43) correctly includes it. This inconsistency means search results won't be locale-aware when storeConfig.cms.data is falsy.

Proposed fix
   const [page, globalSections, globalSectionsHeader, globalSectionsFooter] =
     await Promise.all([
       contentService.getSingleContent<SearchContentType>({
         contentType: 'search',
         previewData,
+        locale,
       }),
       globalSectionsPromise,
       globalSectionsHeaderPromise,
       globalSectionsFooterPromise,
     ])
packages/core/src/components/templates/LandingPage/LandingPage.tsx (1)

123-125: ⚠️ Potential issue | 🔴 Critical

Bug: find callback missing return statement.

The arrow function uses curly braces but doesn't return the comparison result. This causes pageBySlug to always be undefined, making the CMS data path unreachable.

Proposed fix
       const pageBySlug = cmsData['landingPage'].find((page: any) => {
-        slug === page.settings?.seo?.slug
+        return slug === page.settings?.seo?.slug
       })

Or use implicit return:

-      const pageBySlug = cmsData['landingPage'].find((page: any) => {
-        slug === page.settings?.seo?.slug
-      })
+      const pageBySlug = cmsData['landingPage'].find(
+        (page: any) => slug === page.settings?.seo?.slug
+      )
🤖 Fix all issues with AI agents
In `@packages/cli/src/commands/generate-i18n.ts`:
- Around line 119-136: The logger.error message in generate-i18n.ts uses
chalk.yellow('[Error]') (variables involved: shouldUseCP,
currentContentSourceType) but elsewhere the project uses chalk.red('[Error]');
update the logger.error call to use chalk.red('[Error]') so the error color is
consistent and indicates severity, keeping the rest of the message intact
(locate the logger.error invocation that checks shouldUseCP and
currentContentSourceType and replace chalk.yellow with chalk.red).

In `@packages/core/cms/faststore/pages/cms_content_type__globalsections.jsonc`:
- Around line 43-48: Replace the non-descriptive default for the JSON schema
property loadingLabel (title: "Loading Label") which currently uses "…" with an
explicit, accessible string like "Loading…" or "Loading..." so screen readers
and translators get meaningful text; update the "default" value for loadingLabel
to the chosen explicit label and ensure any downstream UI uses loadingLabel for
accessible loading state text.

In `@packages/core/discovery.config.default.js`:
- Around line 37-41: The session defaults are inconsistent:
session.currency.code and symbol currently use USD ('$') while session.locale is
'pt-BR'; update the default so currency matches locale (e.g., set currency.code
to 'BRL' and currency.symbol to 'R$') or change session.locale to a locale that
matches USD; apply the same fix to the other occurrence referenced (the block
around the second currency/locale definition at lines 62-64) and ensure you
update any named exports or constants that reference session.currency or
session.locale so both defaults remain consistent (look for the currency and
locale keys in the exported config object).

In `@packages/core/src/sdk/product/useLocalizedVariables.ts`:
- Line 22: The current expression in useLocalizedVariables (the object property
`after: String(after) ?? '0'`) converts undefined to the string "undefined" and
thus never triggers the ?? fallback; change the order so the nullish fallback is
applied first (e.g., use `after ?? '0'` and then convert to string) wherever
`after` is serialized in useLocalizedVariables to ensure undefined yields "0"
instead of "undefined".
🧹 Nitpick comments (7)
packages/core/src/utils/utilities.ts (1)

10-23: Tighten docs and remove redundant fallback.

Line 10 now accepts nullish input and Line 12 returns '', but the JSDoc still reads string-only. Also Line 23’s ?? '' is redundant because kebabCase is always a string after the early return.

🔧 Suggested tweak
- * `@param` text - The string to convert.
+ * `@param` text - The string to convert. Nullish/empty values return ''.
@@
-  return kebabCase ?? ''
+  return kebabCase
packages/cli/src/commands/generate-i18n.ts (1)

120-122: Consider defensive null check on localization.

If currentConfig.localization is undefined, accessing .enabled will throw. Add optional chaining for resilience against malformed configs.

Defensive improvement
-    const shouldUseCP = currentConfig.localization.enabled
+    const shouldUseCP = currentConfig?.localization?.enabled
packages/core/src/sdk/localization/useLocalizationConfig.tsx (2)

61-67: Remove or guard the debug log before release.
This runs on every settings sync and will spam production consoles.

Proposed change
-    console.log('[useLocalizationConfig] Current session before update:', {
-      locale: session.locale,
-    })

85-113: Normalize salesChannel before comparison to avoid extra session writes.
If the server stores a numeric channel, strict equality against a string will always fail and trigger redundant sessionStore.set churn.

Proposed change
-    const unsubscribe = sessionStore.subscribe((updatedSession) => {
-      const currentChannel = JSON.parse(updatedSession.channel ?? '{}')
+    const unsubscribe = sessionStore.subscribe((updatedSession) => {
+      const currentChannel = JSON.parse(updatedSession.channel ?? '{}') ?? {}
+      const currentSalesChannel = String(currentChannel.salesChannel ?? '')
+      const settingsSalesChannel = String(settings.salesChannel)
 
       // Check if localization got overwritten by validateSession
       const localeMatch = updatedSession.locale === settings.locale
       const currencyMatch = deepEqual(
         updatedSession.currency,
         settings.currency
       )
-      const channelMatch = currentChannel.salesChannel === settings.salesChannel
+      const channelMatch = currentSalesChannel === settingsSalesChannel
 
       if (!localeMatch || !currencyMatch || !channelMatch) {
         // Re-apply the correct binding settings
-        const channel = JSON.parse(updatedSession.channel ?? '{}')
-        channel.salesChannel = settings.salesChannel
+        const channel = JSON.parse(updatedSession.channel ?? '{}') ?? {}
+        channel.salesChannel = settingsSalesChannel
 
         sessionStore.set({
           ...updatedSession,
           locale: settings.locale,
           currency: settings.currency,
           channel: JSON.stringify(channel),
         })
       }
     })
packages/core/src/server/cms/global.ts (1)

15-22: Consider gating the dev-only warning to avoid prod log noise.
If this fallback is mainly for development, wrap the warning (or the whole branch) behind a non‑prod check.

♻️ Example guard
-    console.warn(
-      'Global Sections content type was not found or has no sections. Returning minimal structure for development.'
-    )
+    if (process.env.NODE_ENV !== 'production') {
+      console.warn(
+        'Global Sections content type was not found or has no sections. Returning minimal structure for development.'
+      )
+    }
packages/core/src/server/content/service.ts (1)

25-31: Guard cached client retrieval to keep types safe.

Map.has() does not narrow the return type of Map.get() in TypeScript—the method always returns ClientCP | undefined. Assigning to a local variable and checking it preserves type safety.

♻️ Proposed refactor
-    if (this.clientCPCache.has(currentLocale)) {
-      return this.clientCPCache.get(currentLocale)
-    }
+    const cachedClient = this.clientCPCache.get(currentLocale)
+    if (cachedClient) {
+      return cachedClient
+    }
packages/core/discovery.config.default.js (1)

132-136: EUR currency defined but unused.

The EUR currency is defined but no locale binding references it. If this is intentional for future use, consider adding a comment. Otherwise, it can be removed to avoid confusion.

Comment thread packages/cli/src/commands/generate-i18n.ts Outdated
Comment on lines +43 to 48
},
"loadingLabel": {
"title": "Loading Label",
"type": "string",
"default": "..."
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use a descriptive loading label instead of "…".
Ellipsis isn’t meaningful for screen readers or translation; prefer explicit text (e.g., “Loading…”).

🔧 Suggested tweak
-              "default": "..."
+              "default": "Loading..."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
},
"loadingLabel": {
"title": "Loading Label",
"type": "string",
"default": "..."
}
},
"loadingLabel": {
"title": "Loading Label",
"type": "string",
"default": "Loading..."
}
🤖 Prompt for AI Agents
In `@packages/core/cms/faststore/pages/cms_content_type__globalsections.jsonc`
around lines 43 - 48, Replace the non-descriptive default for the JSON schema
property loadingLabel (title: "Loading Label") which currently uses "…" with an
explicit, accessible string like "Loading…" or "Loading..." so screen readers
and translators get meaningful text; update the "default" value for loadingLabel
to the chosen explicit label and ensure any downstream UI uses loadingLabel for
accessible loading state text.

Comment thread packages/core/discovery.config.default.js Outdated
Comment thread packages/core/src/sdk/product/useLocalizedVariables.ts Outdated
return {
first: first ?? ITEMS_PER_SECTION,
after: String(after) ?? '0',
after: String(after ?? 0),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was having trouble with the content return type. Although CP team has fixed for the default value, I thought it was good idea to keep this type check to avoid passing the wrong type and break the queries.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/cli/src/commands/dev.ts`:
- Around line 205-209: The spawnSync call running "node ${cliPath}
generate-i18n" in the dev command lacks error handling; change it to capture the
return value (e.g., scriptResult = spawnSync(...)) and then check
scriptResult.error or scriptResult.status !== 0, logging an error and exiting
(process.exit(1)) on failure—mirror the error/status checks used in build.ts so
a failed i18n generation halts the dev flow and surfaces the failure.

In `@packages/cli/src/utils/config.ts`:
- Around line 60-62: The code calls toUpperCase() on config?.contentSource?.type
without ensuring it's a string, which can throw for undefined or non-string
types; update the logic around currentContentSourceType (derived from
config?.contentSource?.type) to first coerce or guard: check typeof
config?.contentSource?.type === 'string' (or use String(...)) before calling
toUpperCase(), and treat non-string values as invalid so the subsequent if
(currentContentSourceType !== 'CP') path still runs reliably; adjust the
variable currentContentSourceType and any downstream checks to use the safe,
validated value.
🧹 Nitpick comments (1)
packages/cli/src/utils/config.ts (1)

16-47: Consider adding a typed interface for the discovery config.

Multiple uses of any (lines 16, 45, 55) reduce type safety. A simple interface would catch config issues at compile time:

interface DiscoveryConfig {
  localization?: {
    enabled?: boolean
  }
  contentSource?: {
    type?: string
  }
}

Comment thread packages/cli/src/commands/dev.ts
Comment thread packages/cli/src/utils/config.ts
Comment thread packages/cli/src/utils/config.ts Outdated
Comment thread packages/cli/src/commands/generate-i18n.ts
Comment thread packages/cli/src/utils/config.ts
Comment thread packages/cli/src/utils/config.ts Outdated
Comment thread packages/cli/src/utils/config.ts Outdated
Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@packages/cli/src/utils/config.ts`:
- Around line 84-96: The function checkAndValidateLocalization currently returns
an undefined symbol enabled; replace that with a computed boolean by calling
isLocalizationEnabled(config) after validateContentSourceForLocalization
returns, e.g., compute const enabled = isLocalizationEnabled(config) and return
it. Ensure you still await getDiscoveryConfig(basePath) and call
validateContentSourceForLocalization(config) before computing enabled so the
function uses the validated config and returns the correct boolean.
🧹 Nitpick comments (1)
packages/core/src/server/cms/global.ts (1)

10-33: Type any weakens type safety for settings.

The settings?: any parameter bypasses TypeScript's type checking. Consider extracting the settings type from GlobalSectionsData to maintain consistency.

♻️ Proposed type improvement
+type GlobalSectionsSettings = GlobalSectionsData['settings']
+
 function createMinimalGlobalSections({
   globalSectionsHeader,
   globalSectionsFooter,
   settings,
 }: {
   globalSectionsHeader: GlobalSectionsData
   globalSectionsFooter: GlobalSectionsData
-  settings?: any
+  settings?: GlobalSectionsSettings
 }): GlobalSectionsData {

As per coding guidelines, TypeScript files should "Ensure type safety and avoid type assertions when possible."

Comment thread packages/cli/src/utils/config.ts Outdated
hellofanny and others added 2 commits February 3, 2026 14:50
Co-authored-by: Larícia Mota <laricia.mota@vtex.com.br>
@hellofanny hellofanny force-pushed the feat/cp-fetch-content-locale branch from cf2b7d3 to ac1a40f Compare February 3, 2026 18:05
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (1)
packages/cli/src/utils/config.ts (1)

37-41: ⚠️ Potential issue | 🟠 Major

Fix dynamic import to work on Windows.
import(configPath) with OS paths containing backslashes fails on Windows; pathToFileURL() converts the path to a valid file URL for cross-platform compatibility. This breaks localization detection on Windows.

🔧 Proposed fix
import path from 'path'
+import { pathToFileURL } from 'url'

import { withBasePath } from './directory'
@@
-        const discoveryConfig = await import(configPath)
+        const discoveryConfig = await import(pathToFileURL(configPath).href)

@hellofanny hellofanny merged commit 046dada into feat/multilanguage Feb 3, 2026
4 of 5 checks passed
@hellofanny hellofanny deleted the feat/cp-fetch-content-locale branch February 3, 2026 19:54
@lemagnetic lemagnetic restored the feat/cp-fetch-content-locale branch February 9, 2026 17:21
@lemagnetic lemagnetic deleted the feat/cp-fetch-content-locale branch February 9, 2026 17:25
@hellofanny hellofanny restored the feat/cp-fetch-content-locale branch February 19, 2026 14:47
lemagnetic added a commit that referenced this pull request Mar 5, 2026
## What's the purpose of this pull request?

Removing hardcoded labels:
- #3099
- #3102 
- #3107 
- #3104 
- #3103 
- #3125
- #3131
- #3116
- #3142
- #3192

Setting Up locales
- #3141
- #3143
- #3147
- #3156
- #3162
- #3145
- #3164
- #3169
- #3171
- #3176
- #3180
- #3169
 custom path
- #3185
- #3162
- #3156
- #3170

Components
- #3093
- #3175

Fetching content 

- #3165

Others
- #3176
- #3171
- #3181
- #3189
- #3205


## How to test locally?
- Run `pnpm I` (install all the new dependencies and needed packages)
- If you want to try localization feature, go
to`/discovery.config.default.js`:
Enable localization:
```
localization: {
  enabled: true
}
```
- Run `node packages/cli/bin/run.js generate-i18n ./packages/core` to
fetch the bindings

If the contentSource is not set to content platform yet, you will see a
message to update to it.
>   contentSource: {
>     type: 'CP',
>   },

⚠️ Note: Ensure the url is set to localhost for local testing. These
locale bindings are generated in `discovery.config` after running the
generate-i18n command.

```diff
localization: {
  enabled: true,
  defaultLocale: 'en-US',
   regions: {...},
    locales: {
      'pt-BR': {
           ...
        bindings: [
          {
            currencyCode: 'BRL',
-           url: 'https://brandless.fast.store/pt-BR',
+           url: 'http://localhost:3000/pt-BR',
            salesChannel: '2',
            isDefault: true,
            locales: [
              {
                code: 'pt-BR',
                isDefault: true,
              },
            ],
          },
        ],
      },
      'it-IT': {
        ...
        bindings: [
          {
            currencyCode: 'EUR',
-           url: 'https://brandless.fast.store/it-IT',
+           url: 'http://localhost:3000/it-IT',
            salesChannel: '3',
            isDefault: true,
            locales: [
              {
                code: 'it-IT',
                isDefault: true,
              },
            ],
          },
          {
            currencyCode: 'EUR',
-           url: 'https://brandless.fast.store/europe/it',
+           url: 'http://localhost:3000/europe/it',
            salesChannel: '3',
            isDefault: false,
            locales: [
              {
                code: 'it-IT',
                isDefault: true,
              },
            ],
          },
        ],
      },
      'en-US': {
        code: 'en-US',
        name: 'English',
        languageCode: 'en',
        languageName: 'English',
        script: 'Latn',
        textDirection: 'ltr',
        regionCode: 'US',
        bindings: [
          {
            currencyCode: 'USD',
-           url: 'https://brandless.fast.store',
+           url: 'http://localhost:3000,
            salesChannel: '1',
            isDefault: true,
            locales: [
              {
                code: 'en-US',
                isDefault: true,
              },
            ],
          },
        ],
      },
    ...
}
```

- Go to /packages/core and run `npmn dev`

---------

Co-authored-by: Larícia Mota <laricia.mota@vtex.com.br>
Co-authored-by: Leandro Rodrigues <leandro.rodrigues@vtex.com>
Co-authored-by: Otavio Moreira Meirelles <otavio.meirelles@vtex.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants