Table of contents :

Multilingual Product Search with Weaviate

100-days-of-weaviate-020

Table of contents :

WooCommerce stores often contain product information in several languages: translated titles, localized descriptions, category names, attributes, and search synonyms. A multilingual vector search layer can connect a shopper’s query with the right product even when the wording differs across languages.

Weaviate is useful for this because the same product can be represented as a semantic vector while retaining structured properties for filtering, sorting, stock checks, and WooCommerce identifiers.

Design the product representation

Start by deciding which localized fields should contribute to the product vector. A practical representation usually includes the product name, short description, long description, categories, attributes, and relevant search keywords. Keep operational fields such as SKU, price, stock status, language availability, and product URL as properties rather than mixing them into the searchable text.

Product text for vectorization:
Name: Waterproof hiking jacket
Category: Outdoor clothing
Attributes: breathable, lightweight, hooded
Description: A waterproof shell for hiking in wet and windy conditions.
Search terms: rain jacket, trekking jacket

For multilingual catalogs, either create one document containing all approved translations or create a language-specific document for each product-language pair. The second approach gives agencies more control over language filtering and result presentation.

One document per product

A single product object is simpler when the translated content describes the same item and shoppers may search in any supported language. Store localized values in separate properties, such as name_en, name_fr, and name_de, then build a combined source string for vectorization.

One document per product and language

A product-language object is preferable when translations have substantially different merchandising content or when the storefront must return results only in the shopper’s language. Include a stable WooCommerce product ID, a language code, and a canonical product ID so duplicate language records can be grouped in the application layer.

Configure a multilingual vectorizer

Choose an embedding model that supports every language used by the store. The exact model and configuration depend on the Weaviate deployment and the vectorizer integration enabled in the cluster. Do not assume that an English-only model will preserve search quality for French, German, Spanish, or non-Latin queries.

The following Python example shows the shape of a collection definition using a multilingual vectorizer. Replace the model name with one supported by the vectorizer integration in the target Weaviate environment.

import weaviate
from weaviate.classes.config import Configure, Property, DataType

client = weaviate.connect_to_weaviate_cloud(
    cluster_url="https://YOUR-CLUSTER.weaviate.network",
    auth_credentials=weaviate.auth.AuthApiKey("YOUR-API-KEY"),
)

products = client.collections.create(
    name="Product",
    vectorizer_config=Configure.Vectorizer.text2vec_weaviate(
        model="YOUR-MULTILINGUAL-EMBEDDING-MODEL"
    ),
    properties=[
        Property(name="woo_id", data_type=DataType.INT),
        Property(name="sku", data_type=DataType.TEXT),
        Property(name="language", data_type=DataType.TEXT),
        Property(name="canonical_id", data_type=DataType.TEXT),
        Property(name="name", data_type=DataType.TEXT),
        Property(name="description", data_type=DataType.TEXT),
        Property(name="category", data_type=DataType.TEXT),
        Property(name="stock_status", data_type=DataType.TEXT),
        Property(name="search_text", data_type=DataType.TEXT),
    ],
)

Verify the available model names and module configuration against the Weaviate version used by the agency. In production, pin the configuration and test it with real catalog queries before importing the full product set.

Index WooCommerce translations

A synchronization process should listen for product creation, update, deletion, translation, inventory, and taxonomy events. The content indexing worker can retrieve the canonical WooCommerce product and its translations, normalize the fields, and upsert the corresponding Weaviate objects.

For a product-language design, an object might look like this:

{
  "woo_id": 4821,
  "canonical_id": "4821",
  "language": "fr",
  "name": "Veste de randonnée imperméable",
  "description": "Une veste légère et respirante pour les randonnées sous la pluie.",
  "category": "Vêtements de plein air",
  "stock_status": "instock",
  "search_text": "Veste de randonnée imperméable. Vêtements de plein air. Une veste légère et respirante pour les randonnées sous la pluie."
}

Use a deterministic object ID based on the WooCommerce product ID and language, such as 4821-fr. This makes retries safe and prevents duplicate records when a webhook is delivered more than once. Keep stock and price updates independent from expensive re-vectorization when only operational values have changed.

