This guide explains how to use the automated product slug generation system to populate missing slugs for all products across all locales (Slovenian, English, Russian).
Overview
The slug generation task automatically creates URL-friendly slugs for products based on their titles. It:
Generates slugs from titles: Uses the same logic as manual slug creation (src/utilities/formatSlug.ts)
Respects existing slugs: Only generates slugs for products/locales that don't have one yet
Handles all locales: Generates localized slugs for sl, en, and ru based on their respective titles
Safe operation: Never overwrites existing slugs
How It Works
The slug generation process:
Fetches all products from the database with all locales
For each product, checks each locale (sl, en, ru)
If a slug is missing for that locale:
Gets the product title for that locale
Generates a URL-friendly slug using the same formatting rules as manual entry
Updates only that specific locale's slug field
Provides detailed logging and error reporting
Slug Format
Slugs are formatted according to these rules:
Spaces replaced with hyphens (-)
Non-word characters removed (except hyphens and slashes)
{"slug":{"sl":"svinje-meso","en":""// Empty English slug// Russian slug missing entirely}}
After running job:
json
{"slug":{"sl":"svinje-meso",// Unchanged"en":"pork-meat",// Generated from English title"ru":"svinina"// Generated from Russian title}}
Logs and Debugging
The job provides detailed logging:
code
=== PRODUCT SLUG GENERATION JOB STARTED ===
Found 50 product documents
=== Processing Product ID: 123 ===
Product 123 already has slug for locale sl, skipping
Generating slug for product 123 (en): "Beef Meat" -> "beef-meat"
Successfully generated slug for product 123 (en): beef-meat
Generating slug for product 123 (ru): "Говядина" -> "govyadina"
Successfully generated slug for product 123 (ru): govyadina
=== PRODUCT SLUG GENERATION COMPLETED ===
Generated 87 slugs across 50 products
Safety Features
Never overwrites existing slugs: If a slug already exists for a locale, it's skipped
Per-locale isolation: Each locale is processed independently
Error isolation: If one product/locale fails, others continue processing
Detailed error reporting: All errors are logged and returned in the result
When to Use This
Use this task when:
You have products with missing slugs in some locales
You've imported products without generating slugs
You've added new locale support and need to backfill slugs
You want to ensure all products have consistent, URL-friendly identifiers
Extending for Other Collections
This pattern can be adapted for other collections (Collections, Recipes, etc.) by:
Copying the job handler and changing the collection name
Adjusting the field names (if not using title and slug)
Registering the new task in payload.config.ts
Creating a corresponding API endpoint
Troubleshooting
Problem: Job queues but never runs
Solution: Make sure you have a job runner process active:
bash
curl -X POST http://localhost:3000/api/payload-jobs/run \
-H "Authorization: Bearer YOUR_CRON_SECRET"
Problem: Slugs not generating for a specific locale
Solution: Check that the product has a title in that locale. The job logs will show:
code
Product 123 has no title for locale en, skipping slug generation
Problem: "Duplicate slug" error
Solution: The job doesn't handle slug uniqueness conflicts. Ensure your titles are unique per locale, or manually adjust conflicting slugs before running the job.