## 🔍 Overview
Previously we added the ability to translate existing posts in different
languages: https://github.com/discourse/discourse/pull/32564. In this
update we add the ability to set a post language upon initially creating
a post.
Internally, we also clean-up/improve a few things, like:
- adding a `PostLanguageSelector` component
- Adding a `available_content_localization_locales` onto `SiteSetting`
so it's available in the service (without needing to parse the JSON to
access it)
- fix issues with the translation-editor not working due to some
regressions from here: https://github.com/discourse/discourse/pull/32869
- ensure everything works for replies/drafts/edits
## 📷 Screenshots

This commit introduces new features and utilities related to the backup
and restore system that make use of remote URLs:
- `discourse restore` accepts a URL to a backup file
- `discourse backup_url` generates a URL of a backup file (S3 only)
- `discourse import_backup_url` downloads a backup file from a URL to
the configured backup store
This can be used to move content between two Discourse instances by
backing up the entire site, copying the backup URL, importing or
restoring it on the other instance.
When there is a relevant `username` associated with an outgoing email,
like in the case of post notifications, the `X-Discourse-Sender` header
will be added to the email, indicating the sender's username.
This mimics the `X-GitHub-Sender` header used by GitHub, which is useful
for filtering and categorizing emails based on the sender.
The moment locale files expect `this.` to be the window object. In a
type=module, `this` is `undefined`. This commit wraps the
moment-timezone definitions in an IIFE to resolve that.
Also adds a system spec to prevent future moment-timezone regressions.
Followup to a2b0c193dff40278c0a93995cc9b97b05dc8abb2
Previously we would check the request for a matching CDN hostname before
applying the `Access-Control-Allow-Origin` header. That logic requires
the CDN to include its public-facing hostname in the `Host` header,
which is not always the case.
Since we are only running this `apply_cdn_headers` before_action on
publicly-accessible asset routes, we can simplify things so that the
`Access-Control-Allow-Origin: *` header is always included. That will
make CDN config requirements much more relaxed.
At the moment, this is primarily relevant to the HighlightJsController
routes, which are loaded using native JS `type=module`. But in the near
future, we plan to expand our use of `type=module` to more critical JS
assets like translations and themes.
Also drops the `Access-Control-Allow-Methods` header from these
responses. That isn't needed for `GET` and `HEAD` requests.
RFC 5322 allows special characters, including ? and =, to be used in e-mail addresses.
RFC 2047 is an extension that adds a feature called "encoded words" which let you embed different encodings in the same header. However, it explicitly says that these aren't allowed in e-mail address headers.
Encoded words have the format:
encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
Where encoding is either Q or B, but could take on other values in the future.
After this change we consider e-mail addresses with an encoded word inside invalid.
Removes the composer educational tips for:
- upload avatar
- sequential replies
- reviving old topic
We are also removing the associated site settings that are now
redundant:
- Disable avatar education message
- Sequential replies threshold
- Warn reviving old topic age
Restores the category text/foreground color field that was removed in
#32015.
We are also retaining the auto text color selection that was introduced
and applying on background color change rather than when the form is
saved. The text color algorithm has been changed from color brightness
to use color difference instead, which appears to be more reliable.
Algorithm for color difference:
https://www.w3.org/TR/AERT/#color-contrast
---------
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Both rake tasks do not account for secure uploads so they should be
considered broken. Since there is no longer a need for these rake tasks,
we are removing them instead of spending time to fix them.
The code being removed here was added 7 years ago and is stale at this
point. We don't even know if it is safe to run since no tests have been
written for it. Therefore, it is safer for us to remove it than to spend
time reviewing it.
Likes given / likes received on user admin page were empty because of
this missing data. Also, a background job cleared the like stats from
`user_stats` table after some time because of this missing data.
Marking mixed-decls as silenced & fatal simultaneously is causing a
warning "Ignoring setting to silence mixed-decls deprecation, since it
has also been made fatal"
The intention is for it to be silenced for themes/plugins, but fatal for
core.
This improves the error message(s) displayed when an error happens while
using a social login to log in / sign up into a Discourse community.
Unfortunately, we can't be super precise in the reason behind the error
(it can be the user clicked "cancel" during the authorization phase, or
any of the plethora of other possible errors) because the reason isn't
provided (either for security reasons, or because it's just hard to do
so in a reliable & consistent way accross all social logins).
The best I could do was to
- add the name of the "social login" provider in the error message
- tweak the copy a bit for the different cases handle
- fix the CSS/HTML to match the one used by the main application
In order to show the name of the provider, we use either the "provider"
or the "strategy" query parameter, or use the name of the authenticator
(if it's the only one enabled).
Internal ref - t/153662
---
**BEFORE**

**AFTER**

Fixing this everywhere will be a very large undertaking, so we're
deferring it until there is a concrete timeline for it becoming an error
in sass.
In the meantime, we'll be adding a stylelint rule to enforce ordering of
declarations/nested-blocks/mixins, so that will go some way towards
avoiding this deprecation.
Running this spec locally I was getting an error:
```
1) translate accelerator plugins loads plural rules from plugins
Failure/Error: DiscoursePluginRegistry.unregister_locale("foo")
NoMethodError:
undefined method `unregister_locale' for class DiscoursePluginRegistry
# ./spec/lib/freedom_patches/translate_accelerator_spec.rb:113:in `block (3 levels) in <main>'
Finished in 0.17998 seconds (files took 1.88 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/lib/freedom_patches/translate_accelerator_spec.rb:117 # translate accelerator plugins loads plural rules from plugins
```
On top of this, this spec was flakey, Im not sure this is going to fix
flakyness, but this seems like a good first step.
Previously when changing back to the same email (ie. change to new
email, then change back again) we can easily end up showing the
incorrect old email if changing back to the same email more than once.
Then passing the incorrect old email causes an error as it can't be found.
This happens because we only searched for a combination of `user_id` and
`new_email` which can load an older change from the database. By using
the current email address when finding / initializing the
`EmailChangeRequest` we can prevent this issue as we will be creating a
new entry rather than loading an outdated one.
## 🔍 Overview
This update adds the ability for users to manually add translations to
specific posts. It adds a 🌐 icon on the post menu where you can click to
add translations for posts.
It also introduces a new site setting:
`content_localization_debug_allowed_groups` which is convenient when
debugging localized posts. It adds a globe icon in the post meta data
area along with a number of how many languages the post is translated
in. Hovering over the icon will show a tooltip with access to editing
and deleting the translated posts.
## 📸 Screenshots
<img width="1234" alt="Screenshot 2025-05-07 at 13 26 09"
src="https://github.com/user-attachments/assets/9d65374d-ee3e-4e8b-b171-b98db6f90f23"
/>
<img width="300" alt="Screenshot 2025-05-07 at 13 26 41"
src="https://github.com/user-attachments/assets/6ee9c5e6-16ed-4dab-97ec-9401804a4ac8"
/>
There are instances of posts being deleted by system_user where the context is left blank in the staff action logs, leading to confusion about why exactly they have been deleted.
This change deprecates using the PostDestroyer as system_user without providing a context, and adds a context to all call sites currently missing it in core. Plugins to be done after this is merged.