Compare commits

...

18 Commits

Author SHA1 Message Date
Sunil Mohan Adapa
37e40883e1
ui: Fix dark theme colors for app enable/disable toggle button
Tests:

- In the Calibre app page, the enable/disable toggle button has dark colors in
dark theme mode. The colors are proper when enabled, disabled, enabling,
disabling, hover.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:47 -05:00
Sunil Mohan Adapa
a0fe5e50eb
ui: Fix dark theme color for select-all button
Tests:

- Select-all button in create backup page has mostly unchanged color in light
mode and more consistent color in dark mode.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:42 -05:00
Sunil Mohan Adapa
6c7d77fd3b
ui: Minor CSS refactor to use variables
Tests:

- Main header's shadow is unchanged in light mode. In dark mode, it is still the
same and not really visible. This is better than casting a white shadow.

Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:39 -05:00
Sunil Mohan Adapa
85f04dde1a
ui: Fix dark theme colors for running status indicator
Tests:

- Insert event.preventDefault() in form submission code for submission buttons.

- For various button styles, submit the form. Running status indicator appears
on the form button. The styles for the indicator is appropriate in dark and
light themes.

  - Calibre delete library confirmation page has btn-danger.

  - Software Update, configuration update button has btn-primary.

  - Software Update, 'update now' button has btn-default.

  - Change a button from btn-primary to btn-link. Running status is not shown
  for this type of button.

Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:36 -05:00
Sunil Mohan Adapa
4bbe53e9ff
ui: Drop colors defined in Bootstrap 5.3
- They were only present for compatibility with Bootstrap 5.2. The values were
picked directly from Bootstrap 5.3. So, there is no change in output.

Tests:

- Go to user creation form and make errors. A form element with error has red
outline like more. The help text and error message are also in red like before.
In dark mode, they are more appropriate with the rest of the page and with
higher contrast.

- On default styled button, background color on hover is also improved
similarly.

- The border for select-all button in the create new backup page is also
improved similarly.

Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:33 -05:00
Sunil Mohan Adapa
c19fe296a4
ui: Dark theme color for tags text in an app card
Tests:

- In apps and system pages, the tags text in a card is unchanged in light theme.
In dark theme, it is more consistent with the rest of the page.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:30 -05:00
Sunil Mohan Adapa
499c6073a1
ui: Fix dark theme color for disabled form elements
Tests:

- In network connection editing page, find some form elements that are disabled
and their light mode color is mostly unchanged. In dark mode, it looks
consistent with the rest of the page.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:28 -05:00
Sunil Mohan Adapa
2ae78daebb
ui: Fix dark theme colors for default button style
- Use color variables provided by Bootstrap. These automatically adjust to light
and dark themes.

Tests:

- In light mode, the style for 'Update now' button in Software Update app is
close to what it was before. In dark mode, the styling is consistent with the
rest of the page.

- Same is true for Calibre app 'Delete Library' button and extra options button
in an app.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:25 -05:00
Sunil Mohan Adapa
d6b5b3bed2
ui: Fix dark theme color for form help text
- Use the right CSS variable.

Tests:

- In a form, the help text for an input is unchanged in light mode. And in dark
mode, it is more appropriate.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:21 -05:00
Sunil Mohan Adapa
b166404b0a
ui: Use default button style for tag buttons
- In the app header as well as tag search bar.

- De-emphasize the tag buttons in app header so that users won't see them as
sections of the page.

- Add a bullet Unicode character between the tags in app header to separate them
properly with new de-emphasized styling.

- Fix vertical alignment of text between tag buttons in app header and the close
button in tags in tag search bar.

Tests:

- In the app header, styling has been de-emphasized and tags now look more like
simple text. They are a separated with a bullet Unicode character. Vertical
alignment of bullets is accurate.

- In the tag search bar, tags continue to look like buttons but more like default
buttons. Vertical alignment of close button is accurate.

- In both areas tags look properly in dark and light color themes.

- In mobile view when there are a lot of tags, tags flow into second line.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:18 -05:00
Sunil Mohan Adapa
6c930a9f24
upgrades: Use bootstrap spinner button instead of custom styling
- This simplifies the implementation and gets it ready for dark/light mode.

Tests:

- In the upgrades main view, set is_busy = True and disable setting
refresh_page_sec. Load the upgrades app and notice that the 'Updating...' button
is showing proper styling in light anddark modes.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:11 -05:00
Sunil Mohan Adapa
00a69108dd
ui: Implement a toggle menu for setting dark mode
- Add a toggle menu for selecting the color scheme. JS code largely taken from
Bootstrap documentation and slightly customized.

- Use local storage to store the setting for dark/light/auto. Default to auto
which means browser level preference is picked up (which could be system level
preference).

Tests:

- Appearance of the toggle menu is consistent. Check box is shown on the
currently selected value.

- Deleting the local storage value reverts the preference to browser set value.

- Menu is collapsed at smaller screen sizes. Appearance and functionality as
expected.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2025-12-02 20:17:06 -05:00
Coucouf
0419eb02cf
Translated using Weblate (French)
Currently translated at 100.0% (1875 of 1875 strings)
2025-12-02 13:00:25 +01:00
OwlGale
b2b581309e
Translated using Weblate (Russian)
Currently translated at 100.0% (1875 of 1875 strings)
2025-12-02 13:00:24 +01:00
Coucouf
d99161b4cc
Translated using Weblate (French)
Currently translated at 100.0% (1875 of 1875 strings)
2025-12-01 12:00:42 +01:00
kosagi
6ce4df4350
Translated using Weblate (Catalan)
Currently translated at 44.4% (833 of 1875 strings)
2025-12-01 12:00:39 +01:00
OwlGale
0d30193240
Translated using Weblate (Russian)
Currently translated at 100.0% (1875 of 1875 strings)
2025-12-01 12:00:20 +01:00
James Valleroy
7e9070e418
homeassistant: Fix spelling in tests
Tests:

- pytest runs the expected tests for Home Assistant.

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
2025-11-30 04:43:50 +05:30
13 changed files with 679 additions and 328 deletions

5
debian/copyright vendored
View File

