История коммитов

.
fix(collections): escape ckeditor attributes in the admin item form
Item text is stored raw and was printed unescaped into the value attribute of the CKEditor Vue component, so quotes inside the HTML (links, images, figures) closed the attribute early and mangled the editor content on load and on re-save. Escape all attributes in the partial itself, which is the output boundary and is only used inside this module.
.
fix(contacts): make the admin link in the notification email a real button
.
simba77
docs(changelog): note the contacts module
.
docs(changelog): note the contacts module
.
simba77
feat(contacts): add contacts module with feedback form
- public /contacts page with contact info (email, phone, address, working hours, socials) and Schema.org markup
- feedback form with captcha for guests, honeypot, CSRF/flood/ban checks and consent checkboxes
- contact_messages table, admin list with status filter, message view, mark as processed and delete
- admin settings stored in the johncms config: multilingual texts with current language / site default / english fallback
- admin notification via the EmailMessage queue with a new mail template
- install/install_contacts.php for existing sites
.
feat(contacts): add contacts module with feedback form
- public /contacts page with contact info (email, phone, address, working hours, socials) and Schema.org markup
- feedback form with captcha for guests, honeypot, CSRF/flood/ban checks and consent checkboxes
- contact_messages table, admin list with status filter, message view, mark as processed and delete
- admin settings stored in the johncms config: multilingual texts with current language / site default / english fallback
- admin notification via the EmailMessage queue with a new mail template
- install/install_contacts.php for existing sites
.
docs(changelog): note language name normalization
.
i18n: normalize language names in locale ini files
Use native endonyms in short form consistently:
- ar: Arabic -> العربية
- az: Azərbaycan dili -> Azərbaycanca
- id: Indonesia (country) -> Bahasa Indonesia
- kk: Қазақ тілі -> Қазақша
- ky: Кыргыз тили -> Кыргызча
- lt: Lietuvos (country, genitive) -> Lietuvių
- ro: Romana -> Română (restore diacritics)
- uz: O'zbek tili -> Oʻzbekcha
- vi: Việt Nam (country) -> Tiếng Việt
.
i18n(ky): add draft Kyrgyz translations for untranslated strings
Fill all 351 untranslated Kyrgyz strings across 14 locale files.

- 279 machine-drafted strings are marked fuzzy: gettext keeps them out of the runtime and Crowdin receives them as unconfirmed suggestions, so a native speaker reviews them before they go live.
- 72 strings reuse existing human translations of the same msgid from other locale files, so they are added as confirmed.
- Terminology follows the existing translations (Өчүрүү, Оңдоо, Бөлүк, Колдонуучу, Китепкана).
- Also fixes broken placeholders in ky: %value% in the flood validator message, and spaced % s / % d specifiers.
- Adds the locale files for the collections and consent modules; the non-Kyrgyz ones are empty templates for Crowdin.
.
fix(i18n): repair broken placeholders in translations
Fix placeholders that were corrupted by translators across ar, az, id, lt, pl, ro, uk and uz locales.

- Flood validator: restore %value% (replaced by Laminas via str_replace, not sprintf) where it had been rewritten as %d, so the wait time is substituted instead of printed literally (ar, ro, uk, uz).
- Remove stray %s/%d placeholders absent from the msgid: Comments.php concatenates the flood delay after the string, so these were rendered literally (az, ro, ar).
- Restore literal macro tokens #user_name#, #name#, #description# that had been translated, which broke code-side substitution (az, id).
- Fix spaced (% s) and dropped placeholders, restoring the file size limit and wait time in messages (lt, pl, uz).
- Retranslate "You have a ban" in az and ar, where the existing text belonged to a different string; marked fuzzy for review.