Brandfine Docs
SDK

Resolvers

Locale helpers and the navigation resolver.

import {
  pickLocale,
  localizePath,
  stripLocalePrefix,
  isLocale,
  resolveNavigation,
} from '@brandfine/client/resolvers'

All pure functions — no I/O, no side effects, no module-level state. Each takes the consumer's locale config as an option.

Locale helpers

const opts = { locales: ['en', 'pt'], defaultLocale: 'en' } as const

// Coerce unknown input to a known locale, fallback to default.
pickLocale(Astro.currentLocale, opts) // → 'en' | 'pt'

// Add the locale prefix to a path.
localizePath('/services/uk-eta', 'pt', opts) // → '/pt/services/uk-eta'
localizePath('/services/uk-eta', 'en', opts) // → '/services/uk-eta' (default = bare)

// Strip a non-default locale prefix.
stripLocalePrefix('/pt/about', opts) // → '/about'
stripLocalePrefix('/about', opts)    // → '/about'

// Type guard.
if (isLocale(value, opts.locales)) { /* value: string */ }

Turns the API's locale-agnostic shape into a per-locale render-ready tree:

const nav = await bf.navigations.get('header')
if (!nav) {/* render hardcoded fallback */}

const hydrated = resolveNavigation(nav, 'pt', {
  defaultLocale: 'en',
})

// hydrated.items: HydratedNavItem[]
// Each item: { href: string | null, label: string, type, children }

What the resolver does

  • POST items — picks the sibling for the active locale, builds /<postTypeSlug>/<slug> via localizePath. Falls back to the default-locale URL when no translation exists.
  • CUSTOM_URL items — runs paths through localizePath; external URLs (http://, mailto:) pass through unchanged.
  • HEADING itemshref: null, label-only.
  • Labels — picks the active-locale label, falls back to default-locale, then to any populated label (last resort).
  • Hidden locales — items with the active locale in hiddenLocales are dropped from the tree.

Custom URL conventions

Override urlForPost when your consumer doesn't use the default /<postTypeSlug>/<slug> URL shape:

const hydrated = resolveNavigation(nav, 'pt', {
  defaultLocale: 'en',
  urlForPost: ({ post, sibling }) =>
    `/blog/${sibling.slug}`, // ignore post type, always under /blog
})

Most consumers won't need this — the default convention matches what localizePath expects.

On this page