How Shirely Handles Category Hierarchy Across Languages
A translated category tree contains two different relationships.
First, “Cordless drills” is a child of “Drills.” Second, its German term is a translation of that same category, not a separate branch. A reliable import has to preserve both the parent–child hierarchy and the WPML language group.
Trying to infer those relationships from visible names makes repeat imports fragile. Shirely's Category Matrix uses source keys for structure and language columns for translation.
Two graphs, one source row
Consider this file:
source_id,parent_source_id,name|en,name|de,slug|en,slug|de
tools,,Tools,Werkzeuge,tools,werkzeuge
drills,tools,Drills,Bohrmaschinen,drills,bohrmaschinen
cordless,drills,Cordless drills,Akku-Bohrmaschinen,cordless-drills,akku-bohrmaschinen
The source-key graph is language-neutral:
toolsis a root;drillspoints totools;cordlesspoints todrills.
The |en and |de columns provide the language-specific values. Shirely creates or updates the terms, connects the translations through WPML and builds each language's hierarchy from the same source relationships.
Why names and database IDs are weak keys
Names are content. They can be translated, corrected or reused below different parents. Slugs are more stable but can still be changed for editorial or SEO reasons.
Numeric term IDs are stable only inside one WordPress database. If Drills is term 84 on the source, term 84 on the destination may refer to something else.
source_id solves a different problem: it is an identifier maintained by the dataset. parent_source_id points to another key in that same portable namespace. The file can therefore describe the tree before WordPress assigns local IDs.
Keep both keys as text and never generate them from the current row number. Sorting a spreadsheet should not change category identity.
What happens during the import
At a high level, Shirely:
- reads the Matrix row and its active language columns;
- resolves or creates the category represented by
source_id; - creates or updates its translated terms;
- links those terms through WPML;
- records the intended parent from
parent_source_id; - runs a closing hierarchy pass after the imported set is available.
The closing pass is important. Real datasets are not always perfectly parent-first. If a child arrives before its parent, Shirely can temporarily save it as a root and resolve the hierarchy after all rows have been processed.
That warning is not permission to ignore the file order. Parent-first sources are easier for people to audit, and invalid references or cycles cannot be repaired by processing order.
Validate the source graph first
Before involving WordPress, check:
- every
source_idis unique; - every non-empty
parent_source_idexists; - no row is its own parent;
- no sequence creates a cycle;
- roots are intentionally blank;
- all language suffixes match active WPML languages;
- blank translated names are intentional.
For a cross-store move, keep source identifiers stable across exports and imports. Shirely 1.3.0 catalog provenance prevents a foreign exported ID from being blindly treated as local, but natural keys and a destination preview are still required.
Verify the hierarchy where customers see it
After the import, check WPML Taxonomy Translation and the WooCommerce category list. Then browse real category archives in every language.
Look for:
- a root accidentally placed below another term;
- a child that remained at the root;
- the right name with the wrong parent;
- a translation missing from its group;
- translated products assigned to a category in the wrong language;
- breadcrumbs or menus that expose an unexpected branch.
If WPML still reports pending hierarchy work, run its hierarchy synchronization and inspect the affected branch again. Do not rely only on the number of created terms.
Re-imports update a relationship, not just a label
Suppose “Cordless drills” is renamed but stays below “Drills.” Preserve source_id=cordless and change only the translated name or slug.
If the category moves to a new parent, update parent_source_id intentionally and test that branch. Moving a parent can affect every descendant and the navigation that consumes the tree.
Category and Matrix rows are processed on every import. Smart Sync does not skip them as unchanged. Repeatability depends on stable source keys, the correct Import Mode and a narrow file.
Tags are a different shape
Tags and other non-hierarchical taxonomies can also have WPML language relationships, but they do not use a parent graph. A Matrix tag import focuses on stable term identity, translated values and object assignment.
Do not copy category-specific parent logic into a flat taxonomy simply because both appear under WooCommerce product data.
Automate only after the tree is proven
Shirely 1.3.0 can save a supported Category Matrix import as an Automation slot. Start with Run now, inspect the complete branch and check Run History.
WP-Cron schedules are hourly, twicedaily and daily, but site traffic controls when WordPress can trigger them. System cron with WP-CLI is more predictable when timing matters.
Avoid overlapping imports that may change the same taxonomy or WPML/WCML groups. Same-slot locking does not serialize every possible writer. Headless runs also remove delete_non_matching, preventing an incomplete source from becoming a scheduled broad delete.
Measured behavior is not a universal limit
A documented category run processed 1,068 categories across four languages—4,272 rows—in 9 minutes 21 seconds. Another MAMP regression exercised a hierarchical Matrix workflow with 5,000 total product_cat terms and failed at 6,000 in that specific environment.
These measurements show tested points, not universal capacity promises. Hosting, hooks, taxonomy depth and database state matter. Size the batch on staging and treat the first complete tree as its own QA project.
The useful mental model
Think of the Matrix file as a portable graph. Source IDs describe nodes, parent source IDs describe edges, and language columns describe the WPML variants of each node. Once those parts are explicit, the import does not have to guess from translated names.
For a step-by-step workflow, use importing WooCommerce categories with WPML. The Matrix page shows how the same structure fits products and other translatable data.