diff options
| author | 2025-10-14 11:05:17 +0200 | |
|---|---|---|
| committer | 2025-10-14 11:05:17 +0200 | |
| commit | 5eba322cbd24191e05304df08c80af846977d99b (patch) | |
| tree | 6f41386abfc77937fb042e48ca061e6dc0d2a7a5 | |
| parent | 20ecbeb09cdf05ca3ffd44980e9070b34c2b71ec (diff) | |
New stats overview of dates with most unread articles (#8089)
New view with direct links to dates with most unread articles:
<img width="734" height="581" alt="image" src="https://github.com/user-attachments/assets/159a39b3-3a06-4ae9-9cc0-62ae36d9db9c" />
63 files changed, 299 insertions, 25 deletions
diff --git a/README.fr.md b/README.fr.md index 5d0eb8c56..d5b055ee6 100644 --- a/README.fr.md +++ b/README.fr.md @@ -227,31 +227,31 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio | Langage | Progression | | | - | - | - | | Čeština (cs) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fcs+%2F%28TODO%7CDIRTY%29%24%2F) | -| Deutsch (de) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fde+%2F%28TODO%7CDIRTY%29%24%2F) | +| Deutsch (de) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fde+%2F%28TODO%7CDIRTY%29%24%2F) | | Ελληνικά (el) | ■■・・・・・・・・ 22% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fel+%2F%28TODO%7CDIRTY%29%24%2F) | | English (en) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fen+%2F%28TODO%7CDIRTY%29%24%2F) | | English (United States) (en-US) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fen-US+%2F%28TODO%7CDIRTY%29%24%2F) | | Español (es) | ■■■■■■■■■・ 91% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fes+%2F%28TODO%7CDIRTY%29%24%2F) | | فارسی (fa) | ■■■■■■■■■・ 97% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffa+%2F%28TODO%7CDIRTY%29%24%2F) | -| Suomi (fi) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffi+%2F%28TODO%7CDIRTY%29%24%2F) | +| Suomi (fi) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffi+%2F%28TODO%7CDIRTY%29%24%2F) | | Français (fr) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffr+%2F%28TODO%7CDIRTY%29%24%2F) | | עברית (he) | ■■■■・・・・・・ 45% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhe+%2F%28TODO%7CDIRTY%29%24%2F) | -| Magyar (hu) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%24%2F) | +| Magyar (hu) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%24%2F) | | Bahasa Indonesia (id) | ■■■■■■■■■・ 96% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fid+%2F%28TODO%7CDIRTY%29%24%2F) | | Italiano (it) | ■■■■■■■■■・ 96% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fit+%2F%28TODO%7CDIRTY%29%24%2F) | -| 日本語 (ja) | ■■■■■■■■■・ 95% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) | +| 日本語 (ja) | ■■■■■■■■■・ 94% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) | | 한국어 (ko) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fko+%2F%28TODO%7CDIRTY%29%24%2F) | | Latviešu (lv) | ■■■■■■■■・・ 82% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Flv+%2F%28TODO%7CDIRTY%29%24%2F) | | Nederlands (nl) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%24%2F) | -| Occitan (oc) | ■■■■■■■■・・ 81% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Foc+%2F%28TODO%7CDIRTY%29%24%2F) | -| Polski (pl) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%24%2F) | -| Português (Brasil) (pt-BR) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%24%2F) | +| Occitan (oc) | ■■■■■■■■・・ 80% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Foc+%2F%28TODO%7CDIRTY%29%24%2F) | +| Polski (pl) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%24%2F) | +| Português (Brasil) (pt-BR) | ■■■■■■■■・・ 87% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%24%2F) | | Português (Portugal) (pt-PT) | ■■■■■■■■・・ 87% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-PT+%2F%28TODO%7CDIRTY%29%24%2F) | | Русский (ru) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fru+%2F%28TODO%7CDIRTY%29%24%2F) | | Slovenčina (sk) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fsk+%2F%28TODO%7CDIRTY%29%24%2F) | | Türkçe (tr) | ■■■■■■■■■・ 96% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ftr+%2F%28TODO%7CDIRTY%29%24%2F) | -| Українська (uk) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fuk+%2F%28TODO%7CDIRTY%29%24%2F) | -| 简体中文 (zh-CN) | ■■■■■■■■■・ 90% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fzh-CN+%2F%28TODO%7CDIRTY%29%24%2F) | +| Українська (uk) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fuk+%2F%28TODO%7CDIRTY%29%24%2F) | +| 简体中文 (zh-CN) | ■■■■■■■■・・ 89% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fzh-CN+%2F%28TODO%7CDIRTY%29%24%2F) | | 正體中文 (zh-TW) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fzh-TW+%2F%28TODO%7CDIRTY%29%24%2F) | </translations> @@ -123,31 +123,31 @@ See the [repository dedicated to those extensions](https://github.com/FreshRSS/E | Language | Progress | | | - | - | - | | Čeština (cs) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fcs+%2F%28TODO%7CDIRTY%29%24%2F) | -| Deutsch (de) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fde+%2F%28TODO%7CDIRTY%29%24%2F) | +| Deutsch (de) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fde+%2F%28TODO%7CDIRTY%29%24%2F) | | Ελληνικά (el) | ■■・・・・・・・・ 22% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fel+%2F%28TODO%7CDIRTY%29%24%2F) | | English (en) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fen+%2F%28TODO%7CDIRTY%29%24%2F) | | English (United States) (en-US) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fen-US+%2F%28TODO%7CDIRTY%29%24%2F) | | Español (es) | ■■■■■■■■■・ 91% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fes+%2F%28TODO%7CDIRTY%29%24%2F) | | فارسی (fa) | ■■■■■■■■■・ 97% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffa+%2F%28TODO%7CDIRTY%29%24%2F) | -| Suomi (fi) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffi+%2F%28TODO%7CDIRTY%29%24%2F) | +| Suomi (fi) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffi+%2F%28TODO%7CDIRTY%29%24%2F) | | Français (fr) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffr+%2F%28TODO%7CDIRTY%29%24%2F) | | עברית (he) | ■■■■・・・・・・ 45% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhe+%2F%28TODO%7CDIRTY%29%24%2F) | -| Magyar (hu) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%24%2F) | +| Magyar (hu) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%24%2F) | | Bahasa Indonesia (id) | ■■■■■■■■■・ 96% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fid+%2F%28TODO%7CDIRTY%29%24%2F) | | Italiano (it) | ■■■■■■■■■・ 96% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fit+%2F%28TODO%7CDIRTY%29%24%2F) | -| 日本語 (ja) | ■■■■■■■■■・ 95% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) | +| 日本語 (ja) | ■■■■■■■■■・ 94% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) | | 한국어 (ko) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fko+%2F%28TODO%7CDIRTY%29%24%2F) | | Latviešu (lv) | ■■■■■■■■・・ 82% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Flv+%2F%28TODO%7CDIRTY%29%24%2F) | | Nederlands (nl) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%24%2F) | -| Occitan (oc) | ■■■■■■■■・・ 81% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Foc+%2F%28TODO%7CDIRTY%29%24%2F) | -| Polski (pl) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%24%2F) | -| Português (Brasil) (pt-BR) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%24%2F) | +| Occitan (oc) | ■■■■■■■■・・ 80% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Foc+%2F%28TODO%7CDIRTY%29%24%2F) | +| Polski (pl) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%24%2F) | +| Português (Brasil) (pt-BR) | ■■■■■■■■・・ 87% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%24%2F) | | Português (Portugal) (pt-PT) | ■■■■■■■■・・ 87% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-PT+%2F%28TODO%7CDIRTY%29%24%2F) | | Русский (ru) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fru+%2F%28TODO%7CDIRTY%29%24%2F) | | Slovenčina (sk) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fsk+%2F%28TODO%7CDIRTY%29%24%2F) | | Türkçe (tr) | ■■■■■■■■■・ 96% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ftr+%2F%28TODO%7CDIRTY%29%24%2F) | -| Українська (uk) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fuk+%2F%28TODO%7CDIRTY%29%24%2F) | -| 简体中文 (zh-CN) | ■■■■■■■■■・ 90% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fzh-CN+%2F%28TODO%7CDIRTY%29%24%2F) | +| Українська (uk) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fuk+%2F%28TODO%7CDIRTY%29%24%2F) | +| 简体中文 (zh-CN) | ■■■■■■■■・・ 89% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fzh-CN+%2F%28TODO%7CDIRTY%29%24%2F) | | 正體中文 (zh-TW) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fzh-TW+%2F%28TODO%7CDIRTY%29%24%2F) | </translations> diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php index 4491443c0..7c1791dd6 100644 --- a/app/Controllers/statsController.php +++ b/app/Controllers/statsController.php @@ -246,4 +246,18 @@ class FreshRSS_stats_Controller extends FreshRSS_ActionController { $this->view->hours24Labels = $hours24Labels; } + + public function unreadDatesAction(): void { + $statsDAO = FreshRSS_Factory::createStatsDAO(); + $field = Minz_Request::paramString('field', plaintext: true); + if (!in_array($field, ['id', 'date'], true)) { + $field = 'id'; + } + $granularity = Minz_Request::paramString('granularity', plaintext: true); + if (!in_array($granularity, ['day', 'month', 'year'], true)) { + $granularity = 'day'; + } + $dates = $statsDAO->getMaxUnreadDates($field, $granularity, Minz_Request::paramInt('max') ?: 100); + $this->view->unreadDates = $dates; + } } diff --git a/app/Models/StatsDAO.php b/app/Models/StatsDAO.php index 771a2c7ee..c10567951 100644 --- a/app/Models/StatsDAO.php +++ b/app/Models/StatsDAO.php @@ -5,6 +5,30 @@ class FreshRSS_StatsDAO extends Minz_ModelPdo { public const ENTRY_COUNT_PERIOD = 30; + /** Get the number of seconds to add to UTC to get the user's local time */ + protected function getTimezoneOffset(): int { + $timezone = new DateTimeZone(date_default_timezone_get()); + return $timezone->getOffset(new DateTime('now', new DateTimeZone('UTC'))); + } + + /** + * @param string $field to use for the date + * @param int $precision to apply to the timestamp (1 for seconds, 1000 for milliseconds, 1000000 for microseconds) + * @param 'day'|'month'|'year' $granularity of the date intervals + */ + protected function sqlDateToIsoGranularity(string $field, int $precision, string $granularity): string { + if (!preg_match('/^[a-zA-Z0-9_]+$/', $field)) { + throw new InvalidArgumentException('Invalid date field!'); + } + $offset = $this->getTimezoneOffset(); + return match ($granularity) { + 'day' => "FROM_UNIXTIME(($field / $precision) + $offset, '%Y-%m-%d')", + 'month' => "FROM_UNIXTIME(($field / $precision) + $offset, '%Y-%m')", + 'year' => "FROM_UNIXTIME(($field / $precision) + $offset, '%Y')", + default => throw new InvalidArgumentException('Invalid date granularity!'), + }; + } + protected function sqlFloor(string $s): string { return "FLOOR($s)"; } @@ -132,8 +156,9 @@ SQL; if ($feed) { $restrict = "WHERE e.id_feed = {$feed}"; } + $offset = $this->getTimezoneOffset(); $sql = <<<SQL -SELECT DATE_FORMAT(FROM_UNIXTIME(e.date), '{$period}') AS period +SELECT DATE_FORMAT(FROM_UNIXTIME(e.date + {$offset}), '{$period}') AS period , COUNT(1) AS count FROM `_entry` AS e {$restrict} @@ -356,4 +381,26 @@ SQL; return $translated; } + + /** + * Gets the date intervals with the largest number of unread articles. + * @param 'id'|'date' $field to use for the date + * @param 'day'|'month'|'year' $granularity of the date intervals + * @return list<array{'granularity':string,'unread_count':int}> + */ + public function getMaxUnreadDates(string $field, string $granularity, int $max = 100): array { + $sql = <<<SQL +SELECT + {$this->sqlDateToIsoGranularity($field, precision: $field === 'id' ? 1000000 : 1, granularity: $granularity)} AS granularity, + COUNT(*) AS unread_count +FROM `_entry` +WHERE is_read = 0 +GROUP BY granularity +ORDER BY unread_count DESC, granularity DESC +LIMIT $max; +SQL; + $res = $this->fetchAssoc($sql); + /** @var list<array{granularity:string,unread_count:int}>|null $res */ + return is_array($res) ? $res : []; + } } diff --git a/app/Models/StatsDAOPGSQL.php b/app/Models/StatsDAOPGSQL.php index 5e3476808..c4a5e5c05 100644 --- a/app/Models/StatsDAOPGSQL.php +++ b/app/Models/StatsDAOPGSQL.php @@ -3,6 +3,17 @@ declare(strict_types=1); class FreshRSS_StatsDAOPGSQL extends FreshRSS_StatsDAO { + #[\Override] + protected function sqlDateToIsoGranularity(string $field, int $precision, string $granularity): string { + $offset = $this->getTimezoneOffset(); + return match ($granularity) { + 'day' => "to_char(to_timestamp(($field / $precision) + $offset), 'YYYY-MM-DD')", + 'month' => "to_char(to_timestamp(($field / $precision) + $offset), 'YYYY-MM')", + 'year' => "to_char(to_timestamp(($field / $precision) + $offset), 'YYYY')", + default => throw new InvalidArgumentException('Invalid date granularity'), + }; + } + /** * Calculates the number of article per hour of the day per feed * @@ -43,8 +54,9 @@ class FreshRSS_StatsDAOPGSQL extends FreshRSS_StatsDAO { if ($feed) { $restrict = "WHERE e.id_feed = {$feed}"; } + $offset = $this->getTimezoneOffset(); $sql = <<<SQL -SELECT extract( {$period} from to_timestamp(e.date)) AS period +SELECT extract( {$period} from to_timestamp(e.date + {$offset})) AS period , COUNT(1) AS count FROM `_entry` AS e {$restrict} diff --git a/app/Models/StatsDAOSQLite.php b/app/Models/StatsDAOSQLite.php index 4e51615fc..50b12d2c7 100644 --- a/app/Models/StatsDAOSQLite.php +++ b/app/Models/StatsDAOSQLite.php @@ -4,6 +4,17 @@ declare(strict_types=1); class FreshRSS_StatsDAOSQLite extends FreshRSS_StatsDAO { #[\Override] + protected function sqlDateToIsoGranularity(string $field, int $precision, string $granularity): string { + $offset = $this->getTimezoneOffset(); + return match ($granularity) { + 'day' => "strftime('%Y-%m-%d', ($field / $precision) + $offset, 'unixepoch')", + 'month' => "strftime('%Y-%m', ($field / $precision) + $offset, 'unixepoch')", + 'year' => "strftime('%Y', ($field / $precision) + $offset, 'unixepoch')", + default => throw new InvalidArgumentException('Invalid date granularity'), + }; + } + + #[\Override] protected function sqlFloor(string $s): string { return "CAST(($s) AS INT)"; } @@ -18,8 +29,9 @@ class FreshRSS_StatsDAOSQLite extends FreshRSS_StatsDAO { } else { $restrict = ''; } + $offset = $this->getTimezoneOffset(); $sql = <<<SQL -SELECT strftime('{$period}', e.date, 'unixepoch') AS period +SELECT strftime('{$period}', e.date + {$offset}, 'unixepoch') AS period , COUNT(1) AS count FROM `_entry` AS e {$restrict} diff --git a/app/Models/ViewStats.php b/app/Models/ViewStats.php index 89b7d8af4..22b2470f9 100644 --- a/app/Models/ViewStats.php +++ b/app/Models/ViewStats.php @@ -44,4 +44,7 @@ final class FreshRSS_ViewStats extends FreshRSS_View { public array $repartitionMonth; /** @var list<array{id:int,name:string,category:string,count:int}> */ public array $topFeed; + + /** @var list<array{granularity:string,unread_count:int}> */ + public array $unreadDates; } diff --git a/app/i18n/cs/admin.php b/app/i18n/cs/admin.php index 1621d55eb..6bf067a4c 100644 --- a/app/i18n/cs/admin.php +++ b/app/i18n/cs/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistika', 'all_feeds' => 'Všechny kanály', 'category' => 'Kategorie', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Počet položek', 'entry_per_category' => 'Položek na kategorii', 'entry_per_day' => 'Položek za den (posledních 30 dní)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Nečinné kanály', 'main' => 'Hlavní statistika', 'main_stream' => 'Všechny kanály', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Nejsou žádné nečinné kanály!', 'number_entries' => '%d článků', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Nepřečtené', 'title' => 'Statistika', 'top_feed' => 'Top 10 kanálů', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Nastavení systému', diff --git a/app/i18n/cs/sub.php b/app/i18n/cs/sub.php index 5f6e16a8e..cbf997322 100644 --- a/app/i18n/cs/sub.php +++ b/app/i18n/cs/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Nečinné kanály', 'main' => 'Hlavní statistika', 'repartition' => 'Přerozdělení článků', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Správa odběrů', 'subscription_tools' => 'Nástroje odběrů', diff --git a/app/i18n/de/admin.php b/app/i18n/de/admin.php index 7d398f034..a9ec4fd7f 100644 --- a/app/i18n/de/admin.php +++ b/app/i18n/de/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistiken', 'all_feeds' => 'Alle Feeds', 'category' => 'Kategorie', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Anzahl der Einträge', 'entry_per_category' => 'Einträge pro Kategorie', 'entry_per_day' => 'Einträge pro Tag (letzten 30 Tage)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Inaktive Feeds', 'main' => 'Haupt-Statistiken', 'main_stream' => 'Haupt-Feeds', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Es gibt keinen inaktiven Feed!', 'number_entries' => '%d Artikel', 'overview' => 'Übersicht', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Ungelesen', 'title' => 'Statistiken', 'top_feed' => 'Top 10-Feeds', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Systemeinstellungen', diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index d8ae79dc7..5fbfdae21 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Inaktive Feeds', 'main' => 'Haupt-Statistiken', 'repartition' => 'Artikel-Verteilung', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Abonnementverwaltung', 'subscription_tools' => 'Abonnement-Tools', diff --git a/app/i18n/el/admin.php b/app/i18n/el/admin.php index 19f81d756..a1e687b58 100644 --- a/app/i18n/el/admin.php +++ b/app/i18n/el/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Στατιστικά', 'all_feeds' => 'Όλες οι τροφοδοσίες', 'category' => 'Κατηγορία', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Αριθμός καταχωρίσεων', 'entry_per_category' => 'Καταχωρίσεις ανά κατηγορία', 'entry_per_day' => 'Καταχωρίσεις ανά ημέρα (τελευταίες 30 ημέρες)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Αδρανείς τροφοδοσίες', 'main' => 'Κύρια στατισικά', 'main_stream' => 'Κύρια ροή', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Δεν υπάρχουν αδρανείς τροφοδοσίες!', 'number_entries' => '%d άρθρα', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Μη αναγνωσμένα', 'title' => 'Στατιστικά', 'top_feed' => 'Κορυφαίες δέκα τροφοδοσίες', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Ρυθμίσεις συστήματος', diff --git a/app/i18n/el/sub.php b/app/i18n/el/sub.php index 27641d131..a9ba689e9 100644 --- a/app/i18n/el/sub.php +++ b/app/i18n/el/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Idle feeds', // TODO 'main' => 'Main statistics', // TODO 'repartition' => 'Articles repartition', // TODO + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Subscription management', // TODO 'subscription_tools' => 'Subscription tools', // TODO diff --git a/app/i18n/en-US/admin.php b/app/i18n/en-US/admin.php index 199edfe65..29185b462 100644 --- a/app/i18n/en-US/admin.php +++ b/app/i18n/en-US/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistics', // IGNORE 'all_feeds' => 'All feeds', // IGNORE 'category' => 'Category', // IGNORE + 'date_published' => 'Publication date', // IGNORE + 'date_received' => 'Received date', // IGNORE 'entry_count' => 'Entry count', // IGNORE 'entry_per_category' => 'Entries per category', // IGNORE 'entry_per_day' => 'Entries per day (last 30 days)', // IGNORE @@ -146,6 +148,7 @@ return array( 'idle' => 'Idle feeds', // IGNORE 'main' => 'Main statistics', // IGNORE 'main_stream' => 'Main stream', // IGNORE + 'nb_unreads' => 'Number of unread articles', // IGNORE 'no_idle' => 'There are no idle feeds!', // IGNORE 'number_entries' => '%d articles', // IGNORE 'overview' => 'Overview', // IGNORE @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Unread', // IGNORE 'title' => 'Statistics', // IGNORE 'top_feed' => 'Top ten feeds', // IGNORE + 'unread_dates' => 'Dates with most unread articles', // IGNORE ), 'system' => array( '_' => 'System configuration', // IGNORE diff --git a/app/i18n/en-US/sub.php b/app/i18n/en-US/sub.php index b3c4042ee..8f458095f 100644 --- a/app/i18n/en-US/sub.php +++ b/app/i18n/en-US/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Idle feeds', // IGNORE 'main' => 'Main statistics', // IGNORE 'repartition' => 'Articles repartition', // IGNORE + 'unread_dates' => 'Unread dates', // IGNORE ), 'subscription_management' => 'Subscription management', // IGNORE 'subscription_tools' => 'Subscription tools', // IGNORE diff --git a/app/i18n/en/admin.php b/app/i18n/en/admin.php index a138e555c..10f1c0c4b 100644 --- a/app/i18n/en/admin.php +++ b/app/i18n/en/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistics', 'all_feeds' => 'All feeds', 'category' => 'Category', + 'date_published' => 'Publication date', + 'date_received' => 'Received date', 'entry_count' => 'Entry count', 'entry_per_category' => 'Entries per category', 'entry_per_day' => 'Entries per day (last 30 days)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Idle feeds', 'main' => 'Main statistics', 'main_stream' => 'Main stream', + 'nb_unreads' => 'Number of unread articles', 'no_idle' => 'There are no idle feeds!', 'number_entries' => '%d articles', 'overview' => 'Overview', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Unread', 'title' => 'Statistics', 'top_feed' => 'Top ten feeds', + 'unread_dates' => 'Dates with most unread articles', ), 'system' => array( '_' => 'System configuration', diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index 006a9a190..ee3de4282 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Idle feeds', 'main' => 'Main statistics', 'repartition' => 'Articles repartition', + 'unread_dates' => 'Unread dates', ), 'subscription_management' => 'Subscription management', 'subscription_tools' => 'Subscription tools', diff --git a/app/i18n/es/admin.php b/app/i18n/es/admin.php index f61e3f914..aceba49e4 100644 --- a/app/i18n/es/admin.php +++ b/app/i18n/es/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Estadísticas', 'all_feeds' => 'Todas las fuentes', 'category' => 'Categoría', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Cómputo total', 'entry_per_category' => 'Entradas por categoría', 'entry_per_day' => 'Entradas por día (últimos 30 días)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Fuentes inactivas', 'main' => 'Estadísticas principales', 'main_stream' => 'Salida principal', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'No hay fuentes inactivas', 'number_entries' => '%d artículos', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Pendientes', 'title' => 'Estadísticas', 'top_feed' => 'Las 10 fuentes más activas', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Configuración del sistema', diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index f5addbd74..e5e09d0cc 100644 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Fuentes inactivas', 'main' => 'Estadísticas principales', 'repartition' => 'Reparto de artículos', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Administración de suscripciones', 'subscription_tools' => 'Herramientas de suscripción', diff --git a/app/i18n/fa/admin.php b/app/i18n/fa/admin.php index 9f71b5dd4..43e7e0827 100644 --- a/app/i18n/fa/admin.php +++ b/app/i18n/fa/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'آمار', 'all_feeds' => ' همه فیدها', 'category' => ' دسته', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => ' تعداد ورودی', 'entry_per_category' => ' ورودی در هر دسته', 'entry_per_day' => ' ورودی در روز (30 روز گذشته)', @@ -146,6 +148,7 @@ return array( 'idle' => ' تغذیه بیکار', 'main' => ' آمار اصلی', 'main_stream' => ' جریان اصلی', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => ' هیچ فید بیکار وجود ندارد!', 'number_entries' => ' %d مقاله', 'overview' => 'بررسی اجمالی', @@ -157,6 +160,7 @@ return array( 'status_unread' => ' خوانده نشده', 'title' => 'آمار', 'top_feed' => ' ده فید برتر', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => ' پیکربندی سیستم', diff --git a/app/i18n/fa/sub.php b/app/i18n/fa/sub.php index 48034f38c..239388557 100644 --- a/app/i18n/fa/sub.php +++ b/app/i18n/fa/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => ' تغذیه بیکار', 'main' => ' آمار اصلی', 'repartition' => ' تقسیم مجدد مقالات', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => ' مدیریت اشتراک', 'subscription_tools' => 'ابزارهای اشتراک', diff --git a/app/i18n/fi/admin.php b/app/i18n/fi/admin.php index ea4a0f48d..3f37d65e9 100644 --- a/app/i18n/fi/admin.php +++ b/app/i18n/fi/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Tilastot', 'all_feeds' => 'Kaikki syötteet', 'category' => 'Luokka', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Artikkelien määrä', 'entry_per_category' => 'Artikkelit luokan mukaan', 'entry_per_day' => 'Artikkelit päivän mukaan (edelliset 30 päivää)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Hiljentyneet syötteet', 'main' => 'Päätilastot', 'main_stream' => 'Pääsyötevirta', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Hiljentyneitä syötteitä ei ole.', 'number_entries' => '%d artikkelia', 'overview' => 'Katsaus', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Lukemattomat', 'title' => 'Tilastot', 'top_feed' => '10 parasta syötettä', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Järjestelmän määritys', diff --git a/app/i18n/fi/sub.php b/app/i18n/fi/sub.php index 9d1173df3..d23943aa8 100644 --- a/app/i18n/fi/sub.php +++ b/app/i18n/fi/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Hiljentyneet syötteet', 'main' => 'Tilastot', 'repartition' => 'Artikkelien uudelleenjaottelu', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Tilausten hallinta', 'subscription_tools' => 'Tilaustyökalut', diff --git a/app/i18n/fr/admin.php b/app/i18n/fr/admin.php index cb9e300f5..f2ae5b771 100644 --- a/app/i18n/fr/admin.php +++ b/app/i18n/fr/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistiques', 'all_feeds' => 'Tous les flux', 'category' => 'Catégorie', + 'date_published' => 'Date de publication', + 'date_received' => 'Date de réception', 'entry_count' => 'Nombre d’articles', 'entry_per_category' => 'Articles par catégorie', 'entry_per_day' => 'Nombre d’articles par jour (30 derniers jours)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Flux inactifs', 'main' => 'Statistiques principales', 'main_stream' => 'Flux principal', + 'nb_unreads' => 'Nombre d’articles non lus', 'no_idle' => 'Il n’y a aucun flux inactif !', 'number_entries' => '%d articles', // IGNORE 'overview' => 'Vue d’ensemble', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'non lus', 'title' => 'Statistiques', 'top_feed' => 'Les dix plus gros flux', + 'unread_dates' => 'Dates avec le plus d’articles non lus', ), 'system' => array( '_' => 'Configuration du système', diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index 9630cc8b6..9a0635b62 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Flux inactifs', 'main' => 'Statistiques principales', 'repartition' => 'Répartition des articles', + 'unread_dates' => 'Dates non lues', ), 'subscription_management' => 'Gestion des abonnements', 'subscription_tools' => 'Outils d’abonnement', diff --git a/app/i18n/he/admin.php b/app/i18n/he/admin.php index 26145e04a..3d8bb52b9 100644 --- a/app/i18n/he/admin.php +++ b/app/i18n/he/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'סטטיסטיקות', 'all_feeds' => 'כל ההזנות', 'category' => 'קטגוריה', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'סכום המאמרים', 'entry_per_category' => 'מאמרים על פי קטגוריה', 'entry_per_day' => 'מספר מאמרים ליום (30 ימים אחרונים)', @@ -146,6 +148,7 @@ return array( 'idle' => 'הזנות שלא עודכנו', 'main' => 'סטטיסטיקות ראשיות', 'main_stream' => 'הזנה ראשית', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'אין הזנות מובטלות!', 'number_entries' => '%d מאמרים', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'לא נקרא', 'title' => 'סטטיסטיקות', 'top_feed' => 'עשרת ההזנות המובילות', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'System configuration', // TODO diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index eb3e16f8a..ac45c07c8 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'הזנות שלא עודכנו', 'main' => 'סטטיסטיקות ראשיות', 'repartition' => 'חלוקת המאמרים', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'ניהול הרשמות', 'subscription_tools' => 'Subscription tools', // TODO diff --git a/app/i18n/hu/admin.php b/app/i18n/hu/admin.php index d9d1fa414..d8b00de2d 100644 --- a/app/i18n/hu/admin.php +++ b/app/i18n/hu/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statisztika', 'all_feeds' => 'Minden hírforrás', 'category' => 'Kategória', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Bejegyzések száma', 'entry_per_category' => 'Bejegyzések kategóriánként', 'entry_per_day' => 'Bejegyzések naponta (utolsó 30 nap)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Tétlen hírforrások', 'main' => 'Fő statisztika', 'main_stream' => 'Minden cikk', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Nincsenek tétlen hírforrások!', 'number_entries' => '%d cikk', 'overview' => 'Áttekintés', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Olvasatlan', 'title' => 'Statisztika', 'top_feed' => 'Top 10 hírforrás', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Rendszer konfiguráció', diff --git a/app/i18n/hu/sub.php b/app/i18n/hu/sub.php index ce8b195f7..4c9c60b72 100644 --- a/app/i18n/hu/sub.php +++ b/app/i18n/hu/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Tétlen hírforrások', 'main' => 'Fő statisztika', 'repartition' => 'Cikkek eloszlása', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Hírforrások kezelése', 'subscription_tools' => 'Hírforrás eszközök', diff --git a/app/i18n/id/admin.php b/app/i18n/id/admin.php index ff5961c72..806a4cafb 100644 --- a/app/i18n/id/admin.php +++ b/app/i18n/id/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistik', 'all_feeds' => 'Semua umpan', 'category' => 'Kategori', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Jumlah entri', 'entry_per_category' => 'Entri per kategori', 'entry_per_day' => 'Entri per hari (30 hari terakhir)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Umpan Tak Terbarukan', 'main' => 'Statistik utama', 'main_stream' => 'Bagian utama', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Tidak ada umpan tak terbarukan!', 'number_entries' => '%d artikel', 'overview' => 'Ringkasan', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Belum Terbaca', 'title' => 'Statistik', 'top_feed' => 'Sepuluh umpan teratas', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Konfigurasi Sistem', diff --git a/app/i18n/id/sub.php b/app/i18n/id/sub.php index a03b6bb59..f8578fb61 100644 --- a/app/i18n/id/sub.php +++ b/app/i18n/id/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Umpan tak terbarukan', 'main' => 'Statistik utama', 'repartition' => 'Pengkategorian artikel', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Pengelolaan langganan', 'subscription_tools' => 'Alat langganan', diff --git a/app/i18n/it/admin.php b/app/i18n/it/admin.php index 5c6a45cab..27891571c 100644 --- a/app/i18n/it/admin.php +++ b/app/i18n/it/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistiche', 'all_feeds' => 'Tutti i feeds', 'category' => 'Categoria', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Articoli', 'entry_per_category' => 'Articoli per categoria', 'entry_per_day' => 'Articoli per giorno (ultimi 30 giorni)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Feeds non aggiornati', 'main' => 'Statistiche principali', 'main_stream' => 'Flusso principale', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Non ci sono feed non aggiornati', 'number_entries' => '%d articoli', 'overview' => 'Panoramica', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Non letti', 'title' => 'Statistiche', 'top_feed' => 'I migliori 10 feeds', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Configurazione di sistema', diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index e0d4be072..ebeccb07d 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Feed non aggiornati', 'main' => 'Statistiche principali', 'repartition' => 'Ripartizione articoli', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Gestione sottoscrizioni', 'subscription_tools' => 'Strumenti di sottoscrizione', diff --git a/app/i18n/ja/admin.php b/app/i18n/ja/admin.php index 815b0c1d6..fc2e9f5e6 100644 --- a/app/i18n/ja/admin.php +++ b/app/i18n/ja/admin.php @@ -134,6 +134,8 @@ return array( '_' => '統計', 'all_feeds' => 'すべてのフィード', 'category' => 'カテゴリ', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'エントリの統計', 'entry_per_category' => 'カテゴリのエントリ', 'entry_per_day' => '日にちごとのエントリ (直近30日間)', @@ -146,6 +148,7 @@ return array( 'idle' => '休止中のフィード', 'main' => '主な統計', 'main_stream' => '主なストリーム', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => '休止中のフィードはありません!', 'number_entries' => '%d 記事', 'overview' => '概要', @@ -157,6 +160,7 @@ return array( 'status_unread' => '未読', 'title' => '統計', 'top_feed' => '上位10位のフィード', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'システム設定', diff --git a/app/i18n/ja/sub.php b/app/i18n/ja/sub.php index eafb9cbb6..d02117031 100644 --- a/app/i18n/ja/sub.php +++ b/app/i18n/ja/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => '休止中のフィード', 'main' => '主な統計', 'repartition' => '記事の割合', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => '購読フィードの管理', 'subscription_tools' => '購読ツール', diff --git a/app/i18n/ko/admin.php b/app/i18n/ko/admin.php index a47465ced..8f3f4cec2 100644 --- a/app/i18n/ko/admin.php +++ b/app/i18n/ko/admin.php @@ -134,6 +134,8 @@ return array( '_' => '통계', 'all_feeds' => '모든 피드', 'category' => '카테고리', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => '글 개수', 'entry_per_category' => '카테고리별 글 개수', 'entry_per_day' => '일일 글 개수 (최근 30 일)', @@ -146,6 +148,7 @@ return array( 'idle' => '유휴 피드', 'main' => '주요 통계', 'main_stream' => '메인 스트림', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => '유휴 피드가 없습니다!', 'number_entries' => '%d 개의 글', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => '읽지 않음', 'title' => '통계', 'top_feed' => '상위 10 개 피드', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => '시스템 설정', diff --git a/app/i18n/ko/sub.php b/app/i18n/ko/sub.php index 6e0234c38..8719e6f7b 100644 --- a/app/i18n/ko/sub.php +++ b/app/i18n/ko/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => '유휴 피드', 'main' => '주요 통계', 'repartition' => '글 분류', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => '구독 관리', 'subscription_tools' => '구독 도구', diff --git a/app/i18n/lv/admin.php b/app/i18n/lv/admin.php index 87acea3d3..87b32b875 100644 --- a/app/i18n/lv/admin.php +++ b/app/i18n/lv/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistika', 'all_feeds' => 'Visas barotnes', 'category' => 'Kategorija', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Ierakstu skaits', 'entry_per_category' => 'Ieraksti katrā kategorijā', 'entry_per_day' => 'Ieraksti dienā (pēdējās 30 dienas)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Neaktīvās barotnes', 'main' => 'Galvenās statistikas', 'main_stream' => 'Galvenā plūsma', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Nav neaktīvu barotņu!', 'number_entries' => '%d raksti', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Neizlasīti', 'title' => 'Statistika', 'top_feed' => 'Top 10 barotnes', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Sistēmas konfigurācija', diff --git a/app/i18n/lv/sub.php b/app/i18n/lv/sub.php index 4f0bee742..337d9418d 100644 --- a/app/i18n/lv/sub.php +++ b/app/i18n/lv/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Neaktīvās barotnes', 'main' => 'Galvenās statistikas', 'repartition' => 'Rakstu pārdalīšana', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Abonementu pārvalde', 'subscription_tools' => 'Abonamentu rīki', diff --git a/app/i18n/nl/admin.php b/app/i18n/nl/admin.php index 40c552a68..760391c7d 100644 --- a/app/i18n/nl/admin.php +++ b/app/i18n/nl/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statistieken', 'all_feeds' => 'Alle feeds', 'category' => 'Categorie', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Invoer aantallen', 'entry_per_category' => 'Aantallen per categorie', 'entry_per_day' => 'Aantallen per dag (laatste 30 dagen)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Gepauzeerde feeds', 'main' => 'Hoofd statistieken', 'main_stream' => 'Overzicht', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Er is geen gepauzeerde feed!', 'number_entries' => '%d artikelen', 'overview' => 'Overzicht', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Ongelezen', 'title' => 'Statistieken', 'top_feed' => 'Top tien feeds', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Systeem configuratie', diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index 17e8a1ad2..02aec863c 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Gepauzeerde feeds', 'main' => 'Hoofd statistieken', 'repartition' => 'Artikelen verdeling', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Abonnementenbeheer', 'subscription_tools' => 'Hulpmiddelen voor abonnementen', diff --git a/app/i18n/oc/admin.php b/app/i18n/oc/admin.php index 9b0f2aec7..430fe385e 100644 --- a/app/i18n/oc/admin.php +++ b/app/i18n/oc/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Estatisticas', 'all_feeds' => 'Totes los fluxes', 'category' => 'Categoria', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Nombre d’articles', 'entry_per_category' => 'Articles per categoria', 'entry_per_day' => 'Nombre d’articles per jorn (darrièrs 30 jorns)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Fluxes inactius', 'main' => 'Estatisticas principalas', 'main_stream' => 'Flux màger', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'I a pas cap d’article inactiu !', 'number_entries' => '%d articles', // IGNORE 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Pas legits', 'title' => 'Estatisticas', 'top_feed' => 'Los dètz fluxes mai gròsses', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Configuracion sistèma', diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index 108e3caed..678b32e1d 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Fluxes inactius', 'main' => 'Estatisticas principalas', 'repartition' => 'Reparticion dels articles', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Gestion dels abonaments', 'subscription_tools' => 'Aisinas d’abonament', diff --git a/app/i18n/pl/admin.php b/app/i18n/pl/admin.php index 2c4c74bbd..937988ab2 100644 --- a/app/i18n/pl/admin.php +++ b/app/i18n/pl/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Statystyki', 'all_feeds' => 'Wszystkie kanały', 'category' => 'Kategoria', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Liczba wiadomości', 'entry_per_category' => 'Wiadomości w podziale na kategorie', 'entry_per_day' => 'Wiadomości na dzień (przez ostatnie 30 dni)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Bezczynne kanały', 'main' => 'Główne statystyki', 'main_stream' => 'Kanał główny', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Brak bezczynnych kanałów!', 'number_entries' => '%d wiadomości', 'overview' => 'Podsumowanie', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Nieprzeczytane', 'title' => 'Statystyki', 'top_feed' => '10 największych kanałów', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Konfiguracja serwera', diff --git a/app/i18n/pl/sub.php b/app/i18n/pl/sub.php index 415bf67ac..ffc13822a 100644 --- a/app/i18n/pl/sub.php +++ b/app/i18n/pl/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Bezczynne kanały', 'main' => 'Główne statystyki', 'repartition' => 'Podział wiadomości', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Zarządzanie subskrypcjami', 'subscription_tools' => 'Narzędzia subskrypcji', diff --git a/app/i18n/pt-BR/admin.php b/app/i18n/pt-BR/admin.php index 6e2a53ae8..b6e0f5476 100644 --- a/app/i18n/pt-BR/admin.php +++ b/app/i18n/pt-BR/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Estatísticas', 'all_feeds' => 'Todos os feeds', 'category' => 'Categoria', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Contagem de entrada', 'entry_per_category' => 'Entradas por categoria', 'entry_per_day' => 'Entradas por dia (últimos 30 dias)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Feeds inativos', 'main' => 'Estatísticas principais', 'main_stream' => 'Stream principal', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Não há nenhum feed inativo!', 'number_entries' => '%d artigos', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Não lidos', 'title' => 'Estatísticas', 'top_feed' => 'Top10 Feeds', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Configuração do sistema', diff --git a/app/i18n/pt-BR/sub.php b/app/i18n/pt-BR/sub.php index 829b21660..06703a6a2 100644 --- a/app/i18n/pt-BR/sub.php +++ b/app/i18n/pt-BR/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Feeds inativos', 'main' => 'Estatísticas principais', 'repartition' => 'Repartição de artigos', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Gerenciamento de inscrições', 'subscription_tools' => 'Ferramentas de inscrição', diff --git a/app/i18n/pt-PT/admin.php b/app/i18n/pt-PT/admin.php index 1076ef573..d05403ceb 100644 --- a/app/i18n/pt-PT/admin.php +++ b/app/i18n/pt-PT/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Estatísticas', 'all_feeds' => 'Todos os feeds', 'category' => 'Categoria', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Contagem de entrada', 'entry_per_category' => 'Entradas por categoria', 'entry_per_day' => 'Entradas por dia (últimos 30 dias)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Feeds inativos', 'main' => 'Estatísticas principais', 'main_stream' => 'Stream principal', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Não há nenhum feed inativo!', 'number_entries' => '%d artigos', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Não lidos', 'title' => 'Estatísticas', 'top_feed' => 'Top10 Feeds', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Configuração do sistema', diff --git a/app/i18n/pt-PT/sub.php b/app/i18n/pt-PT/sub.php index dcedaeee8..72582fe25 100644 --- a/app/i18n/pt-PT/sub.php +++ b/app/i18n/pt-PT/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Feeds inativos', 'main' => 'Estatísticas principais', 'repartition' => 'Repartição de artigos', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Gerir de inscrições', 'subscription_tools' => 'Ferramentas de inscrição', diff --git a/app/i18n/ru/admin.php b/app/i18n/ru/admin.php index f8b8a9727..6a559f712 100644 --- a/app/i18n/ru/admin.php +++ b/app/i18n/ru/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Статистика', 'all_feeds' => 'Все подписки', 'category' => 'Категория', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Количество статей', 'entry_per_category' => 'Статей в категории', 'entry_per_day' => 'Статей за день (за последние 30 дней)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Неактивные ленты', 'main' => 'Основная статистика', 'main_stream' => 'Основной поток', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Нет неактивных лент!', 'number_entries' => 'статей: %d', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Не прочитано', 'title' => 'Статистика', 'top_feed' => '10 лучших лент', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Системные настройки', diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index e0ff935cd..174b80ce2 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Неактивные ленты', 'main' => 'Основная статистика', 'repartition' => 'Расределение статей', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Управление подписками', 'subscription_tools' => 'Инструменты подписки', diff --git a/app/i18n/sk/admin.php b/app/i18n/sk/admin.php index 2c48fd068..ec861eca9 100644 --- a/app/i18n/sk/admin.php +++ b/app/i18n/sk/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Štatistiky', 'all_feeds' => 'Všetky kanály', 'category' => 'Kategória', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Počet položiek', 'entry_per_category' => 'Položiek v kategórii', 'entry_per_day' => 'Položiek za deň (posledných 30 dní)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Neaktívne kanály', 'main' => 'Hlavné štatistiky', 'main_stream' => 'Všetky kanály', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Žiadne neaktívne kanály!', 'number_entries' => 'Počet článkov: %d', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Neprečítané', 'title' => 'Štatistiky', 'top_feed' => 'Top 10 kanálov', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Nastavenia systému', diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php index 25db456eb..a8026ee0f 100644 --- a/app/i18n/sk/sub.php +++ b/app/i18n/sk/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Neaktívne kanály', 'main' => 'Hlavné štatistiky', 'repartition' => 'Rozdelenie článkov', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Správa odoberaných kanálov', 'subscription_tools' => 'Nástroje na odoberanie kanálov', diff --git a/app/i18n/tr/admin.php b/app/i18n/tr/admin.php index 0b713e2df..df6ef2c4f 100644 --- a/app/i18n/tr/admin.php +++ b/app/i18n/tr/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'İstatistikler', 'all_feeds' => 'Tüm beslemeler', 'category' => 'Kategori', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Giriş sayısı', 'entry_per_category' => 'Kategorilere göre girişler', 'entry_per_day' => 'Günlük girişler (son 30 gün)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Boşta beslemeler', 'main' => 'Ana istatistikler', 'main_stream' => 'Ana akış', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Boşta besleme yok!', 'number_entries' => '%d makale', 'overview' => 'Genel Bakış', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Okunmadı', 'title' => 'İstatistikler', 'top_feed' => 'En iyi on besleme', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Sistem yapılandırması', diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index b44c8df00..62a0c43f4 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Boşta olan beslemeler', 'main' => 'Ana istatistikler', 'repartition' => 'Makale dağılımı', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Abonelik yönetimi', 'subscription_tools' => 'Abonelik araçları', diff --git a/app/i18n/uk/admin.php b/app/i18n/uk/admin.php index 71c2cdd2b..7126d901c 100644 --- a/app/i18n/uk/admin.php +++ b/app/i18n/uk/admin.php @@ -134,6 +134,8 @@ return array( '_' => 'Статистика', 'all_feeds' => 'Всі стрічки', 'category' => 'Категорія', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => 'Кількість статей', 'entry_per_category' => 'Статей у категорії', 'entry_per_day' => 'Статей за день (минулі 30 днів)', @@ -146,6 +148,7 @@ return array( 'idle' => 'Неактивні стрічки', 'main' => 'Основна статистика', 'main_stream' => 'Головний потік', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => 'Неактивних стрічок нема!', 'number_entries' => 'Статей: %d', 'overview' => 'Огляд', @@ -157,6 +160,7 @@ return array( 'status_unread' => 'Непрочитано', 'title' => 'Статистика', 'top_feed' => 'Десять найактивніших стрічок', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => 'Налаштування системи', diff --git a/app/i18n/uk/sub.php b/app/i18n/uk/sub.php index e7d2769d0..547593a92 100644 --- a/app/i18n/uk/sub.php +++ b/app/i18n/uk/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => 'Неактивні стрічки', 'main' => 'Основна статистика', 'repartition' => 'Перерозподіл статей', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => 'Керування підписками', 'subscription_tools' => 'Засоби підписки', diff --git a/app/i18n/zh-CN/admin.php b/app/i18n/zh-CN/admin.php index 8bf7d5fed..d1e3a3b4f 100644 --- a/app/i18n/zh-CN/admin.php +++ b/app/i18n/zh-CN/admin.php @@ -134,6 +134,8 @@ return array( '_' => '统计数据', 'all_feeds' => '所有订阅源', 'category' => '分类', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => '文章数', 'entry_per_category' => '各分类文章数', 'entry_per_day' => '每日文章数(近三十日)', @@ -146,6 +148,7 @@ return array( 'idle' => '长期无更新订阅源', 'main' => '主要统计数据', 'main_stream' => '首页', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => '订阅源近期皆有更新!', 'number_entries' => '%d 篇文章', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => '未读', 'title' => '统计', 'top_feed' => '前十订阅源', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => '系统配置', diff --git a/app/i18n/zh-CN/sub.php b/app/i18n/zh-CN/sub.php index 4769893d5..65b633107 100644 --- a/app/i18n/zh-CN/sub.php +++ b/app/i18n/zh-CN/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => '长期无更新订阅源', 'main' => '主要统计', 'repartition' => '文章分布', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => '订阅管理', 'subscription_tools' => '订阅工具', diff --git a/app/i18n/zh-TW/admin.php b/app/i18n/zh-TW/admin.php index e19660e39..88ad2f0eb 100644 --- a/app/i18n/zh-TW/admin.php +++ b/app/i18n/zh-TW/admin.php @@ -134,6 +134,8 @@ return array( '_' => '統計', 'all_feeds' => '所有訂閱源', 'category' => '分類', + 'date_published' => 'Publication date', // TODO + 'date_received' => 'Received date', // TODO 'entry_count' => '文章數', 'entry_per_category' => '各分類文章數', 'entry_per_day' => '近三十日每日文章數', @@ -146,6 +148,7 @@ return array( 'idle' => '長期無更新訂閱源', 'main' => '主要統計', 'main_stream' => '首頁', + 'nb_unreads' => 'Number of unread articles', // TODO 'no_idle' => '訂閱源近期皆有更新!', 'number_entries' => '%d 篇文章', 'overview' => 'Overview', // TODO @@ -157,6 +160,7 @@ return array( 'status_unread' => '未讀', 'title' => '統計', 'top_feed' => '前十訂閱源', + 'unread_dates' => 'Dates with most unread articles', // TODO ), 'system' => array( '_' => '系統配置', diff --git a/app/i18n/zh-TW/sub.php b/app/i18n/zh-TW/sub.php index 836de4795..06ef379f2 100644 --- a/app/i18n/zh-TW/sub.php +++ b/app/i18n/zh-TW/sub.php @@ -282,6 +282,7 @@ return array( 'idle' => '長期無更新訂閱源', 'main' => '主要統計', 'repartition' => '文章分布', + 'unread_dates' => 'Unread dates', // TODO ), 'subscription_management' => '訂閱管理', 'subscription_tools' => '訂閱工具', diff --git a/app/layout/aside_subscription.phtml b/app/layout/aside_subscription.phtml index ce17eaa26..be414ff03 100644 --- a/app/layout/aside_subscription.phtml +++ b/app/layout/aside_subscription.phtml @@ -39,20 +39,23 @@ <li class="item nav-section"> <div class="nav-header"><?= _t('admin.stats') ?></div> <ul> - <li class="item<?= Minz_Request::controllerName() == 'stats' && Minz_Request::actionName() == 'index' ? ' active' : '' ?>"> + <li class="item<?= Minz_Request::controllerName() === 'stats' && Minz_Request::actionName() === 'index' ? ' active' : '' ?>"> <a href="<?= _url('stats', 'index') ?>"><?= _t('sub.menu.stats.main') ?></a> </li> - <li class="item<?= Minz_Request::actionName() == 'idle' ? ' active' : '' ?>"> + <li class="item<?= Minz_Request::actionName() === 'idle' ? ' active' : '' ?>"> <a href="<?= _url('stats', 'idle') ?>"><?= _t('sub.menu.stats.idle') ?></a> </li> - <li class="item<?= Minz_Request::actionName() == 'repartition' ? ' active' : '' ?>"> + <li class="item<?= Minz_Request::actionName() === 'repartition' ? ' active' : '' ?>"> <a href="<?= _url('stats', 'repartition') ?>"><?= _t('sub.menu.stats.repartition') ?></a> </li> + <li class="item<?= Minz_Request::actionName() === 'unreadDates' ? ' active' : '' ?>"> + <a href="<?= _url('stats', 'unreadDates') ?>"><?= _t('sub.menu.stats.unread_dates') ?></a> + </li> </ul> </li> </ul> </nav> -<?php if (Minz_Request::actionName() != 'repartition') { ?> +<?php if (Minz_Request::actionName() !== 'repartition') { ?> <a class="close-aside" href="#close">❌</a> <nav class="nav_menu nav_mobile"> <a class="btn toggle_aside" href="#aside_feed"><?= _i('category') ?></a> diff --git a/app/views/stats/unreadDates.phtml b/app/views/stats/unreadDates.phtml new file mode 100644 index 000000000..6ef258a61 --- /dev/null +++ b/app/views/stats/unreadDates.phtml @@ -0,0 +1,48 @@ +<?php + declare(strict_types=1); + /** @var FreshRSS_ViewStats $this */ + $this->partial('aside_subscription'); +?> +<main class="post"> + <h1><?= _t('admin.stats.unread_dates') ?></h1> + <form> + <input type="hidden" name="c" value="stats" /> + <input type="hidden" name="a" value="unreadDates" /> + <select name="field" id="field"> + <option value="id" <?= Minz_Request::paramString('field') === 'id' ? 'selected="selected"' : '' ?>><?= _t('admin.stats.date_received') ?></option> + <option value="date" <?= Minz_Request::paramString('field') === 'date' ? 'selected="selected"' : '' ?>><?= _t('admin.stats.date_published') ?></option> + </select> + <input type="number" name="max" id="max" value="<?= Minz_Request::paramInt('max') ?: 100 ?>" min="1" /> + <select name="granularity" id="granularity"> + <option value="day" <?= Minz_Request::paramString('granularity') === 'day' ? 'selected="selected"' : '' ?>><?= _t('gen.period.days') ?></option> + <option value="month" <?= Minz_Request::paramString('granularity') === 'month' ? 'selected="selected"' : '' ?>><?= _t('gen.period.months') ?></option> + <option value="year" <?= Minz_Request::paramString('granularity') === 'year' ? 'selected="selected"' : '' ?>><?= _t('gen.period.years') ?></option> + </select> + <button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button> + </form> + <table> + <thead> + <tr> + <th> + <?php if (Minz_Request::paramString('field') === 'date'): ?> + <?= _t('admin.stats.date_published') ?> + <?php else: ?> + <?= _t('admin.stats.date_received') ?> + <?php endif; ?> + </th> + <th><?= _t('admin.stats.nb_unreads') ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($this->unreadDates as $row): ?> + <tr><?php /* TODO: Make that URL show all articles, including those with PRIORITY_ARCHIVED */ ?> + <td><a href="<?= _url('index', 'index', 'search', + (Minz_Request::paramString('field') === 'date' ? 'pubdate:' : 'date:') . $row['granularity']) ?>"> + <?= htmlspecialchars($row['granularity'], ENT_NOQUOTES, 'UTF-8') ?> + </a></td> + <td><?= format_number($row['unread_count']) ?></td> + </tr> + <?php endforeach; ?> + </tbody> + </table> +</main> |
