Bläddra i källkod

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" />
Alexandre Alapetite 5 månader sedan
förälder
incheckning
5eba322cbd
63 ändrade filer med 299 tillägg och 25 borttagningar
  1. 9 9
      README.fr.md
  2. 9 9
      README.md
  3. 14 0
      app/Controllers/statsController.php
  4. 48 1
      app/Models/StatsDAO.php
  5. 13 1
      app/Models/StatsDAOPGSQL.php
  6. 13 1
      app/Models/StatsDAOSQLite.php
  7. 3 0
      app/Models/ViewStats.php
  8. 4 0
      app/i18n/cs/admin.php
  9. 1 0
      app/i18n/cs/sub.php
  10. 4 0
      app/i18n/de/admin.php
  11. 1 0
      app/i18n/de/sub.php
  12. 4 0
      app/i18n/el/admin.php
  13. 1 0
      app/i18n/el/sub.php
  14. 4 0
      app/i18n/en-US/admin.php
  15. 1 0
      app/i18n/en-US/sub.php
  16. 4 0
      app/i18n/en/admin.php
  17. 1 0
      app/i18n/en/sub.php
  18. 4 0
      app/i18n/es/admin.php
  19. 1 0
      app/i18n/es/sub.php
  20. 4 0
      app/i18n/fa/admin.php
  21. 1 0
      app/i18n/fa/sub.php
  22. 4 0
      app/i18n/fi/admin.php
  23. 1 0
      app/i18n/fi/sub.php
  24. 4 0
      app/i18n/fr/admin.php
  25. 1 0
      app/i18n/fr/sub.php
  26. 4 0
      app/i18n/he/admin.php
  27. 1 0
      app/i18n/he/sub.php
  28. 4 0
      app/i18n/hu/admin.php
  29. 1 0
      app/i18n/hu/sub.php
  30. 4 0
      app/i18n/id/admin.php
  31. 1 0
      app/i18n/id/sub.php
  32. 4 0
      app/i18n/it/admin.php
  33. 1 0
      app/i18n/it/sub.php
  34. 4 0
      app/i18n/ja/admin.php
  35. 1 0
      app/i18n/ja/sub.php
  36. 4 0
      app/i18n/ko/admin.php
  37. 1 0
      app/i18n/ko/sub.php
  38. 4 0
      app/i18n/lv/admin.php
  39. 1 0
      app/i18n/lv/sub.php
  40. 4 0
      app/i18n/nl/admin.php
  41. 1 0
      app/i18n/nl/sub.php
  42. 4 0
      app/i18n/oc/admin.php
  43. 1 0
      app/i18n/oc/sub.php
  44. 4 0
      app/i18n/pl/admin.php
  45. 1 0
      app/i18n/pl/sub.php
  46. 4 0
      app/i18n/pt-BR/admin.php
  47. 1 0
      app/i18n/pt-BR/sub.php
  48. 4 0
      app/i18n/pt-PT/admin.php
  49. 1 0
      app/i18n/pt-PT/sub.php
  50. 4 0
      app/i18n/ru/admin.php
  51. 1 0
      app/i18n/ru/sub.php
  52. 4 0
      app/i18n/sk/admin.php
  53. 1 0
      app/i18n/sk/sub.php
  54. 4 0
      app/i18n/tr/admin.php
  55. 1 0
      app/i18n/tr/sub.php
  56. 4 0
      app/i18n/uk/admin.php
  57. 1 0
      app/i18n/uk/sub.php
  58. 4 0
      app/i18n/zh-CN/admin.php
  59. 1 0
      app/i18n/zh-CN/sub.php
  60. 4 0
      app/i18n/zh-TW/admin.php
  61. 1 0
      app/i18n/zh-TW/sub.php
  62. 7 4
      app/layout/aside_subscription.phtml
  63. 48 0
      app/views/stats/unreadDates.phtml

+ 9 - 9
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>

+ 9 - 9
README.md

@@ -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>

+ 14 - 0
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;
+	}
 }

+ 48 - 1
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 : [];
+	}
 }

+ 13 - 1
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}

+ 13 - 1
app/Models/StatsDAOSQLite.php

@@ -3,6 +3,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}

+ 3 - 0
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;
 }

+ 4 - 0
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',

+ 1 - 0
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ů',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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(
 		'_' => 'Ρυθμίσεις συστήματος',

+ 1 - 0
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

+ 4 - 0
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

+ 1 - 0
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

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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(
 		'_' => ' پیکربندی سیستم',

+ 1 - 0
app/i18n/fa/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => ' تغذیه بیکار',
 			'main' => ' آمار اصلی',
 			'repartition' => ' تقسیم مجدد مقالات',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => ' مدیریت اشتراک',
 		'subscription_tools' => 'ابزارهای اشتراک',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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

+ 1 - 0
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

+ 4 - 0
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ó',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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(
 		'_' => 'システム設定',

+ 1 - 0
app/i18n/ja/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => '休止中のフィード',
 			'main' => '主な統計',
 			'repartition' => '記事の割合',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => '購読フィードの管理',
 		'subscription_tools' => '購読ツール',

+ 4 - 0
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(
 		'_' => '시스템 설정',

+ 1 - 0
app/i18n/ko/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => '유휴 피드',
 			'main' => '주요 통계',
 			'repartition' => '글 분류',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => '구독 관리',
 		'subscription_tools' => '구독 도구',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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(
 		'_' => 'Системные настройки',

+ 1 - 0
app/i18n/ru/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => 'Неактивные ленты',
 			'main' => 'Основная статистика',
 			'repartition' => 'Расределение статей',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => 'Управление подписками',
 		'subscription_tools' => 'Инструменты подписки',

+ 4 - 0
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',

+ 1 - 0
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',

+ 4 - 0
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ı',

+ 1 - 0
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ı',

+ 4 - 0
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(
 		'_' => 'Налаштування системи',

+ 1 - 0
app/i18n/uk/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => 'Неактивні стрічки',
 			'main' => 'Основна статистика',
 			'repartition' => 'Перерозподіл статей',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => 'Керування підписками',
 		'subscription_tools' => 'Засоби підписки',

+ 4 - 0
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(
 		'_' => '系统配置',

+ 1 - 0
app/i18n/zh-CN/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => '长期无更新订阅源',
 			'main' => '主要统计',
 			'repartition' => '文章分布',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => '订阅管理',
 		'subscription_tools' => '订阅工具',

+ 4 - 0
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(
 		'_' => '系統配置',

+ 1 - 0
app/i18n/zh-TW/sub.php

@@ -282,6 +282,7 @@ return array(
 			'idle' => '長期無更新訂閱源',
 			'main' => '主要統計',
 			'repartition' => '文章分布',
+			'unread_dates' => 'Unread dates',	// TODO
 		),
 		'subscription_management' => '訂閱管理',
 		'subscription_tools' => '訂閱工具',

+ 7 - 4
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>

+ 48 - 0
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>