Оформление и языки

Ребрендинг — это одно число. Одиннадцать языков поставляются в пакете, один из них — с письмом справа налево, и настраивать для этого ничего не нужно.

Доступно с версии v0.1.0

Палитра — это одно число

Весь цвет админки выводится из одного оттенка (hue) в OKLCH. Нет ни шага сборки, ни таблицы стилей, которую нужно форкать.

FastFortSettings(
    ui={"accent_hue": 232, "accent_chroma": 0.15},
)

accent_hue — от 0 до 360; accent_chroma — от 0 до 0.37. Каждый акцент, граница, кольцо фокуса, состояние наведения и тень выводятся из этих двух значений — в обеих темах.

OKLCH выбран вместо HSL потому, что при осветлении образца в OKLCH сохраняется его хрома (chroma) — тогда как градиент в HSL смещается к серому на светлом конце, из-за чего вручную подобранные палитры превращаются в сорок HEX-значений, которые приходится поддерживать согласованно.

Темы

ui={"theme": "system", "density": "comfortable"}

system · light · dark, а также comfortable · compact. system — значение по умолчанию, следует настройке браузера; посетитель может переопределить её прямо в шапке админки, и выбор сохраняется.

Флаг, определяющий, какая тема применяется, выставляется boot.js — единственным скриптом, который выполняется до первой отрисовки. Сделать это где-либо позже — значит опоздать на кадр, а опоздание на кадр — это заметная вспышка неверной палитры при каждом переходе.

Собственный CSS

ui={"custom_css_url": "/static/admin-overrides.css"}

Загружается после встроенной таблицы стилей, которая состоит из семи каскадных слоёв (00-reset … 06-widgets), объединённых в один ответ. Ваш файл оказывается после всех них, поэтому обычный селектор побеждает без !important.

Редактор форматированного текста

ui={"richtext_url": "https://cdn.example.com/ckeditor.js"}

FastFort рендерит textarea и помечает её data-ff-richtext; это имя скрипта, который их находит. None оставляет обычный textarea — рабочий элемент управления вместо сломанного редактора.

Альтернативой было бы включить редактор в пакет, но это неверный компромисс: полмегабайта редактора в wheel для каждого проекта, большинству из которых нужен другой редактор или вообще никакой. Если URL находится на другом источнике, этот источник добавляется в script-src CSP — именно поэтому это настройка, а не то, что можно внедрить из шаблона.

Метки окружения

ui={"environment_label": "PRODUCTION", "environment_tone": "danger"}

Отображается в шапке в тоне info, warning или danger. Поэтому разница между двумя открытыми у кого-то окнами видна без чтения.

Логотип и favicon

ui={"logo_url": "/static/logo.svg", "favicon_url": "/static/favicon.png"}

Языки

Одиннадцать каталогов поставляются внутри wheel: английский, узбекский, русский, турецкий, немецкий, французский, испанский, китайский, японский, корейский и арабский.

Настраивать нечего. Админка уже переведена в момент установки и по умолчанию следует заголовку браузера Accept-Language.

ui={"language": None}      # follow the browser — the default
ui={"language": "uz"}      # pin every visitor to one language

None выбран значением по умолчанию намеренно: проект, которому нужна админка на одном языке независимо от того, кто её открывает, должен заявить об этом явно — а не молча закреплять всех на английском.

Арабский разворачивает раскладку

Таблица стилей полностью написана с использованием логических свойств — inset-inline-start, а не left; padding-inline, а не padding-left. Один атрибут dir разворачивает всю админку: боковую панель, выравнивание таблиц, разделители хлебных крошек, стрелки сортировки.

Тест подсчитывает физические направления в таблице стилей и падает, как только появляется новое. Есть ровно два намеренных исключения: галочка чекбокса (галочка — она и есть галочка на любом языке) и карта, которая является координатным пространством, размещаемым скриптом в физических пикселях.

Перевод ваших собственных слов

FastFort переводит свой собственный интерфейс — кнопки, фильтры, сообщения. Он не переводит названия ваших моделей, и verbose_name не проходит через каталог. Название модели — это ваше слово для вашей предметной области, и угадывать его на одиннадцати языках — не то, что должен пытаться делать фреймворк. Django тоже не переводит названия ваших моделей.

Для собственных строк:

ui={"locale_dir": "app/locale"}

Каталог с файлами <language>.json, записи которых имеют приоритет над собственными строками FastFort.

{
  "Products": "Mahsulotlar",
  "Shipments": "Jo'natmalar",
  "Mark discontinued": "Ishlab chiqarishdan olindi deb belgilash"
}

Строки, которые рисует скрипт на стороне браузера

Всё, что виджет рисует сам — названия месяцев в календаре, подписи элемента управления длительностью, плейсхолдер командной палитры — это строка, которую отправляет сервер через атрибуты data-ff-t-* на <html>.

Скрипт — это один кэшируемый файл для всех языков, поэтому он никогда не может содержать видимый пользователю английский текст. Тест сравнивает таблицу запасных значений скрипта с серверной, потому что расхождение оставляет один элемент управления на английском во всех языках, и при этом ничего не падает.

Часовой пояс

ui={"timezone": "Asia/Tashkent"}

Дата и время хранятся как обычно и отображаются в этом часовом поясе.