This commit is a follow-up to b02bc707dec12c607511d4a95c7d791f63131b49
where `Upload#update_secure_status` does not call
`FileStore::S3Store#update_upload_access_control` if
`s3_use_acls` is disabled. This is no longer correct as an upload's
access control on S3 can now be based on tags if the
`s3_enable_access_control_tags` site setting is
enabled.
To fix this, this commit removes the `s3_use_acls` check in
`Upload#update_secure_status` and updates
`FileStore::S3Store#default_s3_options`
to not set the `acl` option if the `s3_use_acls` site setting is
disabled.
This commit is a follow up to b02bc707dec12c607511d4a95c7d791f63131b49.
When the `s3_enable_access_control_tags` site setting is enabled,
calling `FileStore::S3Store#update_access_control` will result in a
argument error.
This commit introduces a `s3_enable_access_control_tags` site setting
which,
when enabled, adds a `discourse:acl` tag with values `public` or
`private` to
S3 objects created by the application. The presence of the tags on S3
objects
enables bucket administrators to implement tag-based access control
policies, providing an alternative to
object ACLs which AWS now discourages.
The `discourse:acl` tag can be customized via the
`s3_access_control_tag_key ` site setting.
Values for `public` and `private` can also be customized via the
`s3_access_control_tag_public_value` and
`s3_access_control_tag_private_value ` site settings respectively.
### Reviewer Notes
To test it locally, run the following commands in your working discourse
directory:
1. `script/install_minio_binaries.rb`
2. Start a local minio server by running: `bundle exec rails runner
script/local_minio_s3.rb`
3. bundle exec rails runner "SiteSetting.enable_s3_uploads = true"
5. Start your development rails server with the following environment
variables: `DISCOURSE_ENABLE_S3_UPLOADS=true
DISCOURSE_S3_ENABLE_ACCESS_CONTROL_TAGS=true
DISCOURSE_BACKUP_LOCATION=s3`
Introduction of system themes. System themes are local themes which:
- Cannot be deleted;
- Cannot have “custom code” added, components only;
- Cannot have uploads;
- Cannot edit color palettes;
- Are updated on deploy, like core plugins.
This PR added the Foundation system theme, which is an empty theme like
Default. The Foundation theme will be added in the next PR.
In a development environment, when system theme files are
changed/added/deleted, the theme is reuploaded and the page is reloaded
to make it a good experience for the engineer working on improvements.
System themes are not visible until
`SiteSetting.experimental_system_theme` is enabled.
This is a second attempt at:
https://github.com/discourse/discourse/pull/33001
We had to [revert the
commit](https://github.com/discourse/discourse/pull/33157) because it
was performing a site-setting check at boot time, which is prone to
issues and not allowed.
This PR:
- re-introduces the changes in the original PR
- a fix by not performing a site-setting check at boot time (verified
by: `SKIP_DB_AND_REDIS=1 DISCOURSE_DEV_DB="nonexist" bin/rails runner
"puts 'booted'"` locally and should be caught by the new CI check
introduced here: https://github.com/discourse/discourse/pull/33158)
- adds a fix to the translation editor to not show the original post
locale in the dropdown, as well as adding an indicator of what the
original post locale is in a small badge in the header:
- 
## 🔍 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

We will be moving towards `type="module"` for all of Discourse's JS
bundles in the near future. This commit makes a start by applying the
change to translation bundles.
This was previously merged, but the lack of `apply_cdn_headers` on the
locales controller led to CORS errors on sites with CDNs.
We will be moving towards `type="module"` for all of Discourse's JS
bundles in the near future. This commit makes a start by applying the
change to translation bundles.
Without this wrapper, `data` is defined in the global scope and clashes
when there are multiple themes with translations.
Followup to 033cccdf17a56b43f9f243bb549abe0a41a0de63
We can remove the wrapper once we land
https://github.com/discourse/discourse/pull/33107
Theme translations are very simple JS, and do not need to be run through
the theme transpiler. This brings their format in-line with core/plugin
translations.
Extracted from https://github.com/discourse/discourse/pull/33103
This commit removes the color palette dropdown from the theme page and replaces it with a new "Colors" tab where the theme's color palette can be edited directly in that tab on the theme page. With this change, a theme's color palette is strongly tied to its theme and can't be linked to other themes and it can't be selected by users without using the theme as well.
All of the changes are behind a feature flag. To enable it, turn on the `use_overhauled_theme_color_palette` setting.
Co-authored-by: Ella <ella.estigoy@gmail.com>
As part of the review queue refresh, we'll be adding the ability for moderators to make notes on individual reviewable items. As a first step, this change adds the new model and associated backend code.
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>
Previously we had omitted determining the locale of categories, as
unlike posts, categories are usually single words and are usually only
translated once.
Since there is no locale, a category called "Staff" would also have an
English translation. With LLMs that perform poorly, we see that
translating "Staff" to English may result in something entirely
different (like "Personnelle" or "Personal").
Thus adding locale support to categories can mitigate this issue due to
the uncertainty.
Updates the composer similar topics tips to return a maximum of 3 topic
results. We are phasing out the site setting in an effort to improve the
UX in the composer.
We will handle the migration to remove the site setting value from the
database in a follow up PR.
Currently, topic excerpts are not localized.
This commit adds the excerpt column into topic_localization and displays the
localized excerpt if present.
`strict_loading` was added to prevent it happening in the future. Few
adjustments had to be made:
- include color_scheme and color_scheme_colors, also for parent and
child themes;
- internal translations were using preload_fields, but it was too deep
to correctly use preloaded tables. I had to pass
`preloaded_locale_fields` manually;
- include theme in color_scheme.
Before:
<img width="663" alt="Screenshot 2025-05-15 at 3 43 47 pm"
src="https://github.com/user-attachments/assets/b55ce11e-80cb-43eb-8e31-940b0e9859f3"
/>
After:
<img width="665" alt="Screenshot 2025-05-16 at 11 29 00 am"
src="https://github.com/user-attachments/assets/f00bac19-f64b-4048-b220-4d0a9d90a929"
/>
**Description**
As part of a customer request, we have added the option to search groups
by ID when doing API calls. However, in doing so we have decided to
correct the confusion around the group's routes. Previously the route
would look like `g/:id` while taking the `name` of the group as the
param. For example, when getting a group the route would be like this:
```
GET /g/admins
```
This would make the code in the controller seem as if it was handling
the group IDs instead of names. With these changes, this should be
addressed.
The new themes listing page at `/admin/config/customize/themes`
currently has poor performance compared to the components page
(`/admin/config/customize/components`) due to various N+1 issues,
loading all themes and components from the server when only themes are
needed, and serializing data/attributes that aren't needed for rendering
the themes grid.
This commit improves the performance by eliminating all N+1 that are
currently present, excluding components from the page payload, and
reducing the amount of data transmitted for each theme when loading the
page.
Similar to https://github.com/discourse/discourse/pull/32526.
Reviewer note: There had been some deliberation if we should just take
the `topic.first_post.locale` instead of having a `topic.locale`.
Ultimately, titles may be of a different language of the post itself,
and secondarily in some cases it could be faster without having to load
the first_post at all.
Chat is currently broken in local development if anonymous mode is enabled in site settings. This is happening after #32416. One of the strict_loading directives in ChannelFetcher is trickling down to an anonymous user check.
We don't need to enforce strict_loading on this 1-to-1 association that's only used in a few code paths, so mark it as strict_loading: false on the User model.
Previous to this change when we used to specify format it could get an
image
in the incorrect format.
Also... allows image magick to decode svg
---
There remains a bug where the crop / resize information is not stored in
optimized images
this means that sometimes when asking for a cropped image you may get a
resized one.
Previously we were compiling core and theme CSS into two targets:
Desktop and Mobile. The majority of both files was the 'common' css.
This commit splits those common styles into their own targets so that
there is less duplication. This should improve compilation times + cache
reuse, as well as opening the door for experiments with
media-query-based mobile-modes.
The only functional change is that we can no longer use `@extend` to
copy 'common' rules in core to mobile/desktop. This is probably for the
best. Duplication and/or mixins are a more native-css pattern for this.
Plugins already have a common / mobile / desktop pattern, so are
unchanged by this commit.
We are making this the only option for our login/signup
pages on April 29th, 2025, per
https://meta.discourse.org/t/introducing-our-new-fullscreen-signup-and-login-pages/340401.
This commit removes the `full_page_login` setting and any logic
around it, as well as deleting the old login and signup modals,
and removing leftover problem checks and settings from the database.
When ordering categories,
af8e48c1e0/app/models/category_list.rb (L61-L68)
Only one of the flows do `.group("categories.id")`.
This was causing sites with `SiteSetting.fixed_category_positions=true`
to 500 when another site setting
`SiteSetting.experimental_content_localization` was enabled. (Related:
https://github.com/discourse/discourse/pull/32464).
This commit fixes the issue by also grouping on the other case.
This commit adds
- `topic_localization` containing its topic, a locale, title, and
fancy_title
- `post_localization` containing its post, a locale, raw, cooked, the
associated post's version
- and also APIs to add them
Reviewer note: We may ask ourselves "why create separate models instead
of one that is generic?" but the different localizable models may be
vastly different. For example in posts we only have raw that we need to
translate, and topics we have only title, but for categories we have
name and description. Then, we may ask ourselves "why not create a
polymorphic one that takes in model and column name?" and then we end up
with the same thing as what we have currently which is custom fields
(which is a mess in itself). Also, when replacing the untranslated
content to the translated one, we may find it easier to just `join` +
`coalesce` on the dedicated table - it would be a much simpler query
than polymorphism.
A rework of https://github.com/discourse/discourse/pull/32460.
In the earlier PR that had to be reverted, we were directly deleting
cache (redis) and it was causing our image build to fail (see dev chat).
In this commit, we will rely on the existing method of invalid the keys
(which essentially will cause the next request to get the new site json
since the seq is not the same).