#### What type of PR is this?
/kind bug
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR check if the locale is undetermined during resolving locale. Or it will cause the error below if locale is `und`:
```java
2025-05-21T17:28:45.953+08:00 ERROR 58760 --- [undedElastic-14] o.s.w.s.adapter.HttpWebHandlerAdapter : [c1824fa5-1] 500 Server Error for HTTP GET "/"
org.thymeleaf.exceptions.TemplateOutputException: An error happened during template rendering
at org.thymeleaf.engine.OutputTemplateHandler.handleText(OutputTemplateHandler.java:75) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.AbstractTemplateHandler.handleText(AbstractTemplateHandler.java:221) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleText(ProcessorTemplateHandler.java:587) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Text.beHandled(Text.java:97) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.GatheringModelProcessable.process(GatheringModelProcessable.java:78) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1642) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.CloseElementTag.beHandled(CloseElementTag.java:139) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTagModelProcessable.process(OpenElementTagModelProcessable.java:110) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1559) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:155) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:235) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:200) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.spring6.SpringWebFluxTemplateEngine$StreamThrottledTemplateProcessor.process(SpringWebFluxTemplateEngine.java:720) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.spring6.SpringWebFluxTemplateEngine.lambda$createChunkedStream$2(SpringWebFluxTemplateEngine.java:269) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:271) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:213) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:85) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:68) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.scheduler.BoundedElasticThreadPerTaskScheduler$SchedulerTask.run(BoundedElasticThreadPerTaskScheduler.java:1013) ~[reactor-core-3.7.5.jar:3.7.5]
at java.base/java.lang.VirtualThread.run(VirtualThread.java:329) ~[na:na]
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Locale "" cannot be used as it does not specify a language. (template: "modules/layout" - line 12, col 49)
at org.thymeleaf.messageresolver.StandardMessageResolutionUtils.computeMessageResourceNamesFromBase(StandardMessageResolutionUtils.java:202) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolutionUtils.resolveMessagesForTemplate(StandardMessageResolutionUtils.java:69) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessagesForTemplate(StandardMessageResolver.java:380) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessage(StandardMessageResolver.java:282) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessage(StandardMessageResolver.java:227) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.context.AbstractEngineContext.getMessage(AbstractEngineContext.java:134) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.MessageExpression.executeMessageExpression(MessageExpression.java:265) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:69) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.processor.StandardUtextTagProcessor.doProcess(StandardUtextTagProcessor.java:87) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:136) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateManager.process(TemplateManager.java:519) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.LazyProcessingCharSequence.writeUnresolved(LazyProcessingCharSequence.java:85) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.AbstractLazyCharSequence.write(AbstractLazyCharSequence.java:103) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.AbstractTextualTemplateEvent.writeContent(AbstractTextualTemplateEvent.java:224) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Text.write(Text.java:78) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OutputTemplateHandler.handleText(OutputTemplateHandler.java:71) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
... 29 common frames omitted
```
#### Does this PR introduce a user-facing change?
```release-note
修复因 Locale 解析错误导致无法访问页面的问题
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR removes `/uploads/**` from static resources to make it protected by Halo security.
#### Does this PR introduce a user-facing change?
```release-note
None
```
* refactor: improve entity component layout for better device responsiveness
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Resolve CSS style conflicts
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Update missing translaions
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR sets Java 21 as minimal version. After doing that, Halo can only run on Java 21 or newer version.
Fortunately, all plugins and themes won't be affected by the restriction.
> https://docs.gradle.org/current/userguide/toolchains.html#sec:release-flag-toolchain
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/6867
#### Does this PR introduce a user-facing change?
```release-note
[Action Required] 更新最低运行环境为 Java 21
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
Defining `into` property in `processResources` task is not working, so I create a new copy task to process UI dist.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind cleanup
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR bumps versions to 2.21.0-SNAPSHOT, including ui packages and API client.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
#### What this PR does / why we need it:
过期的Spring @Component API
#### Which issue(s) this PR fixes:
Fixes#7431
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/area plugin
/area editor
/milestone 2.20.x
#### What this PR does / why we need it:
Previously, editor extension related types were not exported because the type names conflicted with some UI component names, making it impossible to import extension types in plugins. This PR modifies the type names and exports them in index.ts.
#### Does this PR introduce a user-facing change?
```release-note
导出与编辑器扩展相关的类型定义
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR adds support for redirection on logout. We can request <http://localhost:8090/logout?redirect_uri=/archives> with GET method, then click the logout to see the redirection.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7401
#### Does this PR introduce a user-facing change?
```release-note
登出页面支持自定义重定向
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
1. This PR removes duplicate invocations while resolving handler functions of theme.
2. Throw NotFoundException while post was not found.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7409
#### Does this PR introduce a user-facing change?
```release-note
修复访问不存在的分类或者文章页面时始终抛出异常的问题
```
#### What type of PR is this?
/kind feature
#### What this PR does / why we need it:
标签支持根据文章量排序
#### Does this PR introduce a user-facing change?
```release-note
标签支持根据文章量排序
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR adds SwitchUserGrantedAuthorityMixin into HaloSecurityJackson2Module to fix the deserialization error.
See https://github.com/halo-dev/halo/issues/7406 for more.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7406
#### Does this PR introduce a user-facing change?
```release-note
修复个人中心处可能出现登录设备查询异常的问题
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR makes Argon2 password encoder as default to remove password limit of 72.
Please note that there is no compatibility issue for old passwords.
#### Which issue(s) this PR fixes:
Fixes#7405
#### Special notes for your reviewer:
1. Try to login as admin
2. Create a password having the length of 73 or more for a new user
3. See the result
#### Does this PR introduce a user-facing change?
```release-note
修复无法设置长度超过72个字符的密码的问题
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR adds therapi-runtime-javadoc dependency and annotationProcessor for api and application projects. After doing that, SpringDoc will introspect Javadoc annotations and comments. See https://springdoc.org/#javadoc-support for more.
For support in plugin, just add an annotationProcessor like below:
```gradle
dependencies {
implementation platform('run.halo.tools.platform:plugin:2.20.8-SNAPSHOT')
compileOnly 'run.halo.app:api'
annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.13.0'
}
```
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR bumps Spring Boot to [3.4.5](https://github.com/spring-projects/spring-boot/releases/tag/v3.4.5).
#### Which issue(s) this PR fixes:
Fixes#7374
#### Does this PR introduce a user-facing change?
```release-note
升级依赖 Spring Boot 至 3.4.5,同时解决可能无法登录的问题
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR upgrades Gradle to 8.13.
#### Does this PR introduce a user-facing change?
```release-note
升级构建工具 Gradle 至 8.13
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
修复 Unstructured Metadata 的 equals hashcode 排除 version,这可能是之前误操作提交的
ed50a0224d/api/src/main/java/run/halo/app/extension/Unstructured.java (L75)
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind feature
/area ui
/milestone 2.20.x
#### What this PR does / why we need it:
Add support for multiple roles during user creation
#### Which issue(s) this PR fixes:
Fixes#7325
#### Does this PR introduce a user-facing change?
```release-note
新建用户时支持设置多个角色
```
#### What type of PR is this?
/area ui
/kind improvement
/milestone 2.20.x
#### What this PR does / why we need it:
Use `Promise.all` to execute part of the batch operation logic of the post in chunks to optimize the execution performance.
#### Which issue(s) this PR fixes:
Fixes #
#### Does this PR introduce a user-facing change?
```release-note
优化文章部分批量操作的执行性能
```
#### What type of PR is this?
/kind bug
#### What this PR does / why we need it:
This PR manually set UTF-8 charset while loading YAML file to fix the problem "java.nio.charset.MalformedInputException: Input length = 1".
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/6937
Fixes https://github.com/orgs/halo-dev/discussions/7375
#### Does this PR introduce a user-facing change?
```release-note
修复 Windows 下可能无法正常初始化的问题
```
### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
In PR <https://github.com/halo-dev/halo/pull/7371>, I used strong secure random to generate metadata name, but the random may cause system block in some specific environments. See https://github.com/orgs/lxware-dev/discussions/13#discussioncomment-12907298 for more.
So this PR revert the use of strong secure random.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR use secure-strong SecureRandom to generate unpredictable metadata name. Meanwhile, the length of generate name suffix is increased to `8` and lower-case is to prevent data conflicts caused by database case sensitivity as possible.
Another improvement is using bounded-elastic thread to run the method `secureString()#nextAlphanumeric` because the method contains blocking operation, which might cause system block.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR removes application startup steps buffer to reduce memory usage.
#### Does this PR introduce a user-facing change?
```release-note
None
```