Parcourir la source

Add privacy settings on extension list retrieval (#4603)

* Add privacy settings on extension list retrieval

There is a new privacy page to handle all configuration related to privacy. At
the moment, only privacy related to extensions can be configured.

The new settings allow to change the location of the extension list file and to
choose if the selected file is cached for a day or retrieved for each request.

Fix #4570

* Update code to pass PHPStan

* make fix-all

---------

Co-authored-by: maTh <math-home@web.de>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Alexis Degrugillier il y a 1 an
Parent
commit
ad2c6e6fbf
80 fichiers modifiés avec 212 ajouts et 1 suppressions
  1. 16 0
      app/Controllers/configureController.php
  2. 12 1
      app/Controllers/extensionController.php
  3. 1 0
      app/Models/UserConfiguration.php
  4. 1 0
      app/i18n/cs/admin.php
  5. 4 0
      app/i18n/cs/conf.php
  6. 1 0
      app/i18n/cs/gen.php
  7. 1 0
      app/i18n/de/admin.php
  8. 4 0
      app/i18n/de/conf.php
  9. 1 0
      app/i18n/de/gen.php
  10. 1 0
      app/i18n/el/admin.php
  11. 4 0
      app/i18n/el/conf.php
  12. 1 0
      app/i18n/el/gen.php
  13. 1 0
      app/i18n/en-us/admin.php
  14. 4 0
      app/i18n/en-us/conf.php
  15. 1 0
      app/i18n/en-us/gen.php
  16. 1 0
      app/i18n/en/admin.php
  17. 4 0
      app/i18n/en/conf.php
  18. 1 0
      app/i18n/en/gen.php
  19. 1 0
      app/i18n/es/admin.php
  20. 4 0
      app/i18n/es/conf.php
  21. 1 0
      app/i18n/es/gen.php
  22. 1 0
      app/i18n/fa/admin.php
  23. 4 0
      app/i18n/fa/conf.php
  24. 1 0
      app/i18n/fa/gen.php
  25. 1 0
      app/i18n/fr/admin.php
  26. 4 0
      app/i18n/fr/conf.php
  27. 1 0
      app/i18n/fr/gen.php
  28. 1 0
      app/i18n/he/admin.php
  29. 4 0
      app/i18n/he/conf.php
  30. 1 0
      app/i18n/he/gen.php
  31. 1 0
      app/i18n/hu/admin.php
  32. 4 0
      app/i18n/hu/conf.php
  33. 1 0
      app/i18n/hu/gen.php
  34. 1 0
      app/i18n/id/admin.php
  35. 4 0
      app/i18n/id/conf.php
  36. 1 0
      app/i18n/id/gen.php
  37. 1 0
      app/i18n/it/admin.php
  38. 4 0
      app/i18n/it/conf.php
  39. 1 0
      app/i18n/it/gen.php
  40. 1 0
      app/i18n/ja/admin.php
  41. 4 0
      app/i18n/ja/conf.php
  42. 1 0
      app/i18n/ja/gen.php
  43. 1 0
      app/i18n/ko/admin.php
  44. 4 0
      app/i18n/ko/conf.php
  45. 1 0
      app/i18n/ko/gen.php
  46. 1 0
      app/i18n/lv/admin.php
  47. 4 0
      app/i18n/lv/conf.php
  48. 1 0
      app/i18n/lv/gen.php
  49. 1 0
      app/i18n/nl/admin.php
  50. 4 0
      app/i18n/nl/conf.php
  51. 1 0
      app/i18n/nl/gen.php
  52. 1 0
      app/i18n/oc/admin.php
  53. 4 0
      app/i18n/oc/conf.php
  54. 1 0
      app/i18n/oc/gen.php
  55. 1 0
      app/i18n/pl/admin.php
  56. 4 0
      app/i18n/pl/conf.php
  57. 1 0
      app/i18n/pl/gen.php
  58. 1 0
      app/i18n/pt-br/admin.php
  59. 4 0
      app/i18n/pt-br/conf.php
  60. 1 0
      app/i18n/pt-br/gen.php
  61. 1 0
      app/i18n/ru/admin.php
  62. 4 0
      app/i18n/ru/conf.php
  63. 1 0
      app/i18n/ru/gen.php
  64. 1 0
      app/i18n/sk/admin.php
  65. 4 0
      app/i18n/sk/conf.php
  66. 1 0
      app/i18n/sk/gen.php
  67. 1 0
      app/i18n/tr/admin.php
  68. 4 0
      app/i18n/tr/conf.php
  69. 1 0
      app/i18n/tr/gen.php
  70. 1 0
      app/i18n/zh-cn/admin.php
  71. 4 0
      app/i18n/zh-cn/conf.php
  72. 1 0
      app/i18n/zh-cn/gen.php
  73. 1 0
      app/i18n/zh-tw/admin.php
  74. 4 0
      app/i18n/zh-tw/conf.php
  75. 1 0
      app/i18n/zh-tw/gen.php
  76. 3 0
      app/layout/aside_configure.phtml
  77. 1 0
      app/layout/header.phtml
  78. 32 0
      app/views/configure/privacy.phtml
  79. 2 0
      app/views/extension/index.phtml
  80. 1 0
      config-user.default.php

+ 16 - 0
app/Controllers/configureController.php

@@ -503,4 +503,20 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
 			Minz_Request::good(_t('feedback.conf.updated'), [ 'c' => 'configure', 'a' => 'system' ]);
 			Minz_Request::good(_t('feedback.conf.updated'), [ 'c' => 'configure', 'a' => 'system' ]);
 		}
 		}
 	}
 	}
