Improve add feed (#8683)

* Reorder add feed and add category

Implements some suggestions made in https://github.com/FreshRSS/FreshRSS/issues/2014

Changes proposed in this pull request:

- Move "Add feed" as the first section of the Subscriptions add page.  
- Add checkbox "Keep adding feeds" to stay on the "add" page.  

How to test the feature manually:

1. Navigate to the page "Add a feed or category"  
2. See new order.  
3. Type URL of a new feed, select a category, and check "Keep adding feeds "  
4. See FreshRSS confirm the feed was added while staying in the same page.  

* Add checkbox to stay in the add feed page

* Update i18n

* PHP CS

* Manually set i18n progress

* Change i18n

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
This commit is contained in:
pe1ucaandAlexandre Alapetite authored and GitHub committed 2026-04-16 08:23:43 +02:00
1 parent bf4dcb3ddb
commit 6d76dfe822
31 files changed
+63 -24

No files matched your search

+2 -2
View File
@@ -240,10 +240,10 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio
| Magyar (hu) | ■■■■■■■■■・ 97% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%24%2F) |
| Bahasa Indonesia (id) | ■■■■■■■■■・ 90% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fid+%2F%28TODO%7CDIRTY%29%24%2F) |
| Italiano (it) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fit+%2F%28TODO%7CDIRTY%29%24%2F) |
| 日本語 (ja) | ■■■■■■■■・・ 89% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) |
| 日本語 (ja) | ■■■■■■■■・・ 88% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) |
| 한국어 (ko) | ■■■■■■■■・・ 82% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fko+%2F%28TODO%7CDIRTY%29%24%2F) |
| Latviešu (lv) | ■■■■■■■・・・ 76% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Flv+%2F%28TODO%7CDIRTY%29%24%2F) |
| Nederlands (nl) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%24%2F) |
| Nederlands (nl) | ■■■■■■■■■・ 97% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%24%2F) |
| Occitan (oc) | ■■■■■■■・・・ 75% | [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) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%24%2F) |
+2 -2
View File
@@ -136,10 +136,10 @@ See the [repository dedicated to those extensions](https://github.com/FreshRSS/E
| Magyar (hu) | ■■■■■■■■■・ 97% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%24%2F) |
| Bahasa Indonesia (id) | ■■■■■■■■■・ 90% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fid+%2F%28TODO%7CDIRTY%29%24%2F) |
| Italiano (it) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fit+%2F%28TODO%7CDIRTY%29%24%2F) |
| 日本語 (ja) | ■■■■■■■■・・ 89% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) |
| 日本語 (ja) | ■■■■■■■■・・ 88% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fja+%2F%28TODO%7CDIRTY%29%24%2F) |
| 한국어 (ko) | ■■■■■■■■・・ 82% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fko+%2F%28TODO%7CDIRTY%29%24%2F) |
| Latviešu (lv) | ■■■■■■■・・・ 76% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Flv+%2F%28TODO%7CDIRTY%29%24%2F) |
| Nederlands (nl) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%24%2F) |
| Nederlands (nl) | ■■■■■■■■■・ 97% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%24%2F) |
| Occitan (oc) | ■■■■■■■・・・ 75% | [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) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%24%2F) |
+11 -3
View File
@@ -334,9 +334,17 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
return;
}
// Entries are in DB, we redirect to feed configuration page.
$url_redirect['a'] = 'feed';
$url_redirect['params']['id'] = '' . $feed->id();
// Entries are in DB
$keep_adding_feed = Minz_Request::paramBoolean('keep_adding_feed');
if ($keep_adding_feed) {
// We stay in add feed while maintaining some fields
$url_redirect['params']['cat_id'] = $feed->categoryId();
$url_redirect['params']['keep_adding_feed'] = $keep_adding_feed;
} else {
// we redirect to feed configuration page.
$url_redirect['a'] = 'feed';
$url_redirect['params']['id'] = '' . $feed->id();
}
Minz_Request::good(
_t('feedback.sub.feed.added', $feed->name()),
$url_redirect,
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'Informace',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimální počet článků pro ponechání',
'kind' => array(
'_' => 'Typ zdroje feedu',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers werden durch einen Zeilenumbruch getrennt. Name und Wert des Headers werden per Doppelpunkt getrennt (z.B: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icon', // IGNORE
'information' => 'Informationen',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimale Anzahl an Artikeln, die behalten wird',
'kind' => array(
'_' => 'Art der Feed-Quelle',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'Information', // TODO
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimum number of articles to keep', // TODO
'kind' => array(
'_' => 'Type of feed source', // TODO
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // IGNORE
'icon' => 'Icon', // IGNORE
'information' => 'Information', // IGNORE
'keep_adding_feed' => 'Then add more feeds', // IGNORE
'keep_min' => 'Minimum number of articles to keep', // IGNORE
'kind' => array(
'_' => 'Type of feed source', // IGNORE
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icon',
'information' => 'Information',
'keep_adding_feed' => 'Then add more feeds',
'keep_min' => 'Minimum number of articles to keep',
'kind' => array(
'_' => 'Type of feed source',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Las cabeceras son separadas por un salto de línea, y el nombre y valor de una cabecera son separadas por dos puntos (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icono',
'information' => 'Información',
'keep_adding_feed' => 'Seguir añadiendo fuentes',
'keep_min' => 'Número mínimo de artículos a conservar',
'kind' => array(
'_' => 'Tipo de origen de la fuente',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'سر برگ ها با یک خط جدید از هم جدا می‌شوند و نام و مقدار سربرگ ها با یک دونقطه از هم جدا می‌شوند (مثلاً: <kbd><code>پذیرش: application/atom+xml<br />مجوز: Bearer some-token</code></kbd>).',
'icon' => 'آیکون',
'information' => ' اطلاعات',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => ' حداقل تعداد مقالات برای نگهداری',
'kind' => array(
'_' => ' نوع منبع خوراک',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Otsikot erotellaan rivinvaihdoin, ja nimi ja arvo erotellaan kaksoispisteellä. Esimerkki: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Kuvake',
'information' => 'Tiedot',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Säilytettävien artikkeleiden vähimmäismäärä',
'kind' => array(
'_' => 'Syötteen lähteen laji',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Un entête HTTP par ligne, avec le nom et la valeur séparés par un deux-points (ex. : <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icône',
'information' => 'Informations',
'keep_adding_feed' => 'Puis ajouter d’autres flux',
'keep_min' => 'Nombre minimum d’articles à conserver',
'kind' => array(
'_' => 'Type de source de flux',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'מידע',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'מסםר מינימלי של מאמרים לשמור',
'kind' => array(
'_' => 'Type of feed source', // TODO
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'A fejléceket újsor választja el, a fejléc nevét és értékét kettőspont választja el (pl: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icon', // IGNORE
'information' => 'Információ',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Megtartandó cikkek minimális száma',
'kind' => array(
'_' => 'Hírforrás típusa',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Tajuk dipisahkan dengan baris baru dan nama dan nilai dari tajuk dipisahkan dengan titik dua (contoh: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Ikon',
'information' => 'Informasi',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Jumlah minimum artikel yang harus disimpan',
'kind' => array(
'_' => 'Jenis sumber umpan',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Le intestazioni sono separate da una linea e il nome e il valore di un’intestazione sono separati da due punti (p.es: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icona',
'information' => 'Informazioni',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Numero minimo di articoli da mantenere',
'kind' => array(
'_' => 'Tipo di sorgente del feed',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'ヘッダは改行で区切られ、ヘッダの名前と値はコロンで区切られます (例: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icon', // TODO
'information' => 'インフォメーション',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => '最小数の記事は保持されます',
'kind' => array(
'_' => 'フィードソースの種類',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => '정보',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => '최소 유지 글 개수',
'kind' => array(
'_' => '피드 소스 유형',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'Informācija',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimālais saglabājamo izstrādājumu skaits',
'kind' => array(
'_' => 'Barotnes avota veids',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers worden gescheiden door een regeleinde, en de naam en waarde van een header worden gescheiden door een dubbele punt (bijv.: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer een-token</code></kbd>).',
'icon' => 'Pictogram',
'information' => 'Informatie',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimum aantal artikelen om te houden',
'kind' => array(
'_' => 'Feedbron-type',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'Informacions',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Nombre minimum d’articles de servar',
'kind' => array(
'_' => 'Tipe de font de flux',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Nagłówki są oddzielane przez nową linię, a nazwa i wartość nagłówka są oddzielane przez dwukropek (np: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer jakiś-token</code></kbd>).',
'icon' => 'Ikona',
'information' => 'Informacja',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimalna liczba wiadomości do przechowywania',
'kind' => array(
'_' => 'Rodzaj źródła kanału',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Os cabeçalhos são separados por uma nova linha, e o nome e o valor de um cabeçalho são separados por dois pontos (ex: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Ícone',
'information' => 'Informações',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Número mínimo de artigos para manter',
'kind' => array(
'_' => 'Tipo de fonte de alimentação do Feed',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'Informações',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Número mínimo de artigos para manter',
'kind' => array(
'_' => 'Tipo de fonte de alimentação do Feed',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Заголовки разделяются новой строкой, имя и значение заголовка разделяются двоеточием (например: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Иконка',
'information' => 'Информация',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Оставлять статей не менее',
'kind' => array(
'_' => 'Тип источника ленты',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => 'Informácia',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Minimálny počet článkov na uchovanie',
'kind' => array(
'_' => 'Typ zdroja kanála',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Başlıklar yeni bir satırla ayrılır ve bir başlığın adı ile değeri iki nokta üst üste ile ayrılır (örneğin: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).',
'icon' => 'Icon', // TODO
'information' => 'Bilgi',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Saklanacak minimum makale sayısı',
'kind' => array(
'_' => 'Besleme kaynağı türü',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'По заголовку на рядок. Назву й значення відокремлено двокрапкою (наприклад, <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer деякий-токен</code></kbd>).',
'icon' => 'Піктограма',
'information' => 'Інформація',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => 'Мінімум збережених статей',
'kind' => array(
'_' => 'Тип джерела стрічки',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => '头部之间用换行符分隔,头部名称和值用冒号分隔(例如:<kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>)。',
'icon' => '图标',
'information' => '信息',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => '至少保存的文章数',
'kind' => array(
'_' => '订阅源类型',
+1
View File
@@ -86,6 +86,7 @@ return array(
'http_headers_help' => 'Headers are separated by a newline, and the name and value of a header are separated by a colon (e.g: <kbd><code>Accept: application/atom+xml<br />Authorization: Bearer some-token</code></kbd>).', // TODO
'icon' => 'Icon', // TODO
'information' => '信息',
'keep_adding_feed' => 'Then add more feeds', // TODO
'keep_min' => '至少保存的文章數',
'kind' => array(
'_' => '訂閱源類型',
+21 -17
View File
@@ -5,23 +5,6 @@
?>
<main class="post drop-section" data-auto-leave-validation="1">
<h1><?= _t('sub.menu.add') ?></h1>
<h2><?= _t('sub.title.add_category') ?></h2>
<form action="<?= _url('category', 'create') ?>" method="post">
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
<div class="form-group">
<label class="group-name" for="new-category"><?= _t('sub.category') ?></label>
<div class="group-controls">
<input id="new-category" name="new-category" type="text" required="required" autocomplete="off" />
</div>
</div>
<div class="form-group form-actions">
<div class="group-controls">
<button type="submit" class="btn btn-important"><?= _t('gen.action.add') ?></button>
</div>
</div>
</form>
<h2><?= _t('sub.title.add_feed') ?></h2>
<form id="add_rss" method="post" action="<?= _url('feed', 'add') ?>" autocomplete="off">
@@ -52,6 +35,10 @@
</option>
<?php } ?>
</select>
<label for="keep_adding_feed">
<input type="checkbox" name="keep_adding_feed" id="keep_adding_feed" value="1" <?= Minz_Request::paramBoolean('keep_adding_feed') ? "checked" : "" ?> />
<?= _t('sub.feed.keep_adding_feed') ?>
</label>
</div>
</div>
@@ -378,6 +365,23 @@
</div>
</form>
<h2><?= _t('sub.title.add_category') ?></h2>
<form action="<?= _url('category', 'create') ?>" method="post">
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
<div class="form-group">
<label class="group-name" for="new-category"><?= _t('sub.category') ?></label>
<div class="group-controls">
<input id="new-category" name="new-category" type="text" required="required" autocomplete="off" />
</div>
</div>
<div class="form-group form-actions">
<div class="group-controls">
<button type="submit" class="btn btn-important"><?= _t('gen.action.add') ?></button>
</div>
</div>
</form>
<h2>
<?= _t('sub.title.add_dynamic_opml') ?>
<?= _i('opml-dyn') ?>