User tests: Successful: Unsuccessful:
Pull Request resolves # .
Editing a category quietly drops any unpublished translation from its association group, and if that leaves only one member the group is deleted. Nothing warns you and republishing does not bring it back. Those translations are also missing from the Association column, which is why it is easy to miss.
Both come from CategoriesHelper::getAssociations(), which keeps only members that are published and in your view levels. Three places read associations through it: the frontend language switcher, the edit form (CategoryModel::getItem()) and the Association column (AdministratorService::association()). This Pull Request changes the last two and leaves the switcher alone.
The loss happens on save. The form renders a field per content language, a member that was filtered out submits an empty value, and AdminModel::save() then deletes the group and re-inserts only what came back.
com_categories is the only component that filters here. com_content, com_contact, com_newsfeeds and com_menus all call Associations::getAssociations() directly, which is why the same thing works for articles. com_associations reads category associations unfiltered too, so it shows the translation that the edit form hides and then deletes.
The filter came from #19551 (in 2018). Its testing instructions only mention the language switcher and the hreflang tag, and CategoryModel::getItem() was already calling the helper, so the edit form picked up a display filter it was never meant to have.
Nothing about display changes. The helper is untouched, so the language switcher still filters and #19551 still works. The form gets every member as the same integer ids it got before, and the column shows a badge for each one, like Articles already does.
On a multilingual site with at least two content languages.
Assoc demo EN, Language English (en-GB), Status Published. Save & Close.Assoc demo FR, Language French (fr-FR), Status Unpublished. Save & Close.Assoc demo EN -> Associations tab -> select Assoc demo FR for French -> Save & Close.
Assoc demo EN row. (My before and after results are below)Assoc demo EN and look at the Associations tab. (My before and after results are below)At Step 3: You can verify in DB that association is written:

At Step 4: the Assoc demo EN row shows no badge, while Assoc demo FR shows its en-GB one.

At Step 5: the Associations tab is already empty, even though the query still returns both rows.

At Step 6 then deletes the group, so at step 7 the tab is still empty and the query returns nothing.

At any point you can check the association group in DB directly using :
SELECT a.key, a.id, c.title, c.language, c.published
FROM `#__associations` a
JOIN `#__categories` c ON c.id = a.id
WHERE a.context = 'com_categories.item' AND c.title LIKE 'Assoc demo%'
ORDER BY a.key, c.language;With more languages the loss is partial instead of total: associate three translations, unpublish one, save the source, and the group comes back without it, leaving it an orphan.
After applying the patch, redo step 3 to re-link the two categories, since the steps above deleted the association. Then repeat steps 4 to 7.
At Step 4: the Assoc demo EN row shows the fr-FR badge, the same as Articles shows for an unpublished associated article.

At Step 5: the tab shows Assoc demo FR in the French field.

Step 7: the association is still there and the query still returns both rows. With more languages every member is kept.
The language switcher is unaffected either way: an unpublished category is still left out of it and gets no hreflang.
Please select:
Documentation link for guide.joomla.org:
No documentation changes for guide.joomla.org needed
Pull Request link for manual.joomla.org:
No documentation changes for manual.joomla.org needed
| Status | New | ⇒ | Pending |
| Category | ⇒ | Administration com_categories |