Run semantic multilingual queries

When the collection uses a suitable multilingual vectorizer, a query can be written in one supported language while matching product content written in another. The query text is embedded into the same vector space as the indexed product text.

products = client.collections.use("Product")

response = products.query.near_text(
    query="chaussures de course légères pour la pluie",
    limit=12,
    return_properties=[
        "woo_id",
        "canonical_id",
        "language",
        "name",
        "stock_status",
    ],
)

for item in response.objects:
    print(item.properties)

For a storefront with localized documents, add a language filter so French shoppers receive French records first. A fallback strategy can run a second query without the filter when the first result set is too small.

from weaviate.classes.query import Filter

response = products.query.near_text(
    query="chaussures de course légères pour la pluie",
    filters=Filter.by_property("language").equal("fr"),
    limit=12,
    return_properties=["woo_id", "language", "name", "stock_status"],
)

Combine semantic search with WooCommerce filters

Semantic similarity should not replace commerce constraints. Apply structured filters for stock status, product visibility, catalog permissions, brand, category, price range, and any other business rule. This prevents an unavailable or hidden product from ranking highly merely because its description is semantically relevant.

from weaviate.classes.query import Filter

commerce_filter = (
    Filter.by_property("stock_status").equal("instock") &
    Filter.by_property("language").equal("de")
)

response = products.query.near_text(
    query="warme wasserdichte Jacke zum Wandern",
    filters=commerce_filter,
    limit=20,
    return_properties=["woo_id", "name", "stock_status", "language"],
)

For price filtering, store a numeric property such as price_minor instead of relying on formatted currency strings. Keep currency and tax-region decisions in the WooCommerce application layer or index separate regional price properties when the catalog requires it.

Use hybrid search for SKUs and product names

Vector search is strong for intent and paraphrases, while keyword search is usually better for exact SKUs, model numbers, named brands, and uncommon technical terms. Hybrid search combines both signals.

response = products.query.hybrid(
    query="trail runner XR-500",
    alpha=0.65,
    filters=Filter.by_property("stock_status").equal("instock"),
    limit=12,
    return_properties=["woo_id", "sku", "name", "language"],
)

Adjust alpha using production search logs rather than choosing a universal value. A lower value gives keyword matching more influence; a higher value gives vector similarity more influence. Test queries containing translated product concepts, accents, inflected words, SKUs, and mixed-language terms.

Handle duplicate translations in the result layer

If each language has its own object, one product may appear several times when the query is not language-filtered. Group results by canonical_id before rendering the product grid. Select the preferred translation according to the shopper’s locale, then use the object’s woo_id to retrieve the current WooCommerce permalink, price, and inventory details.

Do not treat the Weaviate result as the authoritative source for fast-changing commerce data. A common architecture uses Weaviate for candidate retrieval and WooCommerce or a commerce API for final availability, pricing, permissions, and URL resolution.

Evaluate multilingual relevance

Create a test set from real WooCommerce search analytics. Include queries in every supported language and label expected products, acceptable alternatives, and products that must not appear. Measure results separately for:

  • Translated product concepts, such as “chaussures de randonnée” and “hiking boots”.
  • Cross-language queries where the query and indexed translation use different languages.
  • Exact identifiers such as SKUs and manufacturer codes.
  • Attribute combinations such as color, size, material, and intended use.
  • Out-of-stock, hidden, restricted, and region-specific products.

Track recall at a useful result depth, click-through rate, add-to-cart rate, zero-result rate, and the proportion of results requiring a fallback query. Review poor matches manually because embedding quality, translation quality, field weighting, and catalog structure can all affect the outcome.

Operational considerations for agencies

Use a queue for webhook processing, retry transient failures, and record the source revision that produced each indexed object. During a bulk rebuild, create or populate a replacement collection and switch the application configuration after validation rather than exposing a partially indexed catalog.

Keep API keys server-side, restrict collection permissions, and avoid indexing customer-specific or sensitive data into a shared product collection. Log the query language, applied filters, selected search mode, and result identifiers so relevance issues can be reproduced without logging unnecessary personal information.

Trending posts
You might also like