Commit Graph

3536 Commits

Author SHA1 Message Date
IEEE-754
4cb2bb5be0 i18n: Improve Traditional Chinese translations (#9037)
**Change(s)**
- Add missing punctuation
- Add missing spaces in the date format
- Add some new translations

**File(s) changed**
`app/i18n/zh-TW/{admin,conf,gen,install,sub}.php`
`README.md`
`README.fr.md`
2026-07-12 22:42:13 +02:00
Christos Longros
4b378ebea0 Improve Greek (el) translation (#9038)
* Improve Greek (el) translation

Complete install.php and translate reading-view sorting and
menu strings in index.php.

* Update translation completion tables
2026-07-12 12:36:23 +02:00
Gerard Alvear Porras
e24ac6f21c Sort labels with locale-aware collation (#9023)
Labels (tags) were sorted by the database's raw byte/ASCII collation
via ORDER BY name, so accented or non-Latin label names sorted after
all ASCII names instead of near their base letter.

Apply the same FreshRSS_Context::localeCompare() sort used for
categories, feeds, and shares (#8985) to TagDAO::listTags(), fixing
the last remaining sub-item of this issue; the others were already
resolved by #6212.

Fixes #6211

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-11 17:35:33 +02:00
Inverle
0f0b696cdf Display slider after submit for all buttons in feed/update.phtml (#8999)
Slight improvement of https://github.com/FreshRSS/FreshRSS/pull/8612
2026-07-11 17:04:12 +02:00
TowyTowy
ad78838ffc Keep search and state filters when marking articles as read (#9007)
* Keep search and state filters when marking articles as read

Marking articles as read (e.g. "mark all as read") POSTs to
entry?a=read and, for non-AJAX requests, redirects back to the index.
That redirect rebuilt its parameters without the current `search` and
`state`, so the view fell back to the default state and the active
search was dropped, forcing the user to re-apply their filter.

Carry `search` and `state` through the redirect, mirroring the existing
handling for `order`/`sort`, so the filtered view is preserved.

Fixes #8671

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Reduce comments a bit

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-09 21:13:14 +02:00
Jam Balaya
7744f1fed9 WebSub: ignore http/https scheme difference in Self URL comparison (#9005)
* WebSub: ignore http/https scheme difference in Self URL comparison

The PubSubHubbub endpoint logged 'Self URL does not match registered
canonical URL' whenever a feed's self URL differed from the registered
canonical URL only by http vs https (common with http->https redirects),
spamming the log. Compare the URLs ignoring the http/https scheme while
still requiring host/path/query to match exactly.

Closes #3087

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Stylistic preferences

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-09 07:50:42 +02:00
Jam Balaya
f201061345 Feeds tree: sort feed names with locale-aware collation (#8985)
## Problem

The feed **tree** (left sidebar) and the **feed-title view** (main body) order feeds differently for names with accents or symbols. As reported in #8300, a Spanish feed starting with `Ú` appears **last** in the tree, after every ASCII-named feed.

The tree is sorted in PHP by `FreshRSS_Category::sortFeeds()` with `strnatcasecmp()`, which compares raw UTF-8 **bytes** — so any name starting with a non-ASCII character (`0xC3…` for `Á`, `Ñ`, `Ú`, …) sorts after `A–Z`. The main view is sorted by the database according to its collation, which orders accented letters near their base letter — hence the mismatch (as @Alkarex noted in the issue).

Closes #8300.

## Change

`sortFeeds()` now compares with a `Collator` (`ext-intl`, already a hard requirement) for the user's language, falling back to the previous `strnatcasecmp()` if a collator cannot be created:

```php
$collator = \Collator::create(FreshRSS_Context::hasUserConf() ? FreshRSS_Context::userConf()->language : '');
```

Sorting a Spanish set, before / after:

```
old: banana, Manzana, nube, Zorro, Ábaco, Ñandú, Úlcera, árbol
new: Ábaco, árbol, banana, Manzana, nube, Ñandú, Úlcera, Zorro
```

This makes the tree order locale-aware and much closer to the main view. Exact parity with the main view still depends on the database collation (which is admin/DB-specific and cannot be reproduced generically in PHP), but the "accented names sort last" problem is gone.

* Feeds tree: sort feed names with locale-aware collation

The feed tree sorted names byte-wise with strnatcasecmp(), which places
names starting with a non-ASCII character (e.g. an accented capital such
as "U-acute") after every ASCII name. Use a Collator for the user's
language so accented and non-ASCII names sort near their base letter,
closer to the database collation used on the main feed-title view.

For https://github.com/FreshRSS/FreshRSS/issues/8300

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Guard Collator with class_exists() so intl stays optional

The intl extension is only a recommended (not required) dependency, but
sortFeeds() called \Collator::create() unconditionally when a user language
was set. On installs without intl the \Collator class does not exist, so the
call raised a fatal "Class \"Collator\" not found" — effectively promoting
intl from recommended to required.

Guard the call with class_exists('Collator'): when intl is absent, fall back
to the previous byte-wise strnatcasecmp() sort. Locale-aware ordering stays a
progressive enhancement and the listed requirements are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Shorten the sortFeeds() collation comment per review

Trim the rationale comment to a concise four lines as suggested in review,
keeping the locale-aware/fallback and class_exists() reasoning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Stylistic preference

* Factorise localeCompare

* Minor code preference

* Preserve natural locale sort behaviour

* Avoid repeated locale lookup in comparator

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-07 15:42:12 +02:00
Jam Balaya
ce7a196034 Remove unused simple layout (#8998)
Closes #6223.
Supersedes the investigation draft in #6765.

## Summary
- Removed the remaining explicit uses of the `simple` layout from the email-validation flows.
- Deleted `app/layout/simple.phtml` so those pages now use the shared `layout.phtml`.
- Kept the existing `disable_aside` behavior for the profile page while an email validation token is pending.

## Notes
The replacement for `simple.phtml` is the normal shared layout. Access while email validation is pending is still constrained by the existing `FreshRSS::checkEmailValidated()` route guard, which allows the validation/profile/logout paths and forwards other routes to `user#validateEmail`.
2026-07-07 15:04:11 +02:00
i @man
2188070aa6 Add option to keep or reset article sort order when navigating (#8969)
* Add option to keep or reset article sort order when navigating

Adds a new per-user reading option, "Keep the current sort order when
navigating between categories and feeds" (config key: sticky_sort), under
Settings > Reading > "Left navigation: Categories". It defaults to enabled,
which reproduces the current behaviour exactly.

Background (addresses #8953)
----------------------------
Once a sort/order was active in one view, it was propagated to every sidebar
link and to the "mark all as read" redirect. Opening another category then
ignored that category's own defaultSort/defaultOrder, because FreshRSS_Context
only applies those defaults when sort/order are absent from the request. As a
result the current view's sort (whether chosen manually or resolved from that
view's default) "bled" into the next category/feed.

Behaviour of the new option
---------------------------
- ON (default): unchanged. The current sort/order stays sticky while
  navigating, exactly as before.
- OFF: sidebar links and the "mark all as read" redirect no longer carry
  sort/order, so each target resolves its own order in FreshRSS_Context:
  feed/category defaultSort/defaultOrder, falling back to the global Reading
  sort criterion when none is configured.

order/sort propagation across the UI (for reference)
----------------------------------------------------
- Categories & feeds (sidebar): now gated by sticky_sort (app/layout/aside_feed.phtml).
- "Mark all as read" -> next category, both the top navigation button and the
  stream-footer button: now gated by sticky_sort
  (app/Controllers/entryController.php::readAction, non-AJAX redirect).
- Custom user queries: unaffected. A query's link is a self-contained URL built
  from that query's own saved parameters, so switching query A -> B never
  carried A's sort; no option is needed there.
- Stream transition links when sorting by category/feed name: intentionally
  left unchanged (out of scope; the sort is intrinsic to that grouping).

Compatibility
-------------
- Not a breaking change: the default (true) reproduces the previous behaviour.
- No database migration. The setting is a standard user configuration value
  with its default declared in config-user.default.php, so existing users keep
  the previous behaviour transparently.
- The read/unread state filter still persists across navigation regardless of
  this option.

i18n
----
English strings authored; en-US marked as IGNORE. Translations for the other
25 languages were produced with an automated (AI) translation service and
should be reviewed by native speakers.

* Update app/i18n/en/conf.php

Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>

* Comments preference

* Update app/i18n/en/conf.php

Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>

* i18n updates and comment

* Update translations to match reworded sticky_sort strings

Re-applies the 24 non-English/French translations of the "sticky_sort"
reading option after the English and French wording was updated to
"Keep manual sort order during navigation".

* improve Dutch

* i18n DIRTY

* i18n en: custom sort order

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>
2026-07-07 11:04:31 +02:00
Jam Balaya
271257be42 Fix statistics repartition averages (#8996)
* Fix statistics repartition averages

* Minor code preference

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-07 10:42:53 +02:00
Jam Balaya
310bcb5e90 Add read status hook for entries (#8995)
- Add a new `EntriesRead` / `entries_read` hook for extensions.
- Trigger the hook when `markRead()` changes entry read/unread state for explicit entry IDs.
- Cover both the default DAO path and the SQLite/PGSQL DAO path.
- Add Minz hook tests for the new hook signature and argument passing.

## Why

Extensions can already react to favorite/bookmark changes through `EntriesFavorite`. This adds the matching read/unread hook requested in #4051 for extensions that need to collect stats or react to manual read state changes.

Closes #4051
2026-07-07 09:04:32 +02:00
Jam Balaya
241c7fb425 Respect simplepie_syslog_enabled for cache-hit debug logs (#8986)
Two "uses cache" LOG_DEBUG syslog() calls were emitted on every feed
refresh regardless of the simplepie_syslog_enabled setting, so users who
disabled it still saw "FreshRSS SimplePie uses cache for ..." spam in
syslog (issue #8540). Guard both with simplepie_syslog_enabled, like the
neighbouring SimplePie GET logs already are. Real error and fatal logs
are left untouched.

For https://github.com/FreshRSS/FreshRSS/issues/8540

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:19:33 +02:00
Frans de Jonge
612ac4f117 Notifications: pluralize the "new articles" count message (#8988)
* Generate new articles notification string in PHP

Closes #6470

Changes proposed in this pull request:

- Generate notifications string  in PHP
- Use plurals support

* New articles notification: switch to plural forms

* README status

* fix paramInt invocation

* i18n

* make fix-all

* Apply suggestion from @Frenzie

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-06 11:16:29 +02:00
utkutibet
56d31c53de Improve turkish translation 3 (#8989)
* Translate remaining Turkish strings

* Translate remaining Turkish strings

---------

Co-authored-by: Utku Tibet <utkutibet@Utkus-MacBook-Pro.local>
2026-07-05 14:20:15 +02:00
Jam Balaya
cf2ceafca1 OPML: include each feed's refresh interval (TTL) in export/import (#8982)
Feeds moved between instances via OPML lost their refresh interval,
forcing manual reconfiguration. Add a 'frss:ttl' attribute (signed, so a
negative value also carries the muted state) to the OPML export, and read
it back on import. Documented in docs/en/developers/OPML.md.

For https://github.com/FreshRSS/FreshRSS/issues/5914

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 21:55:13 +02:00
Jam Balaya
c90e48fd62 Report new articles count per feed in actualize_script output (#8948)
* feat: report new articles count per feed in actualize_script output

Closes #8291

## Changes proposed in this pull request

`app/actualize_script.php` now reports, for each feed that received new articles, how many new articles were fetched — in addition to the existing per-user summary. This makes batch refreshes (cron / systemd timers) much more informative.

Example output:

```
FreshRSS actualize admin…
	10 new article(s) from feed: FreshRSS releases
	3 new article(s) from feed: Some other blog
```

The feature is implemented **entirely within the CLI script**, reusing the existing extension-hook mechanism that the script already uses for the actualization mutex — no change to `feedController` or to any other behaviour:

- `FeedBeforeActualize` records each feed's name.
- `EntryBeforeAdd` counts new entries per feed. This hook fires only in the "genuinely new GUID" branch of the actualization loop (updated articles go through `EntryBeforeUpdate`), so the count matches the controller's own `$nbNewArticles` counter. Because the counting hook is registered after `$app->init()`, it runs last in the chain and is skipped for entries dropped by another extension — i.e. it counts only articles that are actually added.

Counts are printed through the script's existing `notice()` helper, so they reach STDOUT regardless of the `environment` setting (unlike `Minz_Log::notice`, which is suppressed in `production`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Minor

* Remove tab
The tab character is escaped in some logs, e.g.

```
 [notice] --- \x091 new article(s) from feed: L’Express
```

* Sort per-feed output and also report updated articles

Addresses review feedback on #8948:
- Sort the per-feed report by descending article count, then feed name.
- Also count updated articles (via EntryBeforeUpdate) and report them
  alongside new ones, e.g. '10 new, 2 updated article(s) from feed: X'.
  EntryBeforeAdd fires only for new articles (new-GUID branch), so
  updated articles need the separate EntryBeforeUpdate hook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Reduced code

* Do not report feeds with no new or updated articles

FeedBeforeActualize initializes every actualized feed in $feedStatistics
and fires before the TTL/mute skips, so skipped or unchanged feeds would
otherwise print an empty count ('  article(s) from feed: X'). Skip them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Minor code logic preference

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-04 17:38:40 +02:00
Harry Andreolas
44b5c132b8 i18n: Update el (Greek) translations (#8977)
* Update el (i18n)

* Update CREDITS.md
2026-07-04 12:26:51 +02:00
utkutibet
da52ac4ee0 Translated remaining Turkish strings (#8970)
* Translate remaining Turkish strings

* Trigger CI re-run

* Update translation status

---------

Co-authored-by: Utku Tibet <utkutibet@Utkus-MacBook-Pro.local>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-04 12:22:20 +02:00
Inverle
8a5f7d24b6 Remove .DS_Store files and update .gitignore (#8971)
The `.DS_Store` files were accidentally added in #8966
2026-07-03 13:28:36 +02:00
utkutibet
2e6e571b91 Worked on Turkish translation (#8966)
* Worked on Turkish translation

* Add my name to CREDITS.md

* Run make fix-all

* Fix credits

---------

Co-authored-by: Utku Tibet <utkutibet@Utkus-MacBook-Pro.local>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-03 10:03:55 +02:00
Inverle
a3badc2d2e Fix bad header filtering bypass (#8964)
* Fix bad header filtering bypass

* Sanitize every save using `_attribute('curl_params')`

* Sanitize every read using `attributeArray('curl_params')`
2026-07-02 15:08:32 +02:00
dependabot[bot]
93e83943a3 chore(deps-dev): bump phpstan/phpstan from 2.2.2 to 2.2.3 (#8962)
* chore(deps-dev): bump phpstan/phpstan from 2.2.2 to 2.2.3

Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan-phar-composer-source) from 2.2.2 to 2.2.3.
- [Commits](https://github.com/phpstan/phpstan-phar-composer-source/commits)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-version: 2.2.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Ignore a could of redundant tests, for keeping additional safety

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-01 21:35:39 +02:00
Inverle
dcec27c69d Add SSRF mitigations using filter_var and CURLOPT_RESOLVE (#8400)
* Add SSRF mitigations using `filter_var` and `CURLOPT_RESOLVE`
The idea is to prevent FreshRSS from sending any HTTP requests to internal services, except for the ones that are explicitly allowed in the config.

Based on 6e82b46a48/lib/filelib.php (L3818) and https://github.com/symfony/symfony/blob/8.1/src/Symfony/Component/HttpClient/NoPrivateNetworkHttpClient.php

https://github.com/FreshRSS/simplepie/pull/76
https://github.com/FreshRSS/simplepie/pull/78

* Add allowlist setting in Web UI

* make readme

* Update app/i18n/fr/admin.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* make readme again

* make readme

* Further work

Still WIP and needs testing etc.

* Readd previous if check for domain combination allowlist

* Turn POST to GET after redirect

* Improve

* Update config.default.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* make readme

* Skip SSRF check if `CURLOPT_PROXY` is set

* make readme

* Fix `!empty()` mistake

* Respect max redirects feed option when fetching with `httpGet()`

* Respect max redirects during SimplePie fetching + fix bypass

bypass fix: `CURLOPT_FOLLOWLOCATION` was moved below so that emulated redirects are enforced.

* Avoid FreshRSS and Minz code in SimplePie
https://github.com/FreshRSS/FreshRSS/pull/8400#discussion_r2935375980

* Corrected hook code

* phpdoc wrong return type

* Add CIDR support in allowlist

* Implement simple DNS caching

* Suppress `dns_get_record()` warnings

* A bit of proof-reading

* Minor typo

* Fix proxy logic

* Fix HTTP POST redirect logic

* Proofread checkCIDR
Add fixes for several situations

* Remove credentials from URL in logs

* Ensure `CURLOPT_FOLLOWLOCATION` is `false` by setting it at the end

* Fix codesniffer long line

* Fix potential bypass due to wrong return value

If there were no records returned by `dns_get_record()`, no overrides to `CURLOPT_RESOLVE` would get passed,
and a potential bypass could occur, when cURL would try to resolve the domain by itself.

* Put the URL at the end in logs

* Add documentation and environment variable support

* make readme

* Fix wrong behavior in case of IP

* Fix duplicate selector in CSS

* Minor type check change

* i18n fr, en

* Minor type check change

* Fix whitespace i18n fr

* make fix-all

* Fix `$ips_ok` not being returned after domain records were cached

* make readme

* PHPStan fix

* make readme

* Minor syntax in SimplePie

* Only return `null` if no allowed IPs were found

* Add wildcard *, help message

* Consistent docs with help message

* i18n: pl

* SimplePie compatibility PHP 7.2

* make fix-all

* Sync SimplePie
* https://github.com/FreshRSS/simplepie/pull/76

* 💥 Breaking change in the Changelog

* Document `INTERNAL_HOST_ALLOWLIST` in Docker docs

* Remove `Cookie` and `Authorization` headers in `httpGet()` during cross-origin redirect

* Minor whitespace
And same comment convention than below

* Remove authentication headers and change POST to GET on redirect in SimplePie

* Remove .local in Docker example

* Fill in default ports when comparing URL origins

* Remove .local from other places than the Docker example

* Rewrite WebSub subscribe to use `httpGet()`

* make fix-all

* Also unset `CURLOPT_USERPWD` during redirects

* phpcs fix

* Always unset `CURLOPT_FOLLOWLOCATION`

* Bump SimplePie
https://github.com/FreshRSS/simplepie/pull/78

* Update logic for CURLOPT_FOLLOWLOCATION

* Fix PHPStan

* Changelog fix security section

* Update most common RSS Bridge case
https://hub.docker.com/r/rssbridge/rss-bridge

* Replace misleading 127.0.0.1:8080 example for Docker
This does not make sense for a Docker container

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-06-28 18:51:04 +02:00
Thomas Vermeer
3161fd1333 fix: move disable button before remove button in user management (#8944)
* fix: move disable button before remove button in user management

The order of action buttons when modifying a user was inconsistent.
The "disable" button appeared after the "remove" button, which is
counterintuitive since disabling a user is a less destructive action
than removing one.

This commit reorders the buttons in `details.phtml` to reflect the
severity of each action, from least to most destructive:
update → purge → promote/demote → disable/enable → delete

Closes #8877

* Remove blank lines

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-06-27 14:29:48 +02:00
Inverle
931d62ab08 Use timing safe comparison for tokens everywhere (#8945)
I already changed some places that were using normal string comparison to hash_equals before, but didn't check other places.

Now the checks should be consistent.
2026-06-27 14:02:20 +02:00
Mohammad Lashkari
53ca983ef2 Complete the Persian translation (#8923)
Translate remaining TODO and DIRTY entries in the Persian locale.
2026-06-14 21:30:56 +02:00
Inverle
1349c7c1a9 SimplePie: Disallow javascript: URI protocol (#8263)
Follow-up of https://github.com/FreshRSS/FreshRSS/pull/7924
https://github.com/FreshRSS/simplepie/pull/80
https://github.com/FreshRSS/simplepie/pull/65

* SimplePie: Disallow `javascript:` URI protocol

* Sync SimplePie

* Update code to work with SimplePie again

* Partial revert previous commit

* Bump SimplePie

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-06-13 21:15:36 +02:00
Inverle
5e18e96887 Set limits for regex during search (#8913)
Prevents regex searches from running for too long
2026-06-05 23:12:59 +02:00
Inverle
bf2de1baea Fix access control in rss and opml actions (#8912)
Due to missing `return` statement while using `redirect: false`, no `exit()` is done during `Minz_Error::error()`

Regression from https://github.com/FreshRSS/FreshRSS/pull/8434
2026-06-05 22:38:17 +02:00
Mass Krdjn
6592f45163 i18n: complete Spanish (es) translation (#8878)
* i18n: complete Spanish (es) translation

* Apply suggestions from pe1uca

Co-authored-by: pe1uca <15692727+pe1uca@users.noreply.github.com>

* make fix-all

---------

Co-authored-by: Mass Krdjn <172580248+masskrdjn@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Co-authored-by: pe1uca <15692727+pe1uca@users.noreply.github.com>
2026-06-01 16:31:25 +02:00
Mass Krdjn
159894f9f6 i18n: complete Italian (it) translation (#8880)
* i18n: complete Italian (it) translation

* make fix-all

---------

Co-authored-by: Mass Krdjn <172580248+masskrdjn@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-25 16:59:49 +02:00
Alexandre Alapetite
542f4920e7 Fix lost elements while parsing search query (#8884)
Fix https://github.com/FreshRSS/FreshRSS/issues/8876
2026-05-24 20:23:58 +02:00
Mass Krdjn
803f92e6d3 i18n: complete Hungarian (hu) translation (#8879)
* i18n: complete Hungarian (hu) translation

* make fix-all

---------

Co-authored-by: Mass Krdjn <172580248+masskrdjn@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-24 13:26:31 +02:00
Alexandre Alapetite
4b019ab697 New option to hide badges showing number of unread articles (#8844)
Inspired by @Dan-Q's  *Reducing Phantom Obligation in FreshRSS* https://danq.me/2026/02/06/phantom-obligation-vs-freshrss/

<img width="512" height="105" alt="image" src="https://github.com/user-attachments/assets/df93118b-36f3-4175-a681-b3f81fe63ff2" />

Results in:

<img width="306" height="181" alt="image" src="https://github.com/user-attachments/assets/1c8ccaa6-4fcf-48a4-bf98-0ace43a68861" />

Can be overridden at category and feed levels.
2026-05-20 20:25:20 +02:00
Frans de Jonge
93f989b977 Add a warning message to the API password section, add a log warning when a client uses GET, use POST in sample curl API usage (#8845)
* Add a warning message to the API password section, add a log warning when a client uses GET, use POST in sample curl API usage

References #8834.

* Apply suggestion from @Inverle

Co-authored-by: Inverle <inverle@proton.me>

* Apply suggestion from @Inverle (Polish translation)

Co-authored-by: Inverle <inverle@proton.me>

* French translation

* Dutch translation

* German

* Apply suggestion from @Inverle api via post

Co-authored-by: Inverle <inverle@proton.me>

* Apply suggestion from @Inverle via POST (French)

Co-authored-by: Inverle <inverle@proton.me>

* Add user-agent

* update translation info in README

* avoid phpcs line too long

* also trigger on email as suggested by @Inverle

* i18n: fr typography

* make fix-all

---------

Co-authored-by: Inverle <inverle@proton.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-20 20:09:02 +02:00
Denys Nykula
2000b8dd84 Update Ukrainian translation (#8871)
* Update Ukrainian translation

* Change outer double quotes with inner single quote to single quotes only in Ukrainian translation
2026-05-20 20:01:46 +02:00
Frans de Jonge
a611209a7c Finish Dutch translation (#8868)
* Finish Dutch translation

* 100%
2026-05-20 00:03:54 +02:00
Alexandre Alapetite
8e007af39d Fiix cookies with some browsers (#8867)
Fix https://github.com/FreshRSS/FreshRSS/issues/8850
Fix login with e.g. SeaMonkey
Regression due to https://github.com/FreshRSS/FreshRSS/pull/8778
2026-05-19 23:03:51 +02:00
Alexandre Alapetite
b7c58e590e Add ignore for PHPStan 2.1.55+ (#8864) 2026-05-19 22:07:52 +02:00
Alexandre Alapetite
c3fa374f25 Fix empty entry Generator (#8863)
* Fix empty entry Generator
Fix https://github.com/FreshRSS/FreshRSS/issues/8857
Regression from https://github.com/FreshRSS/FreshRSS/pull/8789
This is due to https://bugs.php.net/bug.php?id=77515

* Use EmptyIterator instead

* Syntax update
2026-05-19 21:45:20 +02:00
McFev
02edc05035 i18n: ru (#8839) (#8861)
* i18n: ru (#8839)

* make fix-all

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-19 08:20:15 +02:00
Inverle
51441abf7c Improve Polish translations (#8854)
Adds missing translations (https://github.com/FreshRSS/FreshRSS/issues/8839) and improves some existing ones.

* Add new pl translations

* Consistency: `artykuł` -> `wiadomość`

* Consistency: `ilość` -> `liczba`
2026-05-17 20:25:23 +02:00
IEEE-754
4102417fc1 i18n: Improve Traditional Chinese translations (#8849)
#8839 

**Change(s)**
- Fix some typos
- Revise the translations that I hadn't checked before
- Add some new translations

**File(s) changed**
`app/i18n/zh-TW/{admin,conf,gen,sub,user}.php`
`README.md`
`README.fr.md`
2026-05-16 12:09:37 +02:00
Ciro Mota
e704dea906 feat: Added news Português Brasil translation (#8846)
* feat: Added news Português Brasil translation

* fix: Translation string

* make fix-all

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-15 23:43:56 +02:00
Christian Weiske
d017e22a46 i18n(de): Add missing translations (#8840)
Related: https://github.com/FreshRSS/FreshRSS/issues/8839
2026-05-15 13:31:45 +02:00
Alexandre Alapetite
146d5f0d60 Fix ensure maximum number of feeds also with Dynamic OPML (#8832)
Fix https://github.com/FreshRSS/FreshRSS/issues/8822
And also add a warning sign in case of error.
Fix related bug about showing errored categories.
2026-05-15 12:19:40 +02:00
Alexandre Alapetite
66568f0283 TXT import compatibility HTML comments (#8837)
Discard lines starting with `<` for e.g. HTML/XML comments, tags
Compatibility with TXT format of https://atlasflux.saynete.net
Follow-up of https://github.com/FreshRSS/FreshRSS/pull/8818
2026-05-15 12:10:55 +02:00
polybjorn
8863cdcaf8 feat(import): accept .txt URL lists alongside OPML/JSON/ZIP (#8818)
* feat(import): accept .txt URL lists alongside OPML/JSON/ZIP

Detects .txt by extension and wraps the URL list into a minimal OPML
document so the existing import pipeline handles dedup, categories and
feed limits unchanged. Blank lines, `#` comments and a UTF-8 BOM are
skipped; lines that don't parse as URLs are logged and dropped without
aborting the batch.

Works through both `cli/import-for-user.php` and the web import form.

* utf8BOM

* ENT_COMPAT

---------

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-12 10:52:00 +02:00
polybjorn
d74337deb6 feat(cli): automatic periodic SQLite export with retention (#8819)
Add an opt-in CLI that exports each user's database to
`data/users/<user>/sqlite-backups/<YYYYMMDDTHHMMSSZ>.sqlite` (UTC) and
prunes older files to a configured count. Gated by two new settings,
`auto_sqlite_export.enabled` and `auto_sqlite_export.retention`.

Kept separate from `cli/db-backup.php` / `cli/db-restore.php`, which
stay the fixed-filename migration tool. First step of #8183.

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
2026-05-12 08:44:00 +02:00
polybjorn
43b10f1d70 fix(themes): use has-date class for date-aware list layout (#8811)
Replace four :has(~.date) selectors with a has-date modifier class
on .flux_header, mirroring the existing has-thumbnail and has-summary
classes. The condition (whether the date is rendered) is known
server-side and can be exposed on the parent <ul> directly. Same
elements matched in modern browsers. The rules now also apply in
browsers without :has() support, fixing the date column overlapping
the title in SeaMonkey (#6776).

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
2026-05-11 20:20:46 +02:00