Two major threads shipped today.
Social publishing fixes: Post scheduling was broken in three separate ways. First: scheduled times were being stored as local time instead of UTC — a 6-hour offset for the configured timezone. Second: the timezone was being read from the wrong settings key (dot notation versus underscore format). Third: token decryption was failing for every social account because an extra base64_decode() was applied to data that CodeIgniter's encrypter had already encoded — this caused an "authentication failed" error on every decrypt attempt. Fixed all three. Posts now schedule correctly, display in local time in the UI (database stores UTC, UI converts to app timezone), and publish to Facebook through the scheduled cron command. Added a timezone selector to Admin → General Settings so the app timezone is database-configurable, not hardcoded. Posts management page built with status filters, stats cards, and timezone-aware time display.
40-file SEO and i18n sprint: Complete overhaul of the public-facing frontend for technical SEO correctness, AIO readiness, and full 12-language internationalisation. Duplicate H1 fixed (navbar logo demoted from <h1> to styled <span>). noindex added to thin pages (search results, FAQ keyword mode). Canonical URL strips the ?lang= parameter so hreflang carries the language signal, not the canonical. BreadcrumbList JSON-LD on all content pages. FAQPage JSON-LD with HTML stripping and 20-item cap, eligible for Google FAQ rich results. Article JSON-LD with dateModified and mainEntityOfPage for rich article results. WebSite JSON-LD with SearchAction on homepage for Google Sitelinks Search Box. hreflang for all 12 language variants plus x-default on every page. og:locale mapped to correct locale format per active language. <html lang dir> dynamic per active CMS language. Language helper autoloaded in BaseController. KB article search covers all 11 translated title and content columns. Language switcher correctly appends lang parameter without duplicating. Migration adds 22 translation columns to KB articles (11 languages × 2 fields). Input sanitisation on search and FAQ query parameters with strip_tags and truncation before use in meta tags. Three new test files: 40 assertions covering SEO data contract, FAQ branching, and header variable logic.