+
+	public function privacyAction(): void {
+		if (!FreshRSS_Auth::hasAccess('admin')) {
+			Minz_Error::error(403);
+		}
+
+		if (Minz_Request::isPost()) {
+			FreshRSS_Context::userConf()->retrieve_extension_list = Minz_Request::paramBoolean('retrieve_extension_list');
+			FreshRSS_Context::userConf()->save();
+			invalidateHttpCache();
+
+			Minz_Request::good(_t('feedback.conf.updated'), array('c' => 'configure', 'a' => 'privacy'));
+		}
+
+		FreshRSS_View::prependTitle(_t('conf.privacy') . ' · ');
+	}
 }
 }

+ 12 - 1
app/Controllers/extensionController.php

@@ -44,7 +44,18 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
 	 */
 	 */
 	protected function getAvailableExtensionList(): array {
 	protected function getAvailableExtensionList(): array {
 		$extensionListUrl = 'https://raw.githubusercontent.com/FreshRSS/Extensions/master/extensions.json';
 		$extensionListUrl = 'https://raw.githubusercontent.com/FreshRSS/Extensions/master/extensions.json';
-		$json = httpGet($extensionListUrl, CACHE_PATH . '/extension_list.json', 'json');
+
+		$cacheFile = CACHE_PATH . '/extension_list.json';
+		if (FreshRSS_Context::userConf()->retrieve_extension_list === true) {
+			if (!file_exists($cacheFile) || (time() - (filemtime($cacheFile) ?: 0) > 86400)) {
+				$json = httpGet($extensionListUrl, $cacheFile, 'json');
+			} else {
+				$json = @file_get_contents($cacheFile) ?: '';
+			}
+		} else {
+			Minz_Log::warning('The extension list retrieval is disabled in privacy configuration');
+			return [];
+		}
 
 
 		// we ran into problems, simply ignore them
 		// we ran into problems, simply ignore them
 		if ($json === '') {
 		if ($json === '') {

+ 1 - 0
app/Models/UserConfiguration.php

@@ -73,6 +73,7 @@ declare(strict_types=1);
  * @property string $view_mode
  * @property string $view_mode
  * @property array<string,bool|int|string> $volatile
  * @property array<string,bool|int|string> $volatile
  * @property array<string,array<string,mixed>> $extensions
  * @property array<string,array<string,mixed>> $extensions
+ * @property bool $retrieve_extension_list
  */
  */
 final class FreshRSS_UserConfiguration extends Minz_Configuration {
 final class FreshRSS_UserConfiguration extends Minz_Configuration {
 	use FreshRSS_FilterActionsTrait;
 	use FreshRSS_FilterActionsTrait;

+ 1 - 0
app/i18n/cs/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Popis',
 		'description' => 'Popis',
 		'disabled' => 'Zakázáno',
 		'disabled' => 'Zakázáno',
 		'empty_list' => 'Nejsou naistalována žádná rozšíření',
 		'empty_list' => 'Nejsou naistalována žádná rozšíření',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Povoleno',
 		'enabled' => 'Povoleno',
 		'latest' => 'Nainstalováno',
 		'latest' => 'Nainstalováno',
 		'name' => 'Název',
 		'name' => 'Název',

+ 4 - 0
app/i18n/cs/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Předchozí',
 			'previous' => 'Předchozí',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Správa profilu',
 		'_' => 'Správa profilu',
 		'api' => 'Správa API',
 		'api' => 'Správa API',

+ 1 - 0
app/i18n/cs/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Zobrazení',
 		'display' => 'Zobrazení',
 		'extensions' => 'Rozšíření',
 		'extensions' => 'Rozšíření',
 		'logs' => 'Protokoly',
 		'logs' => 'Protokoly',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Uživatelské dotazy',
 		'queries' => 'Uživatelské dotazy',
 		'reading' => 'Čtení',
 		'reading' => 'Čtení',
 		'search' => 'Hledat slova nebo #štítky',
 		'search' => 'Hledat slova nebo #štítky',

+ 1 - 0
app/i18n/de/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Beschreibungen',
 		'description' => 'Beschreibungen',
 		'disabled' => 'Deaktiviert',
 		'disabled' => 'Deaktiviert',
 		'empty_list' => 'Es gibt keine installierte Erweiterung.',
 		'empty_list' => 'Es gibt keine installierte Erweiterung.',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Aktiviert',
 		'enabled' => 'Aktiviert',
 		'latest' => 'Installiert',
 		'latest' => 'Installiert',
 		'name' => 'Name',	// IGNORE
 		'name' => 'Name',	// IGNORE

+ 4 - 0
app/i18n/de/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Vorherige',
 			'previous' => 'Vorherige',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profil-Verwaltung',
 		'_' => 'Profil-Verwaltung',
 		'api' => 'API-Verwaltung',
 		'api' => 'API-Verwaltung',

+ 1 - 0
app/i18n/de/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Anzeige',
 		'display' => 'Anzeige',
 		'extensions' => 'Erweiterungen',
 		'extensions' => 'Erweiterungen',
 		'logs' => 'Protokolle',
 		'logs' => 'Protokolle',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Benutzerabfragen',
 		'queries' => 'Benutzerabfragen',
 		'reading' => 'Lesen',
 		'reading' => 'Lesen',
 		'search' => 'Suche Worte oder #Tags',
 		'search' => 'Suche Worte oder #Tags',

+ 1 - 0
app/i18n/el/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Περιγραφή',
 		'description' => 'Περιγραφή',
 		'disabled' => 'Απενεργοποιημένες',
 		'disabled' => 'Απενεργοποιημένες',
 		'empty_list' => 'Δεν υπάρχουν εγκατεστημένες επεκτάσεις',
 		'empty_list' => 'Δεν υπάρχουν εγκατεστημένες επεκτάσεις',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Ενεργοποιημένες',
 		'enabled' => 'Ενεργοποιημένες',
 		'latest' => 'Εγκατεστημένες',
 		'latest' => 'Εγκατεστημένες',
 		'name' => 'Όνομα',
 		'name' => 'Όνομα',

+ 4 - 0
app/i18n/el/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Previous',	// TODO
 			'previous' => 'Previous',	// TODO
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profile management',	// TODO
 		'_' => 'Profile management',	// TODO
 		'api' => 'API management',	// TODO
 		'api' => 'API management',	// TODO

+ 1 - 0
app/i18n/el/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Display',	// TODO
 		'display' => 'Display',	// TODO
 		'extensions' => 'Extensions',	// TODO
 		'extensions' => 'Extensions',	// TODO
 		'logs' => 'Logs',	// TODO
 		'logs' => 'Logs',	// TODO
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'User queries',	// TODO
 		'queries' => 'User queries',	// TODO
 		'reading' => 'Reading',	// TODO
 		'reading' => 'Reading',	// TODO
 		'search' => 'Search words or #tags',	// TODO
 		'search' => 'Search words or #tags',	// TODO

+ 1 - 0
app/i18n/en-us/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Description',	// IGNORE
 		'description' => 'Description',	// IGNORE
 		'disabled' => 'Disabled',	// IGNORE
 		'disabled' => 'Disabled',	// IGNORE
 		'empty_list' => 'There are no installed extensions',	// IGNORE
 		'empty_list' => 'There are no installed extensions',	// IGNORE
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Enabled',	// IGNORE
 		'enabled' => 'Enabled',	// IGNORE
 		'latest' => 'Installed',	// IGNORE
 		'latest' => 'Installed',	// IGNORE
 		'name' => 'Name',	// IGNORE
 		'name' => 'Name',	// IGNORE

+ 4 - 0
app/i18n/en-us/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Previous',	// IGNORE
 			'previous' => 'Previous',	// IGNORE
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profile management',	// IGNORE
 		'_' => 'Profile management',	// IGNORE
 		'api' => 'API management',	// IGNORE
 		'api' => 'API management',	// IGNORE

+ 1 - 0
app/i18n/en-us/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Display',	// IGNORE
 		'display' => 'Display',	// IGNORE
 		'extensions' => 'Extensions',	// IGNORE
 		'extensions' => 'Extensions',	// IGNORE
 		'logs' => 'Logs',	// IGNORE
 		'logs' => 'Logs',	// IGNORE
+		'privacy' => 'Privacy',	// IGNORE
 		'queries' => 'User queries',	// IGNORE
 		'queries' => 'User queries',	// IGNORE
 		'reading' => 'Reading',	// IGNORE
 		'reading' => 'Reading',	// IGNORE
 		'search' => 'Search words or #tags',	// IGNORE
 		'search' => 'Search words or #tags',	// IGNORE

+ 1 - 0
app/i18n/en/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Description',
 		'description' => 'Description',
 		'disabled' => 'Disabled',
 		'disabled' => 'Disabled',
 		'empty_list' => 'There are no installed extensions',
 		'empty_list' => 'There are no installed extensions',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Enabled',
 		'enabled' => 'Enabled',
 		'latest' => 'Installed',
 		'latest' => 'Installed',
 		'name' => 'Name',
 		'name' => 'Name',

+ 4 - 0
app/i18n/en/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Previous',
 			'previous' => 'Previous',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profile management',
 		'_' => 'Profile management',
 		'api' => 'API management',
 		'api' => 'API management',

+ 1 - 0
app/i18n/en/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Display',
 		'display' => 'Display',
 		'extensions' => 'Extensions',
 		'extensions' => 'Extensions',
 		'logs' => 'Logs',
 		'logs' => 'Logs',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'User queries',
 		'queries' => 'User queries',
 		'reading' => 'Reading',
 		'reading' => 'Reading',
 		'search' => 'Search words or #tags',
 		'search' => 'Search words or #tags',

+ 1 - 0
app/i18n/es/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Descripción',
 		'description' => 'Descripción',
 		'disabled' => 'Desactivado',
 		'disabled' => 'Desactivado',
 		'empty_list' => 'No hay extensiones instaladas',
 		'empty_list' => 'No hay extensiones instaladas',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Activado',
 		'enabled' => 'Activado',
 		'latest' => 'Instalado',
 		'latest' => 'Instalado',
 		'name' => 'Nombre',
 		'name' => 'Nombre',

+ 4 - 0
app/i18n/es/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Anterior',
 			'previous' => 'Anterior',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Administración de perfiles',
 		'_' => 'Administración de perfiles',
 		'api' => 'Administración de API',
 		'api' => 'Administración de API',

+ 1 - 0
app/i18n/es/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Visualización',
 		'display' => 'Visualización',
 		'extensions' => 'Extensiones',
 		'extensions' => 'Extensiones',
 		'logs' => 'Registros',
 		'logs' => 'Registros',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Peticiones de usuario',
 		'queries' => 'Peticiones de usuario',
 		'reading' => 'Lectura',
 		'reading' => 'Lectura',
 		'search' => 'Buscar palabras o #etiquetas',
 		'search' => 'Buscar palabras o #etiquetas',

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

@@ -116,6 +116,7 @@ return array(
 		'description' => ' توضیحات',
 		'description' => ' توضیحات',
 		'disabled' => ' معلول',
 		'disabled' => ' معلول',
 		'empty_list' => ' هیچ برنامه افزودنی نصب شده ای وجود ندارد',
 		'empty_list' => ' هیچ برنامه افزودنی نصب شده ای وجود ندارد',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => ' فعال است',
 		'enabled' => ' فعال است',
 		'latest' => ' نصب شده است',
 		'latest' => ' نصب شده است',
 		'name' => ' نام',
 		'name' => ' نام',

+ 4 - 0
app/i18n/fa/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => ' قبلی',
 			'previous' => ' قبلی',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => ' مدیریت پروفایل',
 		'_' => ' مدیریت پروفایل',
 		'api' => ' مدیریت API',
 		'api' => ' مدیریت API',

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

@@ -183,6 +183,7 @@ return array(
 		'display' => 'نمایش',
 		'display' => 'نمایش',
 		'extensions' => ' برنامه های افزودنی',
 		'extensions' => ' برنامه های افزودنی',
 		'logs' => ' سیاهههای مربوط',
 		'logs' => ' سیاهههای مربوط',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => ' پرس و جوهای کاربر',
 		'queries' => ' پرس و جوهای کاربر',
 		'reading' => ' خواندن',
 		'reading' => ' خواندن',
 		'search' => ' کلمات یا #برچسب ها را جستجو کنید',
 		'search' => ' کلمات یا #برچسب ها را جستجو کنید',

+ 1 - 0
app/i18n/fr/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Description',	// IGNORE
 		'description' => 'Description',	// IGNORE
 		'disabled' => 'Désactivée',
 		'disabled' => 'Désactivée',
 		'empty_list' => 'Aucune extension installée',
 		'empty_list' => 'Aucune extension installée',
+		'empty_list_help' => 'Vérifiez les logs pour déterminer pourquoi la liste des extensions est vide.',
 		'enabled' => 'Activée',
 		'enabled' => 'Activée',
 		'latest' => 'Installée',
 		'latest' => 'Installée',
 		'name' => 'Nom',
 		'name' => 'Nom',

+ 4 - 0
app/i18n/fr/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Précédent',
 			'previous' => 'Précédent',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Vie privée',
+		'retrieve_extension_list' => 'Récupération de la liste des extensions',
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Gestion du profil',
 		'_' => 'Gestion du profil',
 		'api' => 'Gestion de l’API',
 		'api' => 'Gestion de l’API',

+ 1 - 0
app/i18n/fr/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Affichage',
 		'display' => 'Affichage',
 		'extensions' => 'Extensions',	// IGNORE
 		'extensions' => 'Extensions',	// IGNORE
 		'logs' => 'Logs',	// IGNORE
 		'logs' => 'Logs',	// IGNORE
+		'privacy' => 'Vie privée',
 		'queries' => 'Filtres utilisateurs',
 		'queries' => 'Filtres utilisateurs',
 		'reading' => 'Lecture',
 		'reading' => 'Lecture',
 		'search' => 'Rechercher des mots ou des #tags',
 		'search' => 'Rechercher des mots ou des #tags',

+ 1 - 0
app/i18n/he/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Description',	// TODO
 		'description' => 'Description',	// TODO
 		'disabled' => 'Disabled',	// TODO
 		'disabled' => 'Disabled',	// TODO
 		'empty_list' => 'There is no installed extension',
 		'empty_list' => 'There is no installed extension',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Enabled',	// TODO
 		'enabled' => 'Enabled',	// TODO
 		'latest' => 'Installed',	// TODO
 		'latest' => 'Installed',	// TODO
 		'name' => 'Name',	// TODO
 		'name' => 'Name',	// TODO

+ 4 - 0
app/i18n/he/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'הקודם',
 			'previous' => 'הקודם',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profile management',	// TODO
 		'_' => 'Profile management',	// TODO
 		'api' => 'API management',	// TODO
 		'api' => 'API management',	// TODO

+ 1 - 0
app/i18n/he/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'תצוגה',
 		'display' => 'תצוגה',
 		'extensions' => 'Extensions',	// TODO
 		'extensions' => 'Extensions',	// TODO
 		'logs' => 'לוגים',
 		'logs' => 'לוגים',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'שאילתות',
 		'queries' => 'שאילתות',
 		'reading' => 'קריאה',
 		'reading' => 'קריאה',
 		'search' => 'חיפוש מילים או #תגים',
 		'search' => 'חיפוש מילים או #תגים',

+ 1 - 0
app/i18n/hu/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Leírás',
 		'description' => 'Leírás',
 		'disabled' => 'Kikapcsolva',
 		'disabled' => 'Kikapcsolva',
 		'empty_list' => 'Nincsenek telepített kiegészítők',
 		'empty_list' => 'Nincsenek telepített kiegészítők',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Bekapcsolva',
 		'enabled' => 'Bekapcsolva',
 		'latest' => 'Telepítve',
 		'latest' => 'Telepítve',
 		'name' => 'Név',
 		'name' => 'Név',

+ 4 - 0
app/i18n/hu/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Előző',
 			'previous' => 'Előző',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profil kezelés',
 		'_' => 'Profil kezelés',
 		'api' => 'API menedzsment',
 		'api' => 'API menedzsment',

+ 1 - 0
app/i18n/hu/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Megjelenítés',
 		'display' => 'Megjelenítés',
 		'extensions' => 'Kiegészítők',
 		'extensions' => 'Kiegészítők',
 		'logs' => 'Log-ok',
 		'logs' => 'Log-ok',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Felhasználói lekérdezések',
 		'queries' => 'Felhasználói lekérdezések',
 		'reading' => 'Olvasás',
 		'reading' => 'Olvasás',
 		'search' => 'Szavak vagy #címkék keresése',
 		'search' => 'Szavak vagy #címkék keresése',

+ 1 - 0
app/i18n/id/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Keterangan',
 		'description' => 'Keterangan',
 		'disabled' => 'Dinonaktifkan',
 		'disabled' => 'Dinonaktifkan',
 		'empty_list' => 'Tidak ada ekstensi terpasang',
 		'empty_list' => 'Tidak ada ekstensi terpasang',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Diaktifkan',
 		'enabled' => 'Diaktifkan',
 		'latest' => 'Terinstal',
 		'latest' => 'Terinstal',
 		'name' => 'Nama',
 		'name' => 'Nama',

+ 4 - 0
app/i18n/id/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Sebelumnya',
 			'previous' => 'Sebelumnya',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Manajemen Profil',
 		'_' => 'Manajemen Profil',
 		'api' => 'Manajemen API',
 		'api' => 'Manajemen API',

+ 1 - 0
app/i18n/id/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Display',	// TODO
 		'display' => 'Display',	// TODO
 		'extensions' => 'Extensions',	// TODO
 		'extensions' => 'Extensions',	// TODO
 		'logs' => 'Logs',	// TODO
 		'logs' => 'Logs',	// TODO
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'User queries',	// TODO
 		'queries' => 'User queries',	// TODO
 		'reading' => 'Reading',	// TODO
 		'reading' => 'Reading',	// TODO
 		'search' => 'Search words or #tags',	// TODO
 		'search' => 'Search words or #tags',	// TODO

+ 1 - 0
app/i18n/it/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Descrizione',
 		'description' => 'Descrizione',
 		'disabled' => 'Disabilitata',
 		'disabled' => 'Disabilitata',
 		'empty_list' => 'Non ci sono estensioni installate',
 		'empty_list' => 'Non ci sono estensioni installate',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Abilitata',
 		'enabled' => 'Abilitata',
 		'latest' => 'Installato',
 		'latest' => 'Installato',
 		'name' => 'Nome',
 		'name' => 'Nome',

+ 4 - 0
app/i18n/it/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Precedente',
 			'previous' => 'Precedente',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Gestione profili',
 		'_' => 'Gestione profili',
 		'api' => 'Gestione API',
 		'api' => 'Gestione API',

+ 1 - 0
app/i18n/it/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Visualizzazione',
 		'display' => 'Visualizzazione',
 		'extensions' => 'Estensioni',
 		'extensions' => 'Estensioni',
 		'logs' => 'Log',
 		'logs' => 'Log',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Ricerche personali',
 		'queries' => 'Ricerche personali',
 		'reading' => 'Lettura',
 		'reading' => 'Lettura',
 		'search' => 'Ricerca parole o #tags',
 		'search' => 'Ricerca parole o #tags',

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

@@ -116,6 +116,7 @@ return array(
 		'description' => '説明',
 		'description' => '説明',
 		'disabled' => '無効',
 		'disabled' => '無効',
 		'empty_list' => 'インストールされている拡張機能はありません',
 		'empty_list' => 'インストールされている拡張機能はありません',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => '有効',
 		'enabled' => '有効',
 		'latest' => 'インストール済み',
 		'latest' => 'インストール済み',
 		'name' => '名前',
 		'name' => '名前',

+ 4 - 0
app/i18n/ja/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => '前へ',
 			'previous' => '前へ',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'プロフィール',
 		'_' => 'プロフィール',
 		'api' => 'API管理',
 		'api' => 'API管理',

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

@@ -183,6 +183,7 @@ return array(
 		'display' => 'ディスプレイ',
 		'display' => 'ディスプレイ',
 		'extensions' => '拡張機能',
 		'extensions' => '拡張機能',
 		'logs' => 'ログ',
 		'logs' => 'ログ',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'ユーザークエリ',
 		'queries' => 'ユーザークエリ',
 		'reading' => 'リーディング',
 		'reading' => 'リーディング',
 		'search' => '単語で検索するかハッシュタグで検索する',
 		'search' => '単語で検索するかハッシュタグで検索する',

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

@@ -116,6 +116,7 @@ return array(
 		'description' => '설명',
 		'description' => '설명',
 		'disabled' => '비활성화됨',
 		'disabled' => '비활성화됨',
 		'empty_list' => '설치된 확장 기능이 없습니다',
 		'empty_list' => '설치된 확장 기능이 없습니다',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => '활성화됨',
 		'enabled' => '활성화됨',
 		'latest' => '설치됨',
 		'latest' => '설치됨',
 		'name' => '이름',
 		'name' => '이름',

+ 4 - 0
app/i18n/ko/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => '이전',
 			'previous' => '이전',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => '프로필 관리',
 		'_' => '프로필 관리',
 		'api' => 'API 관리',
 		'api' => 'API 관리',

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

@@ -183,6 +183,7 @@ return array(
 		'display' => '표시',
 		'display' => '표시',
 		'extensions' => '확장 기능',
 		'extensions' => '확장 기능',
 		'logs' => '로그',
 		'logs' => '로그',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => '사용자 쿼리',
 		'queries' => '사용자 쿼리',
 		'reading' => '읽기',
 		'reading' => '읽기',
 		'search' => '단어 또는 #태그 검색',
 		'search' => '단어 또는 #태그 검색',

+ 1 - 0
app/i18n/lv/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Apraksts',
 		'description' => 'Apraksts',
 		'disabled' => 'Atspējots',
 		'disabled' => 'Atspējots',
 		'empty_list' => 'Nav instalētu paplašinājumu',
 		'empty_list' => 'Nav instalētu paplašinājumu',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Ieslēgts',
 		'enabled' => 'Ieslēgts',
 		'latest' => 'Instalēts',
 		'latest' => 'Instalēts',
 		'name' => 'Vārds',
 		'name' => 'Vārds',

+ 4 - 0
app/i18n/lv/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Iepriekšējais',
 			'previous' => 'Iepriekšējais',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profila pārvalde',
 		'_' => 'Profila pārvalde',
 		'api' => 'API pārvalde',
 		'api' => 'API pārvalde',

+ 1 - 0
app/i18n/lv/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Display',	// TODO
 		'display' => 'Display',	// TODO
 		'extensions' => 'Paplašinājumi',
 		'extensions' => 'Paplašinājumi',
 		'logs' => 'Žurnāls',
 		'logs' => 'Žurnāls',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Lietotāja pieprasījumi',
 		'queries' => 'Lietotāja pieprasījumi',
 		'reading' => 'Lasīšana',
 		'reading' => 'Lasīšana',
 		'search' => 'Meklēt vārdus vai #birkas',
 		'search' => 'Meklēt vārdus vai #birkas',

+ 1 - 0
app/i18n/nl/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Beschrijving',
 		'description' => 'Beschrijving',
 		'disabled' => 'Uitgeschakeld',
 		'disabled' => 'Uitgeschakeld',
 		'empty_list' => 'Er zijn geïnstalleerde uitbreidingen',
 		'empty_list' => 'Er zijn geïnstalleerde uitbreidingen',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Ingeschakeld',
 		'enabled' => 'Ingeschakeld',
 		'latest' => 'Geïnstalleerd',
 		'latest' => 'Geïnstalleerd',
 		'name' => 'Naam',
 		'name' => 'Naam',

+ 4 - 0
app/i18n/nl/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Vorige',
 			'previous' => 'Vorige',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profielbeheer',
 		'_' => 'Profielbeheer',
 		'api' => 'API-beheer',
 		'api' => 'API-beheer',

+ 1 - 0
app/i18n/nl/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Opmaak',
 		'display' => 'Opmaak',
 		'extensions' => 'Uitbreidingen',
 		'extensions' => 'Uitbreidingen',
 		'logs' => 'Log boeken',
 		'logs' => 'Log boeken',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Gebruikers informatie',
 		'queries' => 'Gebruikers informatie',
 		'reading' => 'Lezen',
 		'reading' => 'Lezen',
 		'search' => 'Zoek woorden of #labels',
 		'search' => 'Zoek woorden of #labels',

+ 1 - 0
app/i18n/oc/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Descripcion',
 		'description' => 'Descripcion',
 		'disabled' => 'Desactivada',
 		'disabled' => 'Desactivada',
 		'empty_list' => 'Cap d’extensions pas installadas',
 		'empty_list' => 'Cap d’extensions pas installadas',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Activada',
 		'enabled' => 'Activada',
 		'latest' => 'Installada',
 		'latest' => 'Installada',
 		'name' => 'Nom',
 		'name' => 'Nom',

+ 4 - 0
app/i18n/oc/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Precedent',
 			'previous' => 'Precedent',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Gestion del perfil',
 		'_' => 'Gestion del perfil',
 		'api' => 'Gestion API',
 		'api' => 'Gestion API',

+ 1 - 0
app/i18n/oc/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Afichatge',
 		'display' => 'Afichatge',
 		'extensions' => 'Extensions',	// IGNORE
 		'extensions' => 'Extensions',	// IGNORE
 		'logs' => 'Jornals d’audit',	// IGNORE
 		'logs' => 'Jornals d’audit',	// IGNORE
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Filtres utilizaire',
 		'queries' => 'Filtres utilizaire',
 		'reading' => 'Lectura',
 		'reading' => 'Lectura',
 		'search' => 'Recercar de mots o d’#etiquetas',
 		'search' => 'Recercar de mots o d’#etiquetas',

+ 1 - 0
app/i18n/pl/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Opis',
 		'description' => 'Opis',
 		'disabled' => 'Wyłączone',
 		'disabled' => 'Wyłączone',
 		'empty_list' => 'Brak zainstalowanych rozszerzeń',
 		'empty_list' => 'Brak zainstalowanych rozszerzeń',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Włączone',
 		'enabled' => 'Włączone',
 		'latest' => 'Zainstalowane',
 		'latest' => 'Zainstalowane',
 		'name' => 'Nazwa',
 		'name' => 'Nazwa',

+ 4 - 0
app/i18n/pl/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Poprzednie',
 			'previous' => 'Poprzednie',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Zarządzanie profilem',
 		'_' => 'Zarządzanie profilem',
 		'api' => 'Zarządzanie API',
 		'api' => 'Zarządzanie API',

+ 1 - 0
app/i18n/pl/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Wyświetlanie',
 		'display' => 'Wyświetlanie',
 		'extensions' => 'Rozszerzenia',
 		'extensions' => 'Rozszerzenia',
 		'logs' => 'Dziennik',
 		'logs' => 'Dziennik',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Zapisane zapytania',
 		'queries' => 'Zapisane zapytania',
 		'reading' => 'Czytanie',
 		'reading' => 'Czytanie',
 		'search' => 'Wyszukaj wyrazy lub #tagi',
 		'search' => 'Wyszukaj wyrazy lub #tagi',

+ 1 - 0
app/i18n/pt-br/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Descrição',
 		'description' => 'Descrição',
 		'disabled' => 'Desabilitado',
 		'disabled' => 'Desabilitado',
 		'empty_list' => 'Não há extensões instaladas',
 		'empty_list' => 'Não há extensões instaladas',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Habilitada',
 		'enabled' => 'Habilitada',
 		'latest' => 'Instalado',
 		'latest' => 'Instalado',
 		'name' => 'Nome',
 		'name' => 'Nome',

+ 4 - 0
app/i18n/pt-br/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Anterior',
 			'previous' => 'Anterior',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Gerenciamento de perfil',
 		'_' => 'Gerenciamento de perfil',
 		'api' => 'Administração da API',
 		'api' => 'Administração da API',

+ 1 - 0
app/i18n/pt-br/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Visualização',
 		'display' => 'Visualização',
 		'extensions' => 'Extensões',
 		'extensions' => 'Extensões',
 		'logs' => 'Logs',	// IGNORE
 		'logs' => 'Logs',	// IGNORE
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Queries de usuário',
 		'queries' => 'Queries de usuário',
 		'reading' => 'Leitura',
 		'reading' => 'Leitura',
 		'search' => 'Procurar por palavras ou #tags',
 		'search' => 'Procurar por palavras ou #tags',

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

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Описание',
 		'description' => 'Описание',
 		'disabled' => 'Отключены',
 		'disabled' => 'Отключены',
 		'empty_list' => 'Нет установленных расширений',
 		'empty_list' => 'Нет установленных расширений',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Включены',
 		'enabled' => 'Включены',
 		'latest' => 'Установлено',
 		'latest' => 'Установлено',
 		'name' => 'Название',
 		'name' => 'Название',

+ 4 - 0
app/i18n/ru/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Предыдущая',
 			'previous' => 'Предыдущая',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Настройки профиля',
 		'_' => 'Настройки профиля',
 		'api' => 'Настройки API',
 		'api' => 'Настройки API',

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

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Отображение',
 		'display' => 'Отображение',
 		'extensions' => 'Расширения',
 		'extensions' => 'Расширения',
 		'logs' => 'Журнал',
 		'logs' => 'Журнал',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Пользовательские запросы',
 		'queries' => 'Пользовательские запросы',
 		'reading' => 'Чтение',
 		'reading' => 'Чтение',
 		'search' => 'Искать слова или #теги',
 		'search' => 'Искать слова или #теги',

+ 1 - 0
app/i18n/sk/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Popis',
 		'description' => 'Popis',
 		'disabled' => 'Zakázané',
 		'disabled' => 'Zakázané',
 		'empty_list' => 'Žiadne nainštalované rozšírenia',
 		'empty_list' => 'Žiadne nainštalované rozšírenia',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Povolené',
 		'enabled' => 'Povolené',
 		'latest' => 'Nainštalované',
 		'latest' => 'Nainštalované',
 		'name' => 'Názov',
 		'name' => 'Názov',

+ 4 - 0
app/i18n/sk/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Predošlý',
 			'previous' => 'Predošlý',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Správca profilu',
 		'_' => 'Správca profilu',
 		'api' => 'Správa API',
 		'api' => 'Správa API',

+ 1 - 0
app/i18n/sk/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Zobrazenie',
 		'display' => 'Zobrazenie',
 		'extensions' => 'Rozšírenia',
 		'extensions' => 'Rozšírenia',
 		'logs' => 'Záznamy',
 		'logs' => 'Záznamy',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Používateľské dopyty',
 		'queries' => 'Používateľské dopyty',
 		'reading' => 'Čítanie',
 		'reading' => 'Čítanie',
 		'search' => 'Hľadajte slová alebo #značky',
 		'search' => 'Hľadajte slová alebo #značky',

+ 1 - 0
app/i18n/tr/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => 'Açıklama',
 		'description' => 'Açıklama',
 		'disabled' => 'Pasif',
 		'disabled' => 'Pasif',
 		'empty_list' => 'Yüklenmiş eklenti bulunmamaktadır',
 		'empty_list' => 'Yüklenmiş eklenti bulunmamaktadır',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => 'Aktif',
 		'enabled' => 'Aktif',
 		'latest' => 'Kuruldu',
 		'latest' => 'Kuruldu',
 		'name' => 'İsim',
 		'name' => 'İsim',

+ 4 - 0
app/i18n/tr/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => 'Önceki',
 			'previous' => 'Önceki',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => 'Profil yönetimi',
 		'_' => 'Profil yönetimi',
 		'api' => 'API yönetimi',
 		'api' => 'API yönetimi',

+ 1 - 0
app/i18n/tr/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => 'Görünüm',
 		'display' => 'Görünüm',
 		'extensions' => 'Eklentiler',
 		'extensions' => 'Eklentiler',
 		'logs' => 'Log kayıtları',
 		'logs' => 'Log kayıtları',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => 'Kullanıcı sorguları',
 		'queries' => 'Kullanıcı sorguları',
 		'reading' => 'Okuma',
 		'reading' => 'Okuma',
 		'search' => 'Kelime veya #etiket ara',
 		'search' => 'Kelime veya #etiket ara',

+ 1 - 0
app/i18n/zh-cn/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => '描述',
 		'description' => '描述',
 		'disabled' => '已禁用',
 		'disabled' => '已禁用',
 		'empty_list' => '没有已安装的扩展',
 		'empty_list' => '没有已安装的扩展',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => '已启用',
 		'enabled' => '已启用',
 		'latest' => '已安装',
 		'latest' => '已安装',
 		'name' => '名称',
 		'name' => '名称',

+ 4 - 0
app/i18n/zh-cn/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => '上一页',
 			'previous' => '上一页',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => '账户管理',
 		'_' => '账户管理',
 		'api' => 'API 管理',
 		'api' => 'API 管理',

+ 1 - 0
app/i18n/zh-cn/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => '显示',
 		'display' => '显示',
 		'extensions' => '扩展',
 		'extensions' => '扩展',
 		'logs' => '日志',
 		'logs' => '日志',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => '自定义查询',
 		'queries' => '自定义查询',
 		'reading' => '阅读',
 		'reading' => '阅读',
 		'search' => '搜索内容或#文章标签',
 		'search' => '搜索内容或#文章标签',

+ 1 - 0
app/i18n/zh-tw/admin.php

@@ -116,6 +116,7 @@ return array(
 		'description' => '描述',
 		'description' => '描述',
 		'disabled' => '已禁用',
 		'disabled' => '已禁用',
 		'empty_list' => '沒有已安裝的擴充功能',
 		'empty_list' => '沒有已安裝的擴充功能',
+		'empty_list_help' => 'Check the logs to determine the reason behind the empty extension list.',	// TODO
 		'enabled' => '已啟用',
 		'enabled' => '已啟用',
 		'latest' => '已安裝',
 		'latest' => '已安裝',
 		'name' => '名稱',
 		'name' => '名稱',

+ 4 - 0
app/i18n/zh-tw/conf.php

@@ -99,6 +99,10 @@ return array(
 			'previous' => '上一頁',
 			'previous' => '上一頁',
 		),
 		),
 	),
 	),
+	'privacy' => array(
+		'_' => 'Privacy',	// TODO
+		'retrieve_extension_list' => 'Retrieve extension list',	// TODO
+	),
 	'profile' => array(
 	'profile' => array(
 		'_' => '個人資料管理',
 		'_' => '個人資料管理',
 		'api' => 'API 管理',
 		'api' => 'API 管理',

+ 1 - 0
app/i18n/zh-tw/gen.php

@@ -183,6 +183,7 @@ return array(
 		'display' => '顯示',
 		'display' => '顯示',
 		'extensions' => '擴充功能',
 		'extensions' => '擴充功能',
 		'logs' => '日誌',
 		'logs' => '日誌',
+		'privacy' => 'Privacy',	// TODO
 		'queries' => '自定義查詢',
 		'queries' => '自定義查詢',
 		'reading' => '閱讀',
 		'reading' => '閱讀',
 		'search' => '搜尋內容或#標簽',
 		'search' => '搜尋內容或#標簽',

+ 3 - 0
app/layout/aside_configure.phtml

@@ -43,6 +43,9 @@
 				<li class="item<?= Minz_Request::controllerName() === 'extension' ? ' active' : '' ?>">
 				<li class="item<?= Minz_Request::controllerName() === 'extension' ? ' active' : '' ?>">
 					<a href="<?= _url('extension', 'index') ?>"><?= _t('gen.menu.extensions') ?></a>
 					<a href="<?= _url('extension', 'index') ?>"><?= _t('gen.menu.extensions') ?></a>
 				</li>
 				</li>
+				<li class="item<?= Minz_Request::controllerName() === 'privacy' ? ' active' : '' ?>">
+					<a href="<?= _url('configure', 'privacy') ?>"><?= _t('gen.menu.privacy') ?></a>
+				</li>
 				<?php if (!FreshRSS_Auth::hasAccess('admin')) { ?>
 				<?php if (!FreshRSS_Auth::hasAccess('admin')) { ?>
 				<li class="item<?= Minz_Request::actionName() === 'logs' ? ' active' : '' ?>">
 				<li class="item<?= Minz_Request::actionName() === 'logs' ? ' active' : '' ?>">
 					<a href="<?= _url('index', 'logs') ?>"><?= _t('gen.menu.logs') ?></a>
 					<a href="<?= _url('index', 'logs') ?>"><?= _t('gen.menu.logs') ?></a>

+ 1 - 0
app/layout/header.phtml

@@ -79,6 +79,7 @@
 						<li class="item"><a href="<?= _url('configure', 'shortcut') ?>"><?= _t('gen.menu.shortcuts') ?></a></li>
 						<li class="item"><a href="<?= _url('configure', 'shortcut') ?>"><?= _t('gen.menu.shortcuts') ?></a></li>
 						<li class="item"><a href="<?= _url('configure', 'queries') ?>"><?= _t('gen.menu.queries') ?></a></li>
 						<li class="item"><a href="<?= _url('configure', 'queries') ?>"><?= _t('gen.menu.queries') ?></a></li>
 						<li class="item"><a href="<?= _url('extension', 'index') ?>"><?= _t('gen.menu.extensions') ?></a></li>
 						<li class="item"><a href="<?= _url('extension', 'index') ?>"><?= _t('gen.menu.extensions') ?></a></li>
+						<li class="item"><a href="<?= _url('configure', 'privacy') ?>"><?= _t('gen.menu.privacy') ?></a></li>
 						<?= Minz_ExtensionManager::callHookString('menu_configuration_entry') ?>
 						<?= Minz_ExtensionManager::callHookString('menu_configuration_entry') ?>
 					</ul>
 					</ul>
 				</li>
 				</li>

+ 32 - 0
app/views/configure/privacy.phtml

@@ -0,0 +1,32 @@
+<?php
+	/** @var FreshRSS_View $this */
+	$this->partial('aside_configure');
+?>
+
+<main class="post">
+	<div class="link-back-wrapper">
+		<a class="link-back" href="<?= _url('index', 'index') ?>"><?= _t('gen.action.back_to_rss_feeds') ?></a>
+	</div>
+
+	<h1><?= _t('conf.privacy') ?></h1>
+
+	<form method="post" action="<?= _url('configure', 'privacy') ?>">
+		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
+
+		<div class="form-group">
+			<label class="group-name" for="retrieve_extension_list"><?= _t('conf.privacy.retrieve_extension_list') ?></label>
+			<div class="group-controls">
+				<input type="checkbox" id="retrieve_extension_list" name="retrieve_extension_list" value="1"<?=
+					FreshRSS_Context::userConf()->retrieve_extension_list !== false ? ' checked="checked"' : '' ?>
+					data-leave-validation="<?= FreshRSS_Context::userConf()->retrieve_extension_list !== false ? 1 : 0 ?>"/>
+			</div>
+		</div>
+
+		<div class="form-group form-actions">
+			<div class="group-controls">
+				<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
+				<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
+			</div>
+		</div>
+	</form>
+</main>

+ 2 - 0
app/views/extension/index.phtml

@@ -76,6 +76,8 @@
 				<?php } ?>
 				<?php } ?>
 			</table>
 			</table>
 		</div>
 		</div>
+	<?php } else { ?>
+		<p class="alert alert-warn"><?= _t('admin.extensions.empty_list_help') ?></p>
 	<?php } ?>
 	<?php } ?>
 </main>
 </main>
 
 

+ 1 - 0
config-user.default.php

@@ -124,6 +124,7 @@ return array (
 	'show_nav_buttons' => true,
 	'show_nav_buttons' => true,
 	# List of enabled FreshRSS extensions.
 	# List of enabled FreshRSS extensions.
 	'extensions_enabled' => [],
 	'extensions_enabled' => [],
+	'retrieve_extension_list' => true,
 	# Extensions configurations
 	# Extensions configurations
 	'extensions' => [],
 	'extensions' => [],
 );
 );