# `PhoenixKitEcommerce.ProductSource.Catalogue`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ecommerce/blob/0.5.11/lib/phoenix_kit_ecommerce/product_source/catalogue.ex#L1)

`ProductSource` adapter reading `phoenix_kit_catalogue` items/categories
and returning hand-built `%Product{}`/`%Category{}` view-structs (see
`PhoenixKitEcommerce.ProductSource.Catalogue.View`) so the facade,
`Options`, `PriceDisplay`, `CartItem` and the storefront never need to
know which adapter is active.

Every callback here is read-only: `Query` never writes, and every
view-struct comes back `__meta__: :built` — `Repo.update/preload/delete`
on one is a bug (`update_product/2`/`delete_product/2` already refuse
it). `ProductSource.current/0` only ever returns this module when
`phoenix_kit_catalogue` is loaded, so the direct calls into it below
are safe at runtime; `@compile {:no_warn_undefined, ...}` only
quietens the compiler's static xref check for hosts that don't
declare the optional dependency.

# `translate_filter_label`

```elixir
@spec translate_filter_label(map(), String.t()) :: map()
```

For `attribute_set`/`metadata_option` filters, swaps `"label"` for the
underlying attribute set's translated display name (falling back to
whatever the filter config already had when the set can't be
resolved, or there's no translation) — the sidebar's section header
should read the SET's own (per-language) name, not the single flat
string an admin typed once into `update_storefront_filters/1`. Every
other filter type is returned unchanged.

NOT a `ProductSource` `@behaviour` callback: `PhoenixKitEcommerce.
get_enabled_storefront_filters/2` reaches this via `function_exported?/3`
(mirroring `View.base_currency_code/0`'s pattern for the reverse
direction), so `Legacy` — which has no attribute sets to translate —
needs no matching no-op.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
