Задача
Добавить английский язык в интерфейс настройки Ватериуса. Ниже — исследование трудоёмкости по текущему коду (ветка dev, прошивка 2.0.46).
Старая просьба от пользователя: #13 (2018, закрыт без реализации).
Главный вывод
Задача небольшая и хорошо локализованная. Весь русский текст, который видит пользователь, лежит в LittleFS (ESP8266/data/) — ~190 уникальных строк, ~800 слов, 12,3 КБ. Прошивка на C++ уже полностью англоязычная.
Оценка: ~1,5–2 дня работы + перевод ~800 слов + перерисовка 8 картинок.
Английский интерфейс доставляется пользователям отдельным OTA-обновлением файловой системы, без перепрошивки кода (ota_parse.h, ota_update.cpp:59-87).
Что уже готово в коде
1. Прошивка языконезависима. В src/ha/resources.h — "Cold Water", "Voltage Battery", "Sleep Period"; CHANNEL_NAMES, MODEL_NAMES, ключи JSON в json.cpp — всё латиница. Кириллицы в Home Assistant discovery, MQTT-payload и JSON на сервер — ноль.
Единственная кириллица в литералах C++ — 7 строк в src/portal/resources.h:55-61, и они уходят только в LOG_ERROR, в релизной сборке не видны.
2. Сервер уже отдаёт коды, а не текст. active_point.cpp:296-306 возвращает "8"…"13" вместо сообщений о статусе Wi-Fi, active_point_api.cpp кладёт в errors числа "14"…"19". Текст подставляет браузер — tr(str_id) в data/static/strings.js:135-159. Слой «код ↔ текст» готов, его надо только сделать двухъязычным.
3. Есть заготовка. В шести страницах закомментирована ссылка <a href="/eng/start.html" class="lang fr">Eng</a> (index.html:23, about.html:21, captive_portal*.html:19), CSS-класс .lang живой — style.css:37.
Объём перевода
| Где |
Единиц |
Кириллицы |
19 HTML-страниц (текстовые узлы + title/placeholder) |
229 (150 уникальных) |
4 037 симв. |
data/static/strings.js — tr(), fill_title(), fill_instruction() |
36 литералов |
1 398 симв. |
data/static/common.js (строка 115) |
1 литерал |
19 симв. |
| Итого |
~190 уникальных, 667 слов в HTML |
6 131 симв. ≈ 12,3 КБ |
Остальные 37 466 кириллических символов в src/ — комментарии и changelog, в бинарник не попадают.
Почему дубликат дерева /eng/ не подходит
Свободное место в LittleFS, посчитано по блокам:
| Модель |
Размер ФС |
Блок |
Занято |
Свободно |
| esp01_1m (Classic, ESP-01) |
262 144 Б |
4 096 |
225 280 Б (55 блоков) |
36 864 Б |
| waterius_2 (ESP-12F) |
1 024 000 Б |
8 192 |
303 104 Б (37 блоков) |
720 896 Б |
Дубликат дерева — 19 новых файлов, то есть минимум 19 блоков = 77 824 Б на Classic. Не влезает вдвое. Плюс любая правка вёрстки делается в двух местах.
Словарь влезает: английский текст (1 байт/символ вместо 2) в отдельном файле — +12 КБ нетто.
Запас, если станет тесно: /static/ (common.js 14 КБ + strings.js 8 КБ + style.css 7,7 КБ) отдаётся через serveStatic (active_point.cpp:459-460), который умеет .gz автоматически — это отмечено в комментарии active_point.cpp:436. Сжатие этих трёх файлов сокращает 8 блоков до 3 и освобождает 20 480 Б на Classic.
Две ловушки, которые определяют архитектуру
1. В captive-портале iOS отключён JavaScript
Комментарий active_point.cpp:438: «SAFARI (IOS) popup browser has some severe limitations (javascript disabled, cookies disabled)». Это не теория — четыре страницы captive_portal*.html намеренно написаны без единого <script>, только style.css.
Значит перевод на JS их в iOS-попапе не достанет.
Лечится дёшево: on_root() (active_point.cpp:327-357) — четыре вызова request->send(LittleFS, "/captive_portal*.html", ...). Достаточно прочитать заголовок Accept-Language и подставить префикс пути. ~20 строк C++, язык определяется до того, как пользователь что-то нажал.
2. В картинках счётчиков зашита кириллица
На meter-cold-0.png подписи «ГВС» (красным) и «ХВС» (синим). Таких файлов 8 (meter-{cold,hot,electro,gas}-{0,1}.png, ~40 КБ) — нужна перерисовка. icons.png и tableau.png чистые (иконки и цифры).
Предлагаемое решение
Ключи в HTML + словарь, с русским как встроенным фолбэком. Текст в HTML остаётся на месте, рядом добавляется атрибут:
<p class="text" data-i18n="wifi_list.hint">Выберите сеть 2.4Ghz WiFi через которую…</p>
- при
lang=ru скрипт не делает ничего — русский путь физически не может сломаться, правки только аддитивные;
- при
lang=en текст подменяется по ключу;
- отсутствующий ключ молча оставляет русский;
- язык определяется по
navigator.language, запоминается в localStorage;
- переключатель — та самая ссылка
Eng, для которой уже есть стиль.
Поле языка в Settings не нужно — прошивка ничего не локализует, выбор живёт в браузере. Если понадобится хранить, в reserved9 свободно ~95 байт (прецеденты: ntp_sync_count, last_time_sync).
Смета
| Работа |
Объём |
Проставить data-i18n в 19 HTML |
229 атрибутов, скриптуется |
Рантайм: автоопределение, подстановка, переключатель, localStorage |
~80 строк JS |
Словарь en.js |
~190 строк, ~9 КБ |
strings.js → двухъязычный (tr() + fill_*) |
~40 строк правок |
4 captive-страницы через Accept-Language |
~20 строк C++ + 4 файла (16 КБ) |
| Проверка полноты словаря в CI |
~50 строк python |
gzip /static/ — компенсировать место на Classic |
~20 строк в сборке |
| Перерисовать 8 PNG (ГВС/ХВС → HW/CW) |
дизайн |
Риски
Главный риск — не объём, а проверка. У портала нет ни одного теста: хостовый харнесс собирает только src/core/ (build_src_filter = -<*> +<core/*>), вся вёрстка вне его. Проверять придётся руками на живом устройстве, обе модели, 19 страниц × 2 языка, включая мастер первичной настройки.
Скрипт-сверка ключей в CI ловит только пропущенные строки, но не поехавшую вёрстку: английские фразы бывают длиннее русских, и кнопки с <label> в узкой мобильной раскладке могут переноситься.
Открытый вопрос
Английский нужен только в интерфейсе настройки, или ещё в письмах / личном кабинете / телеграм-боте? Если шире — это другие репозитории и другая смета.
Задача
Добавить английский язык в интерфейс настройки Ватериуса. Ниже — исследование трудоёмкости по текущему коду (ветка
dev, прошивка 2.0.46).Старая просьба от пользователя: #13 (2018, закрыт без реализации).
Главный вывод
Задача небольшая и хорошо локализованная. Весь русский текст, который видит пользователь, лежит в LittleFS (
ESP8266/data/) — ~190 уникальных строк, ~800 слов, 12,3 КБ. Прошивка на C++ уже полностью англоязычная.Оценка: ~1,5–2 дня работы + перевод ~800 слов + перерисовка 8 картинок.
Английский интерфейс доставляется пользователям отдельным OTA-обновлением файловой системы, без перепрошивки кода (
ota_parse.h,ota_update.cpp:59-87).Что уже готово в коде
1. Прошивка языконезависима. В
src/ha/resources.h—"Cold Water","Voltage Battery","Sleep Period";CHANNEL_NAMES,MODEL_NAMES, ключи JSON вjson.cpp— всё латиница. Кириллицы в Home Assistant discovery, MQTT-payload и JSON на сервер — ноль.Единственная кириллица в литералах C++ — 7 строк в
src/portal/resources.h:55-61, и они уходят только вLOG_ERROR, в релизной сборке не видны.2. Сервер уже отдаёт коды, а не текст.
active_point.cpp:296-306возвращает"8"…"13"вместо сообщений о статусе Wi-Fi,active_point_api.cppкладёт вerrorsчисла"14"…"19". Текст подставляет браузер —tr(str_id)вdata/static/strings.js:135-159. Слой «код ↔ текст» готов, его надо только сделать двухъязычным.3. Есть заготовка. В шести страницах закомментирована ссылка
<a href="/eng/start.html" class="lang fr">Eng</a>(index.html:23,about.html:21,captive_portal*.html:19), CSS-класс.langживой —style.css:37.Объём перевода
title/placeholder)data/static/strings.js—tr(),fill_title(),fill_instruction()data/static/common.js(строка 115)Остальные 37 466 кириллических символов в
src/— комментарии и changelog, в бинарник не попадают.Почему дубликат дерева
/eng/не подходитСвободное место в LittleFS, посчитано по блокам:
Дубликат дерева — 19 новых файлов, то есть минимум 19 блоков = 77 824 Б на Classic. Не влезает вдвое. Плюс любая правка вёрстки делается в двух местах.
Словарь влезает: английский текст (1 байт/символ вместо 2) в отдельном файле — +12 КБ нетто.
Запас, если станет тесно:
/static/(common.js14 КБ +strings.js8 КБ +style.css7,7 КБ) отдаётся черезserveStatic(active_point.cpp:459-460), который умеет.gzавтоматически — это отмечено в комментарииactive_point.cpp:436. Сжатие этих трёх файлов сокращает 8 блоков до 3 и освобождает 20 480 Б на Classic.Две ловушки, которые определяют архитектуру
1. В captive-портале iOS отключён JavaScript
Комментарий
active_point.cpp:438: «SAFARI (IOS) popup browser has some severe limitations (javascript disabled, cookies disabled)». Это не теория — четыре страницыcaptive_portal*.htmlнамеренно написаны без единого<script>, толькоstyle.css.Значит перевод на JS их в iOS-попапе не достанет.
Лечится дёшево:
on_root()(active_point.cpp:327-357) — четыре вызоваrequest->send(LittleFS, "/captive_portal*.html", ...). Достаточно прочитать заголовокAccept-Languageи подставить префикс пути. ~20 строк C++, язык определяется до того, как пользователь что-то нажал.2. В картинках счётчиков зашита кириллица
На
meter-cold-0.pngподписи «ГВС» (красным) и «ХВС» (синим). Таких файлов 8 (meter-{cold,hot,electro,gas}-{0,1}.png, ~40 КБ) — нужна перерисовка.icons.pngиtableau.pngчистые (иконки и цифры).Предлагаемое решение
Ключи в HTML + словарь, с русским как встроенным фолбэком. Текст в HTML остаётся на месте, рядом добавляется атрибут:
lang=ruскрипт не делает ничего — русский путь физически не может сломаться, правки только аддитивные;lang=enтекст подменяется по ключу;navigator.language, запоминается вlocalStorage;Eng, для которой уже есть стиль.Поле языка в
Settingsне нужно — прошивка ничего не локализует, выбор живёт в браузере. Если понадобится хранить, вreserved9свободно ~95 байт (прецеденты:ntp_sync_count,last_time_sync).Смета
data-i18nв 19 HTMLlocalStorageen.jsstrings.js→ двухъязычный (tr()+fill_*)Accept-Language/static/— компенсировать место на ClassicРиски
Главный риск — не объём, а проверка. У портала нет ни одного теста: хостовый харнесс собирает только
src/core/(build_src_filter = -<*> +<core/*>), вся вёрстка вне его. Проверять придётся руками на живом устройстве, обе модели, 19 страниц × 2 языка, включая мастер первичной настройки.Скрипт-сверка ключей в CI ловит только пропущенные строки, но не поехавшую вёрстку: английские фразы бывают длиннее русских, и кнопки с
<label>в узкой мобильной раскладке могут переноситься.Открытый вопрос
Английский нужен только в интерфейсе настройки, или ещё в письмах / личном кабинете / телеграм-боте? Если шире — это другие репозитории и другая смета.