# CPalius CMF 1.1.2

**Released:** 2026-09-16 · **Channel:** stable · **Critical:** no

A file patch. Four things members and operators actually ran into: mails that
could not be edited and arrived in the wrong language, account details that
could be changed with nobody told, reputation that could not be given at all,
and an error log filled with traffic that was never an error.

Turkish: [1.1.2-tr.md](1.1.2-tr.md)

## Mails are editable, and arrive in the member's own language

**AACP → System → Mail templates.** Every mail the site sends to a member is now
editable, with one card per active language. Turn on a third language in
AACP → Locales and a third card appears here — there is no second place to
register a language.

Nine mails are covered: e-mail verification, welcome, waiting-for-approval,
account approved, the three account-change notices below, and the envelopes
around single notifications and the notification digest.

**Each member now receives all of them in the language they picked at
registration.** That choice was already being recorded and nothing ever read it
back, so until now the language came from whatever request happened to trigger
the mail: an administrator approving an account mailed the member in the
*administrator's* language, and anything sent from a queue worker or from cron
used the kernel default for everybody. Both are fixed at the source.

The registration form also stops offering a hard-coded Turkish/English pair and
lists the languages that are actually active, and the profile page gained a
"language for mail" field so a member can change their mind later.

### How the fallback works

A mail resolves in this order: your wording for that language, then your wording
for the site's default language, then the wording that shipped with the release.
Clearing a field, or saving text that is identical to the shipped default,
deletes your copy rather than storing it — so an untouched installation keeps
picking up improvements to the shipped text, and "edit, change your mind, undo"
leaves no trace.

Your text is never run through the translation formatter. One stray `{` typed
into a textarea would otherwise turn every future registration mail into an
exception instead of a mail.

## E-mail and username changes need an administrator

Until now the profile form wrote both straight to the account. That is a quiet
account-takeover primitive: anyone holding a session could point password resets
at their own address, or take a username another member is known by, with nobody
told.

Now the request is held. **AACP → Users → Change requests** lists what was asked
for; nothing on the account changes until it is approved, the member keeps
signing in with their old details, and they can withdraw the request themselves.
The member is mailed when the request is received, and again when it is approved
or declined — the approval notice goes to the new address, which is the point:
if the change was not theirs, that is where they find out.

Approval re-validates at the moment you click, not at the moment the request was
filed. An address that was free last week may have been registered since.

Operators who do not want this can turn it off in
**Settings → Account → registration**; it is on by default.

## Reputation no longer needs a topic

The topic picker was mandatory and only ever listed topics the *recipient* had
posted in, so it was routinely empty and reputation could not be given at all.

It is replaced by an optional link field: paste the link this reputation is
about, or leave it blank. A link to a thread on this forum is recognised and
still connected to the real topic, so the ledger keeps working when that topic is
renamed or moved. Anything else is kept as a link.

## Quieter, more honest logs

- **404s are no longer errors.** Every scanner probing
  `/autodiscover/autodiscover.xml`, `/wp-login.php` or `/.env` was writing an
  ERROR row into the panel's log, and a log that is mostly bot traffic stops
  being read. 404 and 405 now log at notice level: still there for anyone who
  lowers the log threshold, no longer dressed as a failure of the application.

- **A blog category in another language is not a 404.** A category URL is
  shared and indexed without its language prefix surviving the trip. A Turkish
  slug arriving on the English site now redirects to the translated category
  when there is one, and otherwise shows the archive page with a 404 status —
  the same thing single posts have always done. It was the second-largest source
  of rows in the production error log.

## Upgrade notes

Nothing to do beyond applying the patch.

This patch needs a database table (`cp_mail_templates`) and a column
(`forum_user_reputations.topic_url`), and a patch cannot run migrations. Both are
therefore created by the code itself, once, the first time they are needed. The
migrations still ship for fresh installs, and both sides are written so that
whichever runs second does nothing.

If your database user is not allowed to issue DDL, nothing breaks: mails fall
back to the shipped wording exactly as before, and running
**AACP → Updates → Apply** creates both properly.

## Known limits

- Notification mails for individual events are localised, but the per-event
  body templates a module ships are still Twig files, not entries on the mail
  template screen. Only the envelope around them is editable.
- `latest.json` still points at the 1.1.1 package. This release is a patch, not
  a new full package; installations older than 1.1.1 should take the 1.1.1
  release first and then this patch.