@ -38,6 +38,11 @@ Copyright: Marie Van den Broeck (https://thenounproject.com/marie49/)
Comment: https://thenounproject.com/icon/162372/
License: CC-BY-SA-3.0
Files: static/themes/default/js/color-modes.js
Copyright: 2011-2025 The Bootstrap Authors
Comment: https://getbootstrap.com/docs/5.3/customize/color-modes/
License: CC-BY-3.0
Files: plinth/modules/bepasty/static/icons/bepasty.svg
Copyright: (c) 2014 by the Bepasty Team, see the AUTHORS file.
Comment: https://github.com/bepasty/bepasty-server/blob/master/src/bepasty/static/app/bepasty.svg

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: FreedomBox UI\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-11-25 01:21+0000\n"
"PO-Revision-Date: 2025-10-30 04:24+0000\n"
"PO-Revision-Date: 2025-12-02 12:00+0000\n"
"Last-Translator: Coucouf <coucouf@coucouf.fr>\n"
"Language-Team: French <https://hosted.weblate.org/projects/freedombox/"
"freedombox/fr/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.14.1-dev\n"
"X-Generator: Weblate 5.15-dev\n"
#: plinth/config.py:103
#, python-brace-format
@ -4460,11 +4460,7 @@ msgstr ""
"moins un domaine pour pouvoir utiliser Matrix Synapse."
#: plinth/modules/matrixsynapse/templates/matrix-synapse.html:20
#, fuzzy, python-format
#| msgid ""
#| "The Matrix server domain is set to <em>%(domain_name)s</em>. User IDs "
#| "will look like <em>@username:%(domain_name)s</em>. Changing the domain "
#| "name after the initial setup is currently not supported."
#, python-format
msgid ""
"The Matrix server domain is set to <em>%(domain_name)s</em>. User IDs will "
"look like <em>@username:%(domain_name)s</em>. Changing the domain name "
@ -4472,8 +4468,9 @@ msgid ""
msgstr ""
"Votre serveur Matrix utilise le domaine <em>%(domain_name)s</em>. Les "
"identifiants utilisateur seront du type <em>@identifiant:%(domain_name)s</"
"em>. Le changement du nom de domaine après linstallation initiale nest "
"actuellement pas pris en charge."
"em>. Le changement du nom de domaine nécéssite la désinstallation et "
"réinstallation de lappli ce qui entraînera la suppression de lensemble des "
"données de cette appli."
#: plinth/modules/matrixsynapse/templates/matrix-synapse.html:28
msgid ""
@ -4516,10 +4513,8 @@ msgid "Unlimited"
msgstr "Illimité"
#: plinth/modules/matrixsynapse/templates/matrix-synapse.html:78
#, fuzzy
#| msgid "Feed generator"
msgid "Federation"
msgstr "Générateur de fils"
msgstr "Fédération"
#: plinth/modules/matrixsynapse/templates/matrix-synapse.html:81
#, python-format
@ -4530,6 +4525,12 @@ msgid ""
"hosted here. If you face problems with federation, try the <a "
"href=\"%(tester_url)s#%(domain_name)s\"> federation tester tool</a>."
msgstr ""
"Matrix Synapse est configuré pour communiquer avec dautres serveurs sur "
"Internet. Ceci permet aux utilisateurices de la %(box_name)s de participer à "
"des salons hébergés ailleurs et à des utilisateurices dautres serveurs de "
"participer aux salons hébergés ici. En cas de problème avec la fédération, "
"vous pouvez utiliser l<a href=\"%(tester_url)s#%(domain_name)s\">outil de "
"test de fédération</a>."
#: plinth/modules/matrixsynapse/templates/matrix-synapse.html:99
#, python-format
@ -7453,20 +7454,16 @@ msgstr ""
"dactualités."
#: plinth/modules/rssbridge/__init__.py:28
#, fuzzy, python-brace-format
#| msgid ""
#| "You can use RSS-Bridge with <a href=\"{miniflux_url}\">Miniflux</a> or <a "
#| "href=\"{ttrss_url}\">Tiny Tiny RSS</a> to follow various websites. When "
#| "adding a feed, enable authentication and use your {box_name} credentials."
#, python-brace-format
msgid ""
"You can use RSS-Bridge with <a href=\"{miniflux_url}\">Miniflux</a> or <a "
"href=\"{nextcloud_url}\">Nextcloud News</a> to follow various websites. When "
"adding a feed, enable authentication and use your {box_name} credentials."
msgstr ""
"Vous pouvez utiliser RSS-Bridge avec <a href=\"{miniflux_url}\">Miniflux</a> "
"ou bien <a href=\"{ttrss_url}\">Tiny Tiny RSS</a> pour suivre différents "
"sites Internet. Lors de lajout dun fil, activez lauthentification et "
"utilisez les identifiants de {box_name}."
"ou bien <a href=\"{nextcloud_url}\">Nextcloud News</a> pour suivre "
"différents sites Internet. Lors de lajout dun fil, activez "
"lauthentification et utilisez vos identifiants {box_name}."
#: plinth/modules/rssbridge/__init__.py:49
msgid "Read and subscribe to news feeds"

View File

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-11-25 01:21+0000\n"
"PO-Revision-Date: 2025-11-21 02:51+0000\n"
"Last-Translator: Roman Akimov <zoompyc@gmail.com>\n"
"PO-Revision-Date: 2025-12-02 12:00+0000\n"
"Last-Translator: OwlGale <owlgale@users.noreply.hosted.weblate.org>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/freedombox/"
"freedombox/ru/>\n"
"Language: ru\n"
@ -107,7 +107,7 @@ msgstr "Использовать языковые настройки брауз
#: plinth/menu.py:116 plinth/templates/base.html:120
msgid "Home"
msgstr "Домой"
msgstr "Главная"
#: plinth/menu.py:117 plinth/templates/base.html:129
msgid "Apps"
@ -1237,7 +1237,7 @@ msgstr "Библиотека"
#: plinth/modules/calibre/manifest.py:21
msgid "Ebook reader"
msgstr "Читалка для электронных книг"
msgstr "Читалка"
#: plinth/modules/calibre/templates/calibre-delete-library.html:11
#, python-format
@ -1632,12 +1632,12 @@ msgstr "BitTorrent клиент, написанный на Python/pygtk"
#: plinth/modules/deluge/manifest.py:21
#: plinth/modules/transmission/manifest.py:39
msgid "BitTorrent"
msgstr "БитТоррент"
msgstr "BitTorrent"
#: plinth/modules/deluge/manifest.py:21 plinth/modules/roundcube/manifest.py:23
#: plinth/modules/transmission/manifest.py:39
msgid "Web client"
msgstr "Веб клиент"
msgstr "Веб-клиент"
#: plinth/modules/deluge/manifest.py:21 plinth/modules/syncthing/manifest.py:58
#: plinth/modules/transmission/manifest.py:39
@ -2465,7 +2465,7 @@ msgstr "FairEmail"
#: plinth/modules/email/manifest.py:82
msgid "Email server"
msgstr "Сервер Электронной почты"
msgstr "Почтовый сервер"
#: plinth/modules/email/manifest.py:82
msgid "IMAP"
@ -2473,7 +2473,7 @@ msgstr "IMAP"
#: plinth/modules/email/manifest.py:82
msgid "Spam control"
msgstr "Контроль спама"
msgstr "Защита от спама"
#: plinth/modules/email/templates/email-aliases.html:13
#: plinth/modules/email/templates/email.html:15
@ -2635,16 +2635,16 @@ msgstr ""
#: plinth/modules/ikiwiki/__init__.py:79
#: plinth/modules/tiddlywiki/__init__.py:61
msgid "View and edit wiki applications"
msgstr "Просмотр и редактирование приложений Wiki"
msgstr "Просмотр и редактирование вики приложений"
#: plinth/modules/featherwiki/__init__.py:59
#: plinth/modules/featherwiki/manifest.py:9
msgid "Feather Wiki"
msgstr "Перо Вики"
msgstr "Feather Wiki"
#: plinth/modules/featherwiki/forms.py:13 plinth/modules/tiddlywiki/forms.py:13
msgid "Wiki files cannot be named \"index.html\"."
msgstr "Wiki-файлы не могут называться \"index.html\"."
msgstr "Вики файлы не могут называться \"index.html\"."
#: plinth/modules/featherwiki/forms.py:20 plinth/modules/tiddlywiki/forms.py:20
msgid "Name of the wiki file, with file extension \".html\""
@ -2684,13 +2684,13 @@ msgstr "Загрузите существующий файл Feather Wiki с э
#: plinth/modules/mediawiki/manifest.py:25
#: plinth/modules/tiddlywiki/manifest.py:19
msgid "Wiki"
msgstr "Wiki"
msgstr "Вики"
#: plinth/modules/featherwiki/manifest.py:18
#: plinth/modules/infinoted/manifest.py:46
#: plinth/modules/tiddlywiki/manifest.py:20
msgid "Note taking"
msgstr "Взятие на заметку"
msgstr "Заметки"
#: plinth/modules/featherwiki/manifest.py:18
#: plinth/modules/ikiwiki/manifest.py:15
@ -2703,13 +2703,13 @@ msgstr "Веб-сайт"
#: plinth/modules/featherwiki/manifest.py:18
#: plinth/modules/tiddlywiki/manifest.py:25
msgid "Quine"
msgstr "Quine"
msgstr "Куайн"
#: plinth/modules/featherwiki/manifest.py:18
#: plinth/modules/nextcloud/manifest.py:56
#: plinth/modules/tiddlywiki/manifest.py:26
msgid "Non-Debian"
msgstr "Не-Debian"
msgstr "Не Debian"
#: plinth/modules/featherwiki/templates/featherwiki_configure.html:12
#: plinth/modules/tiddlywiki/templates/tiddlywiki_configure.html:12
@ -2781,7 +2781,7 @@ msgstr "Скачать"
#: plinth/modules/featherwiki/views.py:20 plinth/modules/tiddlywiki/views.py:20
msgid "A wiki file with the given name already exists."
msgstr "Файл wiki с указанным именем уже существует."
msgstr "Вики файл с указанным именем уже существует."
#: plinth/modules/featherwiki/views.py:54 plinth/modules/tiddlywiki/views.py:54
msgid "Wiki created."
@ -2816,7 +2816,7 @@ msgstr "Добавлен вики-файл."
#: plinth/modules/featherwiki/views.py:119
#: plinth/modules/tiddlywiki/views.py:120
msgid "Failed to add wiki file."
msgstr "Не удалось добавить файл wiki."
msgstr "Не удалось добавить вики файл."
#: plinth/modules/featherwiki/views.py:138
#: plinth/modules/tiddlywiki/views.py:139
@ -3248,7 +3248,7 @@ msgstr "GNOME"
#: plinth/modules/gnome/manifest.py:9 plinth/templates/clients.html:42
msgid "Desktop"
msgstr "Десктоп"
msgstr "Рабочий стол"
#: plinth/modules/gnome/manifest.py:10
msgid "Browser"
@ -3260,7 +3260,7 @@ msgstr "Офисный пакет"
#: plinth/modules/gnome/manifest.py:12
msgid "Software store"
msgstr "Магазин программного обеспечения"
msgstr "Магазин приложений"
#: plinth/modules/gnome/manifest.py:13
msgid "GUI"
@ -3288,7 +3288,7 @@ msgstr "Руководство"
#: plinth/modules/help/views.py:91 plinth/templates/help-menu.html:27
#: plinth/templates/help-menu.html:28
msgid "Get Support"
msgstr "Получить поддержку"
msgstr "Получить помощь"
#: plinth/modules/help/__init__.py:45
#: plinth/modules/help/templates/help_feedback.html:9
@ -3303,7 +3303,7 @@ msgstr "Отправить отзыв"
#: plinth/modules/help/views.py:74 plinth/templates/help-menu.html:39
#: plinth/templates/help-menu.html:40
msgid "Contribute"
msgstr "Помощь проекту"
msgstr "Помочь проекту"
#: plinth/modules/help/__init__.py:53 plinth/templates/base.html:216
#: plinth/templates/base.html:219 plinth/templates/help-menu.html:46
@ -3327,13 +3327,13 @@ msgstr "Вы используете %(os_release)s и %(box_name)s версии
msgid ""
"There is a new %(box_name)s version <a href=\"%(upgrades_url)s\">available</"
"a>."
msgstr "<a href=\"%(upgrades_url)s\">Доступна новая версия</a> %(box_name)s."
msgstr "Доступна <a href=\"%(upgrades_url)s\">новая версия</a> %(box_name)s."
#: plinth/modules/help/templates/help_about.html:40
#: plinth/modules/upgrades/templates/upgrades_configure.html:42
#, python-format
msgid "%(box_name)s is up to date."
msgstr "%(box_name)s в актуальном состоянии."
msgstr "Установлены все последние обновления %(box_name)s."
#: plinth/modules/help/templates/help_about.html:49
#, python-format
@ -3346,14 +3346,14 @@ msgid ""
"and a Tor relay, on a device that can replace your Wi-Fi router, so that "
"your data stays with you."
msgstr ""
"%(box_name)s - это проект сообщества для разработки, дизайна и поощрения "
"личных серверов под управлением свободного программного обеспечения для "
"частных, личных сообщений. Это сетевое устройство, предназначенное разрешить "
"взаимодействие с остальной частью Интернета в условиях защиты "
"конфиденциальности и безопасности данных. Он содержит различные приложения, "
"такие как блог, вики, веб-сайт, социальную сеть, электронную почту, Web-"
"прокси и сервер Tor, на устройстве, которое может заменить ваш маршрутизатор "
"Wi-Fi, так что ваши данные остаются с вами."
"%(box_name)s это общественный проект для разработки, проектирования и "
"продвижения персональных серверов работающих на свободном программном "
"обеспечении для частных, личных коммуникаций. Это сетевое устройство "
"предназначено для взаимодействия с остальной частью Интернета при условии "
"обеспечения конфиденциальности и безопасности данных. Оно позволяет "
"размещать такие веб-приложения, как блог, вики, веб-сайт, социальную сеть, "
"электронную почту, веб-прокси и узел сети Tor, на устройстве, которое может "
"заменить ваш Wi-Fi роутер, чтобы ваши данные оставались с вами."
#: plinth/modules/help/templates/help_about.html:62
msgid ""
@ -3364,12 +3364,13 @@ msgid ""
"giving back power to the users over their networks and machines, we are "
"returning the Internet to its intended peer-to-peer architecture."
msgstr ""
"Мы живем в мире, сетями владеют те, с кем у нас не всегда общие интересы. "
"Путем создания программного обеспечения, которое не полагается на "
"центральную службу, мы можем восстановить контроль и конфиденциальность. "
"Сохраняя наши данные в наших домах, мы получаем полезную правовую защиту над "
"ними. Давая обратно власть пользователям в их сети и машины, мы возвращаемся "
его предполагаемую архитектуру Интернета peer-to-peer."
"Мы живем в мире, где использование сети определяется теми, кто зачастую не "
"действует в наших интересах. Разрабатывая программное обеспечение, которое "
"не полагается на централизованный сервис, мы можем вернуть контроль и "
"конфиденциальность. Сохраняя наши данные у себя дома, мы повышаем правовую "
"защищенность над ними. Давая пользователям власть над их сетями и "
"устройствами, мы возвращаем Интернет к его одноранговой архитектуре, каким "
"он был задуман."
#: plinth/modules/help/templates/help_about.html:75
#, python-format
@ -3379,7 +3380,7 @@ msgid ""
"package."
msgstr ""
"Существует ряд проектов, которые работают в сторону реализации будущего "
"распределенных служб, %(box_name)s стремится объединить их в удобном пакете."
"распределенных сервисов, %(box_name)s стремится объединить их."
#: plinth/modules/help/templates/help_about.html:83
#, python-format
@ -3392,16 +3393,17 @@ msgid ""
"running \"apt source <i>package_name</i>\" in a terminal (using Cockpit or "
"SSH)."
msgstr ""
"%(box_name)s - это свободное ПО, лицензированное по лицензии GNU Affero "
"General Public License. <a href=\"http://salsa.debian.org/freedombox-team/"
"freedombox\"> %(box_name)s репозиторий</a>. Кроме того, исходный код любого "
"пакета Debian может быть получен из <a href=\"https://sources.debian.org/"
"\">Debian Sources</a> site, или путем запуска \"apt source <i>package_name</"
"i>\" в терминале (с использованием Cockpit или SSH)."
"%(box_name)s является свободным программным обеспечением и распространяется "
"по лицензии GNU Affero General Public License. Исходный код доступен онлайн "
"в <a href=\"https://salsa.debian.org/freedombox-team/freedombox\"> "
"репозитории %(box_name)s </a>. Кроме того, исходный код пакетов Debian "
"можно получить с сайта <a href=\"https://sources.debian.org/\">Debian "
"Sources</a> или выполнив команду \"apt source <i>название_пакета</i>\" в "
"терминале (с помощью Cockpit или SSH)."
#: plinth/modules/help/templates/help_about.html:97
msgid "Learn"
msgstr "Узнать"
msgstr "Освоить"
#: plinth/modules/help/templates/help_about.html:116
#: plinth/templates/toolbar.html:19
@ -3410,7 +3412,7 @@ msgstr "Пожертвовать"
#: plinth/modules/help/templates/help_about.html:119
msgid "Join project"
msgstr "Присоединяйтесь к проекту"
msgstr "Присоединиться к проекту"
#: plinth/modules/help/templates/help_about.html:123
msgid "Translate"
@ -3708,11 +3710,11 @@ msgstr "Home Assistant"
#: plinth/modules/homeassistant/manifest.py:62
msgid "Home Automation"
msgstr "Домашняя автоматизация"
msgstr "Умный дом"
#: plinth/modules/homeassistant/manifest.py:63
msgid "IoT"
msgstr "IoT"
msgstr "Интернет вещей"
#: plinth/modules/homeassistant/manifest.py:64
#: plinth/modules/networks/manifest.py:8
@ -3733,7 +3735,7 @@ msgstr "Z-Wave"
#: plinth/modules/homeassistant/manifest.py:67
msgid "Thread"
msgstr "Тред"
msgstr "Thread"
#: plinth/modules/homeassistant/templates/homeassistant.html:17
msgid ""
@ -3784,9 +3786,9 @@ msgid ""
"<i>edit</i> existing ones. In the <a href=\"{users_url}\">User "
"Configuration</a> you can change these permissions or add new users."
msgstr ""
"Только пользователи {box_name} группы <b>администраторов</b> могут "
"<i>создавать</i> и <i>управлять</i> блогами и вики, но любой пользователь "
"группы <b>wiki</b> могжет <i>редактировать</i> существующие. На странице <a "
"Только пользователи {box_name} группы <b>администраторов</b> могут <i>"
"создавать</i> и <i>управлять</i> блогами и вики, но любой пользователь "
"группы <b>wiki</b> может <i>редактировать</i> существующие. На странице <a "
"href=\"{users_url}\">Конфигурация пользователей</a> вы можете изменить "
"разрешения или добавить новых пользователей."
@ -3977,7 +3979,7 @@ msgstr "JSXC"
#: plinth/modules/jsxc/manifest.py:16
msgid "Web chat"
msgstr "Веб чат"
msgstr "Веб-чат"
#: plinth/modules/jsxc/manifest.py:16 plinth/modules/quassel/manifest.py:54
msgid "Client"
@ -3989,10 +3991,10 @@ msgid ""
"Wikipedia available without using the internet, but it is potentially "
"suitable for all HTML content. Kiwix packages are in the ZIM file format."
msgstr ""
"Kiwix является офлайн-читателкой для веб-контента. Это программа "
"предназначенная для того,чтобы сделать Википедию доступной автономно без "
"Интернета, но оно потенциально подходит для всего HTML-контента. Пакеты "
"Kiwix находятся в формате ZIM."
"Kiwix является офлайн читалкой для веб-контента. Это программа "
"предназначенная для того, чтобы сделать Википедию доступной автономно без "
"Интернета, но потенциально подходит для любого HTML-контента. Пакеты Kiwix "
"представляют собой файлы в формате ZIM."
#: plinth/modules/kiwix/__init__.py:25
msgid ""
@ -4053,7 +4055,7 @@ msgstr ""
#: plinth/modules/kiwix/manifest.py:24
msgid "Offline reader"
msgstr "Автономный читатель"
msgstr "Оффлайн читалка"
#: plinth/modules/kiwix/manifest.py:25
msgid "Archival"
@ -4064,7 +4066,7 @@ msgstr "Архив"
#: plinth/modules/shadowsocksserver/manifest.py:18
#: plinth/modules/tor/manifest.py:60 plinth/modules/torproxy/manifest.py:57
msgid "Censorship resistance"
msgstr "Противодействие цензуре"
msgstr "Сопротивление цензуре"
#: plinth/modules/kiwix/manifest.py:27
msgid "Wikipedia"
@ -4356,11 +4358,11 @@ msgstr "FluffyChat"
#: plinth/modules/matrixsynapse/manifest.py:101
#: plinth/modules/quassel/manifest.py:54
msgid "Chat room"
msgstr "Чат комната"
msgstr "Чат"
#: plinth/modules/matrixsynapse/manifest.py:105
msgid "Matrix server"
msgstr "Matrix сервер"
msgstr "Cервер Matrix"
#: plinth/modules/matrixsynapse/templates/matrix-synapse-pre-setup.html:18
msgid ""
@ -4512,7 +4514,7 @@ msgid ""
"Anyone with a link to this wiki can read it. Only users that are logged in "
"can make changes to the content."
msgstr ""
"Кто угодно, имея ссылку на wiki, может читать её. Только зарегистрированные "
"Кто угодно, имея ссылку на вики, может читать её. Только зарегистрированные "
"пользователи могут вносить изменения."
#: plinth/modules/mediawiki/__init__.py:51
@ -4542,7 +4544,7 @@ msgid ""
"feeds and emails. Examples: \"myfreedombox.example.org\" or "
"\"example.onion\"."
msgstr ""
"Использовалось MediaWiki для создания ссылок на wiki страницы, например "
"Использовалось MediaWiki для создания ссылок на вики страницы, например "
"внизу веб-страниц, в RSS-потоках или в электронных письмах. Например: "
"\"myfreedombox.example.org\" или \"example.onion\"."
@ -4709,7 +4711,7 @@ msgstr "Игровой сервер"
#: plinth/modules/minetest/manifest.py:49
msgid "Block sandbox"
msgstr "Блокировать песочницу"
msgstr "Песочница"
#: plinth/modules/minetest/manifest.py:49
msgid "Platform"
@ -4772,7 +4774,7 @@ msgstr "totem"
#: plinth/modules/minidlna/manifest.py:116
msgid "Media server"
msgstr "Медиа сервер"
msgstr "Медиасервер"
#: plinth/modules/minidlna/manifest.py:116
msgid "Television"
@ -4877,7 +4879,7 @@ msgstr "RSS Охранник"
#: plinth/modules/miniflux/manifest.py:138
msgid "Feed reader"
msgstr "Устройство для чтения фидов"
msgstr "Ленты новостей"
#: plinth/modules/miniflux/manifest.py:138
msgid "News aggregation"
@ -5227,7 +5229,7 @@ msgstr ""
#: plinth/modules/names/templates/names.html:152 plinth/templates/setup.html:87
msgid "Install"
msgstr "Установка"
msgstr "Установить"
#: plinth/modules/names/templates/names.html:162
msgid "Error retrieving status:"
@ -7248,10 +7250,10 @@ msgid ""
"from an email client, including MIME support, address book, folder "
"manipulation, message searching and spell checking."
msgstr ""
"Roundcube webmail это основанный на браузере многоязычный IMAP клиент с "
"пользовательским интерфейсом. Это предоставляет полную функциональность, "
"которую вы ожидаете от почтового клиента, включая поддержку MIME, адресную "
"книгу, управление папками, поиск сообщений и проверку орфографии."
"Веб-почта Roundcube это браузерный многоязычный IMAP клиент с "
"пользовательским интерфейсом. Он предоставляет полную функциональность, "
"которую вы ожидаете от почтового клиента, включая поддержку MIME, адресной "
"книги, управления папками, поиска сообщений и проверки орфографии."
#: plinth/modules/roundcube/__init__.py:24
msgid ""
@ -7303,7 +7305,7 @@ msgstr ""
#: plinth/modules/roundcube/manifest.py:23
msgid "Email"
msgstr "Email"
msgstr "Электронная почта"
#: plinth/modules/rssbridge/__init__.py:21
msgid ""
@ -7319,9 +7321,8 @@ msgid ""
"When enabled, RSS-Bridge can be accessed by <a href=\"{users_url}\">any "
"user</a> belonging to the feed-reader group."
msgstr ""
"Когда эта функция включена, доступ к RSS-мостику может получить <a "
"href=\"{users_url}\">любой пользователь</a>, входящий в группу читателей "
"фидов."
"Когда эта функция включена, доступ к RSS-Bridge может получить <a href="
"\"{users_url}\">любой пользователь</a>, входящий в группу читателей фидов."
#: plinth/modules/rssbridge/__init__.py:28
#, python-brace-format
@ -7330,10 +7331,10 @@ msgid ""
"href=\"{nextcloud_url}\">Nextcloud News</a> to follow various websites. When "
"adding a feed, enable authentication and use your {box_name} credentials."
msgstr ""
"Вы можете использовать RSS-мост с <a href=\"{miniflux_url}\">Miniflux</a> or "
"<a href=\"{nextcloud_url}\">Nextcloud News</a> следить за различными веб-"
"сайтами. При добавлении фида включите аутентификацию и используйте свои "
"учетные данные от {box_name}."
"Вы можете использовать RSS-Bridge с <a href=\"{miniflux_url}\">Miniflux</a> "
"или <a href=\"{nextcloud_url}\">Nextcloud News</a>, чтобы следить за "
"различными веб-сайтами. При добавлении фида включите аутентификацию и "
"используйте свои учетные данные от {box_name}."
#: plinth/modules/rssbridge/__init__.py:49
msgid "Read and subscribe to news feeds"
@ -7342,7 +7343,7 @@ msgstr "Чтение и подписка на ленты новостей"
#: plinth/modules/rssbridge/__init__.py:52
#: plinth/modules/rssbridge/manifest.py:7
msgid "RSS-Bridge"
msgstr "RSS-мост"
msgstr "RSS-Bridge"
#: plinth/modules/rssbridge/forms.py:12 plinth/modules/searx/forms.py:17
msgid "Allow Public Access"
@ -7354,7 +7355,7 @@ msgstr "Разрешите использовать это приложение
#: plinth/modules/rssbridge/manifest.py:16
msgid "Feed generator"
msgstr "Генератор питания"
msgstr "Генератор лент новостей"
#: plinth/modules/rssbridge/manifest.py:16
msgid "News"
@ -7435,11 +7436,11 @@ msgstr "Сетевой диск"
#: plinth/modules/samba/manifest.py:84
msgid "Media storage"
msgstr "Хранение носителей"
msgstr "Хранилище медиафайлов"
#: plinth/modules/samba/manifest.py:85
msgid "Backup storage"
msgstr "Резервное хранение"
msgstr "Резервное хранилище"
#: plinth/modules/samba/templates/samba.html:20
msgid "Shares"
@ -7580,7 +7581,7 @@ msgstr "Строгий"
#: plinth/modules/searx/manifest.py:17
msgid "Web search"
msgstr "Веб поиск"
msgstr "Веб-поиск"
#: plinth/modules/searx/manifest.py:17
msgid "Metasearch Engine"
@ -7735,7 +7736,7 @@ msgstr ""
#: plinth/modules/shaarli/__init__.py:36 plinth/modules/shaarli/manifest.py:25
msgid "Shaarli"
msgstr "Shаarli"
msgstr "Shaarli"
#: plinth/modules/shaarli/manifest.py:12
msgid "Shaarlier"
@ -7799,7 +7800,7 @@ msgstr ""
#: plinth/modules/shadowsocks/__init__.py:50
msgid "Shadowsocks Client"
msgstr "Клиент Shadowsocks"
msgstr "Shadowsocks Клиент"
#: plinth/modules/shadowsocks/forms.py:25
msgid "Server hostname or IP address"
@ -7846,7 +7847,7 @@ msgstr ""
#: plinth/modules/shadowsocksserver/__init__.py:47
msgid "Shadowsocks Server"
msgstr "Сервер Shadowsocks"
msgstr "Shadowsocks Сервер"
#: plinth/modules/shadowsocksserver/forms.py:10
#: plinth/modules/shadowsocksserver/forms.py:11
@ -7865,7 +7866,7 @@ msgstr "Метод шифрования. Клиенты должны испол
#: plinth/modules/shadowsocksserver/manifest.py:20
msgid "Exit point"
msgstr "Место выхода"
msgstr "Точка выхода"
#: plinth/modules/sharing/__init__.py:17
#, python-brace-format
@ -7926,7 +7927,7 @@ msgstr ""
#: plinth/modules/sharing/manifest.py:19 plinth/modules/zoph/manifest.py:26
msgid "Web sharing"
msgstr "Совместное использование веб-страниц"
msgstr "Обмен в Интернете"
#: plinth/modules/sharing/templates/sharing.html:18
#: plinth/modules/sharing/templates/sharing.html:21
@ -8263,7 +8264,7 @@ msgstr "Коннектор Thunderbird + SOGo"
#: plinth/modules/sogo/manifest.py:71
msgid "Webmail"
msgstr "Webmail"
msgstr "Веб-почта"
#: plinth/modules/sogo/manifest.py:74
msgid "Address book"
@ -8276,14 +8277,14 @@ msgid ""
"administration tasks, copy files or run other services using such "
"connections."
msgstr ""
"Secure Shell сервер использует протокол безопасной оболочки на прием "
"подключений с удаленных компьютеров. Уполномоченный удаленный компьютер "
"может выполнять задачи администрирования, копировать файлы или запускать "
"другие службы с использованием таких соединений."
"SSH-сервер использует протокол безопасной оболочки на прием подключений с "
"удаленных компьютеров. Уполномоченный удаленный компьютер может выполнять "
"задачи администрирования, копировать файлы или запускать другие службы с "
"использованием таких соединений."
#: plinth/modules/ssh/__init__.py:42
msgid "Secure Shell Server"
msgstr "Сервер защищенной оболочки"
msgstr "SSH-сервер"
#: plinth/modules/ssh/__init__.py:75
msgid "Remotely login using Secure Shell (SSH)"
@ -8365,7 +8366,7 @@ msgstr "Перейдите к входу в систему"
#: plinth/modules/sso/templates/login.html:23
msgid "Login"
msgstr "Логин"
msgstr "Войти"
#: plinth/modules/sso/views.py:86
msgid "Logged out successfully."
@ -8752,7 +8753,7 @@ msgstr "Цифровой сад"
#: plinth/modules/tiddlywiki/manifest.py:24
msgid "Zettelkasten"
msgstr "Шкафы для застройки"
msgstr "Цеттелькастен"
#: plinth/modules/tiddlywiki/templates/tiddlywiki_delete.html:18
msgid ""
@ -8920,15 +8921,15 @@ msgstr "Orbot: Прокси с Tor"
#: plinth/modules/tor/manifest.py:57
msgid "Onion services"
msgstr "Луковые сервисы"
msgstr "Onion-сервисы"
#: plinth/modules/tor/manifest.py:58
msgid "Relay"
msgstr "Ретранслятор"
msgstr "Сетевой узел"
#: plinth/modules/tor/manifest.py:59 plinth/modules/torproxy/manifest.py:56
msgid "Anonymity network"
msgstr "Сеть анонимности"
msgstr "Анонимная сеть"
#: plinth/modules/tor/templates/tor.html:23
msgid "Onion Service"
@ -9085,7 +9086,7 @@ msgstr ""
#: plinth/modules/upgrades/__init__.py:146
#: plinth/modules/upgrades/__init__.py:309
msgid "Software Update"
msgstr "Обновление программного обеспечения"
msgstr "Обновление ПО"
#: plinth/modules/upgrades/__init__.py:131
msgid "FreedomBox Updated"
@ -9282,7 +9283,7 @@ msgstr "Перейти к обновлению дистрибутива"
#: plinth/templates/notifications.html:58
#: plinth/templates/operation-notification.html:23
msgid "Dismiss"
msgstr "Отклонить"
msgstr "Закрыть"
#: plinth/modules/upgrades/templates/upgrades-dist-upgrade.html:15
#, python-format
@ -9585,8 +9586,8 @@ msgstr "Имя пользователя уже занято."
msgid ""
"Optional. Used to send emails to reset password and important notifications."
msgstr ""
"Необязательно. Используется для отправки электронных писем для сброса пароля "
"и важных уведомлений."
"Необязательное поле. Используется для отправки электронных писем для сброса "
"пароля и важных уведомлений."
#: plinth/modules/users/forms.py:107
msgid ""
@ -9610,7 +9611,8 @@ msgstr "Введите действительное имя пользовате
msgid ""
"Required. 150 characters or fewer. English letters, digits and @/./-/_ only."
msgstr ""
"Требуется. 150 символов или меньше. Только английские буквы, цифры и @/./-/_."
"Поле обязательно для заполнения. 150 символов или меньше. Только английские "
"буквы, цифры и @/./-/_."
#: plinth/modules/users/forms.py:141
msgid "Authorization Password"
@ -9796,8 +9798,8 @@ msgid ""
"Use the <a href='%(change_password_url)s'>change password form </a> to "
"change the password."
msgstr ""
"Для смены пароля используйте форму <a "
"href=\"%(change_password_url)s\">изменить пароль </a>."
"Для смены пароля используйте форму <a href=\"%(change_password_url)s\""
">изменить пароль</a>."
#: plinth/modules/users/templates/users_update.html:37
#: plinth/templates/language-selection.html:17
@ -10554,7 +10556,7 @@ msgstr ""
#: plinth/templates/base.html:117
msgid " Home"
msgstr " Домой"
msgstr " Главная"
#: plinth/templates/base.html:125
msgid " Apps"
@ -10687,7 +10689,7 @@ msgstr "Уведомления"
#: plinth/templates/notifications.html:18
#, python-format
msgid "%(time_since)s ago"
msgstr "%(time_since)s тому назад"
msgstr "%(time_since)s назад"
#: plinth/templates/port-forwarding-info.html:8
msgid "Port Forwarding"
@ -10820,7 +10822,7 @@ msgstr ""
#: plinth/views.py:89
msgid "Here"
msgstr "Вот здесь"
msgstr "Здесь"
#: plinth/views.py:431
msgid "Setting unchanged"

View File

@ -8,7 +8,7 @@ from plinth.tests import functional
pytestmark = [pytest.mark.apps, pytest.mark.homeassistant]
class TestHomeAssitantApp(functional.BaseAppTests):
class TestHomeAssistantApp(functional.BaseAppTests):
"""Basic tests for Home Assistant app."""
app_name = 'homeassistant'
has_service = True

View File

@ -104,10 +104,10 @@
<h3>{% trans "Manual Update" %}</h3>
{% if is_busy %}
<div class="btn-toolbar">
<button type="button" disabled="disabled"
class="running-status-parent btn btn-default" >
<span class="running-status loading"></span>
{% trans "Updating..." %}
<button type="button" class="btn btn-default" disabled="disabled">
<span class="spinner-border spinner-border-sm" aria-hidden="true">
</span>
<span role="status">{% trans "Updating..." %}</span>
</button>
</div>
{% else %}

View File

@ -43,10 +43,11 @@
</section>
{% if app_info.tags %}
<div class="app-tags">
<div class="app-tags d-flex align-items-center flex-wrap">
{% for tag in app_info.tags %}
{% if not forloop.first %}•{% endif %}
<a href="{{ active_section_url }}?tag={{ tag|urlencode }}"
class="btn btn-light rounded-pill tag">
class="btn btn-default rounded-pill tag">
{% trans tag %}
</a>
{% endfor %}

View File

@ -58,6 +58,9 @@
<link rel="stylesheet" href="{% static user_css %}"/>
{% endif %}
<!-- This script is not loaded in defer mode because it needs to run before
page is rendered -->
<script type="text/javascript" src="{% static 'theme/js/color-modes.js' %}"></script>
<!-- Local link to system Bootstrap JS -->
<script type="text/javascript" src="{% static '/javascript/popperjs2/popper.min.js' %}" defer></script>
<script type="text/javascript" src="{% static '/javascript/bootstrap5/js/bootstrap.bundle.min.js' %}" defer></script>
@ -148,6 +151,8 @@
{% include "notifications-dropdown.html" %}
{% include "theme-menu.html" %}
{% include "help-menu.html" %}
<li id="id_user_menu" class="nav-item dropdown">

View File

@ -8,12 +8,12 @@
<div class="container">
<div class="dropdown searchable-dropdown">
<div class="tag-input">
<div id="selected-tags">
<div id="selected-tags" class="d-flex align-items-center flex-wrap">
{% for tag in tags %}
<span class="btn btn-light rounded-pill tag"
<span class="btn btn-default rounded-pill tag d-flex align-items-center"
data-tag="{{ tag }}">
{% trans tag %}
<button class="btn btn-sm btn-light remove-tag">
<button class="btn btn-sm btn-default remove-tag">
<i class="fa fa-times"></i>
</button>
</span>

View File

@ -0,0 +1,46 @@
{% comment %}
# SPDX-License-Identifier: AGPL-3.0-or-later
{% endcomment %}
{% load i18n %}
<li id="id_theme_menu" class="dropdown nav-item">
<a href="#" title="{% trans "Toggle theme (auto)" %}"
class="nav-link dropdown-toggle" data-bs-toggle="dropdown"
role="button" aria-expanded="false" aria-haspopup="true"
id="id_theme_menu_link">
<span class="fa fa-adjust nav-icon" id="id_active_theme_icon"></span>
<span class="nav-text d-md-none" id="id_toggle_theme_text">
{% trans "Toggle theme" %}
</span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="id_theme_menu_link">
<li>
<button type="button" class="dropdown-item d-flex align-items-center"
data-bs-theme-value="light" data-bs-icon-value="fa-sun"
aria-pressed="false">
<span class="fa fa-sun nav-icon me-2"></span>
{% trans "Light" %}
<span class="fa fa-check nav-icon ms-auto d-none"></span>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center"
data-bs-theme-value="dark" data-bs-icon-value="fa-moon"
aria-pressed="false">
<span class="fa fa-moon nav-icon me-2"></span>
{% trans "Dark" %}
<span class="fa fa-check nav-icon ms-auto d-none"></span>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center"
data-bs-theme-value="auto" data-bs-icon-value="fa-adjust"
aria-pressed="true">
<span class="fa fa-adjust nav-icon me-2"></span>
{% trans "Auto" %}
<span class="fa fa-check nav-icon ms-auto d-none"></span>
</button>
</li>
</ul>
</li>

View File

@ -6,14 +6,13 @@
--neutral-light-color: #f5f5f5; /* Light grey */
--freedombox-blue-color: #4989D4; /* Blue */
--progress-color: #3498db; /* Blue */
--freedombox-form-disabled-bg-color: #e9ecef; /* Grey */
--freedombox-navbar-color: white;
--freedombox-navbar-shadow-color: rgba(0, 0, 0, 0.25);
--freedombox-toggle-button-bg: #ccc;
}
/* Missing variables in Bootstrap 5.2 copied from Bootstrap 5.3 */
--bs-secondary-bg: #e9ecef;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
--bs-secondary-border-subtle: #c4c8cb;
[data-bs-theme="dark"] {
--freedombox-toggle-button-bg: #888;
}
/*
@ -50,20 +49,20 @@ h6:not(:first-child) {
/* Default style removed in bootstrap 4 */
.btn-default {
--bs-btn-color: #333;
--bs-btn-bg: #fff;
--bs-btn-border-color: #ccc;
--bs-btn-hover-color: #333;
--bs-btn-hover-bg: #e6e6e6;
--bs-btn-hover-border-color: #adadad;
--bs-btn-color: var(--bs-body-color);
--bs-btn-bg: var(--bs-body-bg);
--bs-btn-border-color: var(--bs-tertiary-color);
--bs-btn-hover-color: var(--bs-body-color);
--bs-btn-hover-bg: var(--bs-secondary-bg);
--bs-btn-hover-border-color: var(--bs-tertiary-color);
--bs-btn-focus-shadow-rgb: 192, 192, 192;
--bs-btn-active-color: #333;
--bs-btn-active-bg: #e6e6e6;
--bs-btn-active-border-color: #adadad;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #333;
--bs-btn-disabled-bg: #e6e6e6;
--bs-btn-disabled-border-color: #adadad;
--bs-btn-active-color: var(--bs-body-color);
--bs-btn-active-bg: var(--bs-secondary-bg);
--bs-btn-active-border-color: var(--bs-tertiary-color);
--bs-btn-active-shadow: inset 0 3px 5px var(--bs-border-color-translucent);
--bs-btn-disabled-color: var(--bs-body-color);
--bs-btn-disabled-bg: var(--bs-secondary-bg);
--bs-btn-disabled-border-color: var(--bs-tertiary-color);
}
/* Help block removed from bootstrap 4, needs updated django-bootstrap-from */
@ -71,7 +70,7 @@ h6:not(:first-child) {
display: block;
margin-top: 0.3125rem;
margin-bottom: 0.625rem;
color: var(--bs-secondary);
color: var(--bs-secondary-color);
}
/* .close was renamed to .alert-dismissable.btn-close in Bootstrap 5, needs
@ -99,7 +98,7 @@ form .alert .close {
/* Disabled form elements show as gray, removed in Bootstrap 5 */
.form-control:disabled, .form-control[readonly] {
background-color: var(--freedombox-form-disabled-bg-color);
background-color: var(--bs-secondary-bg);
opacity: 1;
}
@ -228,28 +227,6 @@ body {
vertical-align: middle;
}
.running-status-parent {
display: inline-block;
}
.running-status {
border-radius: 50%;
border: 1px solid black;
width: 0.5rem;
height: 0.5rem;
display: inline-block;
}
.running-status.loading {
border: 0.25rem solid var(--neutral-light-color);
border-top: 0.25rem solid var(--progress-color);
border-radius: 50%;
width: 1rem;
height: 1rem;
display: inline-block;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
@ -314,16 +291,21 @@ html {
/* Tags */
.tag {
--bs-btn-padding-y: 0.25rem; /* Make the badge shorter */
border-style: none;
}
#selected-tags .tag {
border-style: solid;
}
/* Tag Input Container */
.tag-input {
display: flex;
align-items: center;
border: 1px solid #ced4da;
border: 1px solid var(--bs-border-color);
border-radius: .25rem;
padding: .375rem .75rem;
background-color: #fff;
background-color: var(--bs-body-bg);
margin-bottom: 2rem;
}
@ -472,7 +454,7 @@ footer {
*/
.main-header {
background: var(--freedombox-blue-color);
box-shadow: 0 0.25rem 0.375rem 0 rgba(0, 0, 0, 0.25);
box-shadow: 0 0.25rem 0.375rem 0 var(--freedombox-navbar-shadow-color);
border: none;
}
@ -522,6 +504,10 @@ footer {
border-bottom: var(--freedombox-navbar-color) 3px solid;
}
.main-header .dropdown-menu .active .fa-check {
display: block !important;
}
/* Breadcrumbs */
.breadcrumb-item {
--bs-breadcrumb-divider: ">";
@ -584,7 +570,7 @@ footer {
.card-tags {
font-weight: 400;
color: var(--bs-secondary);
color: var(--bs-secondary-color);
font-size: 0.875rem;
/* Show ellipsis after 3 lines. */
@ -711,9 +697,9 @@ footer {
border-radius: 0.8125rem;
width: 3.125rem;
height: 1.625rem;
background: #ccc;
--bs-btn-hover-bg: #ccc;
--bs-btn-disabled-bg: #ccc;
background: var(--freedombox-toggle-button-bg);
--bs-btn-hover-bg: var(--freedombox-toggle-button-bg);
--bs-btn-disabled-bg: var(--freedombox-toggle-button-bg);;
--bs-btn-disabled-border-color: transparent;
position: relative;
}
@ -724,7 +710,7 @@ footer {
height: 1.5rem;
width: 1.5rem;
border-radius: 100%;
background: #fff;
background: var(--bs-body-bg);
position: absolute;
top: 50%;
left: 0%;
@ -744,8 +730,8 @@ footer {
.toggle-button.running-status-button::before {
top: 0;
border: 0.25rem solid var(--neutral-light-color);
border-top: 0.25rem solid var(--progress-color);
border: 0.25rem solid var(--bs-body-bg);
border-top-color: var(--freedombox-blue-color);
animation: spin 1s linear infinite;
}
@ -758,8 +744,8 @@ footer {
*/
.running-status-button-before {
display: inline-block;
border: 0.25rem solid var(--neutral-light-color);
border-top: 0.25rem solid var(--progress-color);
border: 0.25rem solid var(--bs-btn-color);
border-top-color: transparent;
border-radius: 50%;
width: 1rem;
height: 1rem;
@ -767,6 +753,8 @@ footer {
margin-left: 0.625rem;
margin-bottom: -0.25rem;
margin-right: -1.625rem;
position: relative;
z-index: 10;
}
.running-status-button:disabled {
@ -782,7 +770,7 @@ input[type='submit'].running-status-button {
*/
.select-all-label {
border: 1px solid var(--bs-secondary-border-subtle);
background-color: var(--neutral-light-color);
background-color: var(--bs-tertiary-bg);
border-radius: 0.25rem;
padding: 0.5rem 1rem 0.25rem;
margin-left: -1rem;

View File

@ -0,0 +1,96 @@
// SPDX-License-Identifier: CC-BY-3.0
/*
This file is part of FreedomBox. Color mode toggler for Bootstrap's docs
(https://getbootstrap.com/). Copyright 2011-2025 The Bootstrap Authors.
@licstart The following is the entire license notice for the
JavaScript code in this page.
Licensed under the Creative Commons Attribution 3.0 Unported License.
@licend The above is the entire license notice
for the JavaScript code in this page.
*/
(() => {
'use strict';
const getStoredTheme = () => localStorage.getItem('theme');
const setStoredTheme = theme => localStorage.setItem('theme', theme);
const getBrowserTheme = () => {
return window.matchMedia('(prefers-color-scheme: dark)')
.matches ? 'dark' : 'light';
};
const getPreferredTheme = () => {
const storedTheme = getStoredTheme();
if (storedTheme) {
return storedTheme;
}
return getBrowserTheme();
};
const setTheme = (theme) => {
if (theme === 'auto') {
theme = getBrowserTheme();
}
document.documentElement.setAttribute('data-bs-theme', theme);
};
setTheme(getPreferredTheme());
const showActiveTheme = (theme, focus = false) => {
const themeSwitcher = document.querySelector('#id_theme_menu_link');
if (!themeSwitcher) {
return;
}
const themeSwitcherText = document.querySelector('#id_toggle_theme_text');
const activeThemeIcon = document.querySelector('#id_active_theme_icon');
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`);
const iconOfActiveBtn = btnToActive.dataset.bsIconValue;
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active');
element.setAttribute('aria-pressed', 'false');
const iconOfBtn = element.dataset.bsIconValue;
if (activeThemeIcon.classList.contains(iconOfBtn)) {
activeThemeIcon.classList.remove(iconOfBtn);
}
});
btnToActive.classList.add('active');
btnToActive.setAttribute('aria-pressed', 'true');
activeThemeIcon.classList.add(iconOfActiveBtn);
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`;
themeSwitcher.setAttribute('title', themeSwitcherLabel);
if (focus) {
themeSwitcher.focus();
};
};
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
const storedTheme = getStoredTheme();
if (storedTheme !== 'light' && storedTheme !== 'dark') {
setTheme(getPreferredTheme());
}
});
window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme());
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value');
setStoredTheme(theme);
setTheme(theme);
showActiveTheme(theme, true);
});
});
});
})();

View File

@ -85,6 +85,11 @@ function onSubmitAddProgress(event) {
// For push buttons
const beforeElement = document.createElement('div');
beforeElement.classList.add('running-status-button-before');
button.classList.forEach(className => {
if (className.startsWith('btn-')) {
beforeElement.classList.add(className);
}
});
button.parentNode.insertBefore(beforeElement, button);
} else if (button.tagName == "BUTTON") {
// For toggle buttons