Add Dutch, German, French, Italian, Spanish, Portuguese and Polish with their calendars and Home Assistant's own words
tools/i18n.py gets cldr (day and month names, date orders, numbers and the clock from Node's Intl), ha-words (the words for states from Home Assistant's own translations, English included) and lint (English left in the firmware's code). The screens write numbers from Home Assistant in the chosen format, and every text font carries the apostrophe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -76,10 +76,7 @@ inline std::string number(float value, int decimals, const std::string &unit) {
|
||||
auto dot = text.find('.');
|
||||
std::string whole = text.substr(0, dot), rest = dot == std::string::npos ? "" : text.substr(dot);
|
||||
bool zero = whole.find_first_not_of('0') == std::string::npos && rest.find_first_not_of(".0") == std::string::npos;
|
||||
const std::string group = screen_text::group_mark();
|
||||
for (int i = static_cast<int>(whole.size()) - 3; i > 0; i -= 3) whole.insert(static_cast<size_t>(i), group);
|
||||
if (!rest.empty()) rest[0] = screen_text::decimal_mark();
|
||||
text = (zero ? "" : sign) + whole + rest;
|
||||
text = (zero ? "" : sign) + screen_text::write_number(whole, rest.empty() ? std::string() : rest.substr(1));
|
||||
if (unit.empty()) return text;
|
||||
if (unit == "%" || unit == "°") return text + unit;
|
||||
return text + " " + unit;
|
||||
|
||||
@@ -923,7 +923,7 @@ inline std::string detail_state(const Tile &t){
|
||||
if(!t.available())return tr(txt::tile_unavailable);
|
||||
// Home Assistant's word where the screen has none of its own (firmware 0.2.58+).
|
||||
if(!t.extra().state_word.empty())return t.extra().state_word;
|
||||
return t.state;
|
||||
return screen_text::localize(t.state);
|
||||
}
|
||||
inline void hide_detail(){if(detail_root)lv_obj_add_flag(detail_root,LV_OBJ_FLAG_HIDDEN);}
|
||||
inline int slider_value(const Tile &t){
|
||||
@@ -2545,9 +2545,10 @@ inline void render_clock(Widgets &w,const Tile &t,bool large,int width,int heigh
|
||||
}
|
||||
int x=dial+(large?10:6),room=std::max(1,width-x);
|
||||
if(!large){
|
||||
// Compact cards: "13 sep" in the large-value font beside the dial.
|
||||
// Compact cards: "13 sep" in the large-value font beside the dial, in the language's order (screen.date.day_month).
|
||||
const lv_font_t *font=watch_value_font?watch_value_font:w.value_font;
|
||||
part_label(w,16,font,x,std::max(0,int(height-lv_font_get_line_height(font))/2),room,LV_TEXT_ALIGN_CENTER,day+" "+month_short(now));
|
||||
part_label(w,16,font,x,std::max(0,int(height-lv_font_get_line_height(font))/2),room,LV_TEXT_ALIGN_CENTER,
|
||||
fill(fill(txt::date_day_month,"day",day),"month",month_short(now)));
|
||||
return;
|
||||
}
|
||||
// Calendar block: weekday over a big day number with the short month beside it.
|
||||
@@ -3139,7 +3140,8 @@ inline void render_slot(size_t slot) {
|
||||
else if (!t.extra().state_word.empty()) value = t.extra().state_word;
|
||||
// A player's state in the screen's own words where Home Assistant sent none (firmware 0.2.64+).
|
||||
else if (d == "media_player") value = tile_controls::media_state_text(t.state);
|
||||
else if (!t.unit.empty() && !watch) value += " " + t.unit;
|
||||
else if (!t.unit.empty() && !watch) value = screen_text::localize(value) + " " + t.unit;
|
||||
else value = screen_text::localize(value);
|
||||
bool pending=t.loading(esphome::millis());
|
||||
if(d=="weather" && std::isfinite(t.current)) {value=screen_text::decimal(t.current,1);if(!watch)value+=" "+t.unit;}
|
||||
if(d=="vacuum" && std::isfinite(t.battery))value += " / "+std::to_string((int)t.battery)+"%";
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// flash: no text is copied, searched for or kept in RAM, and a screen carries no language but its own.
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include "screen_text_keys.h"
|
||||
@@ -62,6 +63,36 @@ inline const char *group_mark() {
|
||||
if (number_style == 3) return " ";
|
||||
return tr(txt::number_group);
|
||||
}
|
||||
// How many digits a whole number needs before it gets separators: 4 ("1,234") in most languages, 5 in Italian, Spanish
|
||||
// and Polish, which write 1234 but 12.345 (CLDR's minimum grouping digits, as Home Assistant's own numbers do).
|
||||
inline size_t group_from() {
|
||||
if (number_style) return 4;
|
||||
int minimum = atoi(tr(txt::number_group_min));
|
||||
return minimum >= 2 ? 5 : 4;
|
||||
}
|
||||
// A number the way this screen writes numbers: `whole` digits (no sign) and the digits after the point.
|
||||
inline std::string write_number(const std::string &whole, const std::string &fraction) {
|
||||
std::string out = whole;
|
||||
if (out.size() >= group_from()) {
|
||||
const std::string group = group_mark();
|
||||
for (int i = static_cast<int>(out.size()) - 3; i > 0; i -= 3) out.insert(static_cast<size_t>(i), group);
|
||||
}
|
||||
if (!fraction.empty()) out += std::string(1, decimal_mark()) + fraction;
|
||||
return out;
|
||||
}
|
||||
// A state as Home Assistant sends a number ("1234.5", "-3") written the way this screen writes numbers ("1.234,5" in
|
||||
// Dutch); any other text as it is.
|
||||
inline std::string localize(const std::string &state) {
|
||||
size_t start = !state.empty() && state[0] == '-' ? 1 : 0, dot = std::string::npos;
|
||||
if (start == state.size()) return state;
|
||||
for (size_t i = start; i < state.size(); ++i) {
|
||||
if (state[i] == '.' && dot == std::string::npos && i > start && i + 1 < state.size()) dot = i;
|
||||
else if (state[i] < '0' || state[i] > '9') return state;
|
||||
}
|
||||
std::string whole = state.substr(start, dot == std::string::npos ? std::string::npos : dot - start);
|
||||
std::string fraction = dot == std::string::npos ? std::string() : state.substr(dot + 1);
|
||||
return state.substr(0, start) + write_number(whole, fraction);
|
||||
}
|
||||
// "point", "comma", "space" or "auto" as its number_style; -1 for anything else.
|
||||
inline int number_style_of(const std::string &name) {
|
||||
if (name == "auto") return 0;
|
||||
|
||||
@@ -8,272 +8,275 @@ namespace screen_text {
|
||||
namespace txt {
|
||||
constexpr uint16_t number_decimal = 0;
|
||||
constexpr uint16_t number_group = 1;
|
||||
constexpr uint16_t time_just_now = 2;
|
||||
constexpr uint16_t time_minutes_ago = 3;
|
||||
constexpr uint16_t time_hours_ago = 4;
|
||||
constexpr uint16_t time_yesterday = 5;
|
||||
constexpr uint16_t time_days_ago = 6;
|
||||
constexpr uint16_t time_weeks_ago = 7;
|
||||
constexpr uint16_t time_months_ago = 8;
|
||||
constexpr uint16_t time_years_ago = 9;
|
||||
constexpr uint16_t time_in_minutes = 10;
|
||||
constexpr uint16_t time_in_hours = 11;
|
||||
constexpr uint16_t time_tomorrow = 12;
|
||||
constexpr uint16_t time_in_days = 13;
|
||||
constexpr uint16_t time_am = 14;
|
||||
constexpr uint16_t time_pm = 15;
|
||||
constexpr uint16_t date_top_bar = 61;
|
||||
constexpr uint16_t date_full = 62;
|
||||
constexpr uint16_t date_day_month = 63;
|
||||
constexpr uint16_t date_weekday_time = 64;
|
||||
constexpr uint16_t duration_seconds = 65;
|
||||
constexpr uint16_t duration_minutes = 66;
|
||||
constexpr uint16_t duration_hours = 67;
|
||||
constexpr uint16_t duration_hours_minutes = 68;
|
||||
constexpr uint16_t duration_days = 69;
|
||||
constexpr uint16_t duration_days_hours = 70;
|
||||
constexpr uint16_t status_connecting = 71;
|
||||
constexpr uint16_t status_waiting = 72;
|
||||
constexpr uint16_t status_loading_tiles = 73;
|
||||
constexpr uint16_t status_ha_not_connected = 74;
|
||||
constexpr uint16_t status_manager_not_active = 75;
|
||||
constexpr uint16_t status_choose_tiles = 76;
|
||||
constexpr uint16_t status_home = 77;
|
||||
constexpr uint16_t status_no_network = 78;
|
||||
constexpr uint16_t settings_title = 79;
|
||||
constexpr uint16_t settings_brightness = 80;
|
||||
constexpr uint16_t settings_night = 81;
|
||||
constexpr uint16_t settings_screen = 82;
|
||||
constexpr uint16_t settings_this_screen = 83;
|
||||
constexpr uint16_t settings_dark_mode = 84;
|
||||
constexpr uint16_t settings_auto_standby = 85;
|
||||
constexpr uint16_t settings_standby_after = 86;
|
||||
constexpr uint16_t settings_standby_brightness = 87;
|
||||
constexpr uint16_t settings_night_mode = 88;
|
||||
constexpr uint16_t settings_starts = 89;
|
||||
constexpr uint16_t settings_ends = 90;
|
||||
constexpr uint16_t settings_night_brightness = 91;
|
||||
constexpr uint16_t settings_back_to_page_1 = 92;
|
||||
constexpr uint16_t settings_after = 93;
|
||||
constexpr uint16_t settings_also_on_standby = 94;
|
||||
constexpr uint16_t settings_swipe_between_pages = 95;
|
||||
constexpr uint16_t settings_page_buttons = 96;
|
||||
constexpr uint16_t settings_rotation = 97;
|
||||
constexpr uint16_t settings_address = 98;
|
||||
constexpr uint16_t settings_firmware = 99;
|
||||
constexpr uint16_t settings_home_assistant = 100;
|
||||
constexpr uint16_t settings_restart = 101;
|
||||
constexpr uint16_t settings_tap_again_to_restart = 102;
|
||||
constexpr uint16_t settings_seconds = 103;
|
||||
constexpr uint16_t settings_minutes = 104;
|
||||
constexpr uint16_t settings_hours = 105;
|
||||
constexpr uint16_t settings_hours_minutes = 106;
|
||||
constexpr uint16_t tile_tap_to_open = 107;
|
||||
constexpr uint16_t tile_page = 108;
|
||||
constexpr uint16_t tile_unavailable = 109;
|
||||
constexpr uint16_t tile_refused = 110;
|
||||
constexpr uint16_t tile_command_sent = 111;
|
||||
constexpr uint16_t tile_confirmed = 112;
|
||||
constexpr uint16_t alert_notification = 113;
|
||||
constexpr uint16_t alert_ok = 114;
|
||||
constexpr uint16_t light_color = 115;
|
||||
constexpr uint16_t light_color_temperature = 116;
|
||||
constexpr uint16_t light_brightness = 117;
|
||||
constexpr uint16_t light_waiting = 118;
|
||||
constexpr uint16_t effects_effect = 119;
|
||||
constexpr uint16_t effects_nothing = 120;
|
||||
constexpr uint16_t effects_loading = 121;
|
||||
constexpr uint16_t effects_not_connected = 122;
|
||||
constexpr uint16_t climate_target = 123;
|
||||
constexpr uint16_t climate_mode = 124;
|
||||
constexpr uint16_t climate_fan = 125;
|
||||
constexpr uint16_t climate_swing = 126;
|
||||
constexpr uint16_t climate_now = 127;
|
||||
constexpr uint16_t vacuum_check_robot = 128;
|
||||
constexpr uint16_t vacuum_auto_suction = 129;
|
||||
constexpr uint16_t vacuum_robot_chooses = 130;
|
||||
constexpr uint16_t vacuum_per_room = 131;
|
||||
constexpr uint16_t vacuum_speed_quiet = 132;
|
||||
constexpr uint16_t vacuum_speed_balanced = 133;
|
||||
constexpr uint16_t vacuum_speed_turbo = 134;
|
||||
constexpr uint16_t vacuum_speed_max = 135;
|
||||
constexpr uint16_t vacuum_pause_cleaning = 136;
|
||||
constexpr uint16_t vacuum_pause = 137;
|
||||
constexpr uint16_t vacuum_resume = 138;
|
||||
constexpr uint16_t vacuum_start_cleaning = 139;
|
||||
constexpr uint16_t vacuum_clean = 140;
|
||||
constexpr uint16_t vacuum_dock = 141;
|
||||
constexpr uint16_t cover_position = 142;
|
||||
constexpr uint16_t cover_tilt = 143;
|
||||
constexpr uint16_t cover_tilt_value = 144;
|
||||
constexpr uint16_t weather_feels_like = 145;
|
||||
constexpr uint16_t weather_no_forecast = 146;
|
||||
constexpr uint16_t weather_coming_days = 147;
|
||||
constexpr uint16_t history_no_data = 148;
|
||||
constexpr uint16_t history_average = 149;
|
||||
constexpr uint16_t history_average_of = 150;
|
||||
constexpr uint16_t history_now = 151;
|
||||
constexpr uint16_t history_range_hour = 152;
|
||||
constexpr uint16_t history_range_day = 153;
|
||||
constexpr uint16_t history_range_week = 154;
|
||||
constexpr uint16_t history_high = 155;
|
||||
constexpr uint16_t history_low = 156;
|
||||
constexpr uint16_t history_times = 157;
|
||||
constexpr uint16_t history_loading = 158;
|
||||
constexpr uint16_t history_empty = 159;
|
||||
constexpr uint16_t history_unavailable = 160;
|
||||
constexpr uint16_t media_muted = 161;
|
||||
constexpr uint16_t media_not_playing = 162;
|
||||
constexpr uint16_t media_loading = 163;
|
||||
constexpr uint16_t timer_running = 164;
|
||||
constexpr uint16_t timer_paused = 165;
|
||||
constexpr uint16_t timer_stopped = 166;
|
||||
constexpr uint16_t timer_pause = 167;
|
||||
constexpr uint16_t timer_start = 168;
|
||||
constexpr uint16_t timer_cancel = 169;
|
||||
constexpr uint16_t timer_paused_left = 170;
|
||||
constexpr uint16_t sun_name = 171;
|
||||
constexpr uint16_t sun_sunrise = 172;
|
||||
constexpr uint16_t sun_sunset = 173;
|
||||
constexpr uint16_t sun_rise = 174;
|
||||
constexpr uint16_t sun_set = 175;
|
||||
constexpr uint16_t script_running = 176;
|
||||
constexpr uint16_t script_never_run = 177;
|
||||
constexpr uint16_t script_last_time = 178;
|
||||
constexpr uint16_t script_yesterday_time = 179;
|
||||
constexpr uint16_t script_last_date = 180;
|
||||
constexpr uint16_t camera_no_image = 181;
|
||||
constexpr uint16_t camera_loading = 182;
|
||||
constexpr uint16_t camera_live = 183;
|
||||
constexpr uint16_t camera_recording = 184;
|
||||
constexpr uint16_t camera_tap_to_view = 185;
|
||||
constexpr uint16_t camera_no_image_yet = 186;
|
||||
constexpr uint16_t button_activate = 187;
|
||||
constexpr uint16_t button_run = 188;
|
||||
constexpr uint16_t button_press = 189;
|
||||
constexpr uint16_t calibration_title = 190;
|
||||
constexpr uint16_t calibration_touch_check = 191;
|
||||
constexpr uint16_t calibration_hold = 192;
|
||||
constexpr uint16_t calibration_crosshair = 193;
|
||||
constexpr uint16_t calibration_gently = 194;
|
||||
constexpr uint16_t calibration_same = 195;
|
||||
constexpr uint16_t calibration_rejected = 196;
|
||||
constexpr uint16_t calibration_save_failed = 197;
|
||||
constexpr uint16_t ha_on = 198;
|
||||
constexpr uint16_t ha_off = 199;
|
||||
constexpr uint16_t ha_climate_off = 200;
|
||||
constexpr uint16_t ha_climate_heat = 201;
|
||||
constexpr uint16_t ha_climate_cool = 202;
|
||||
constexpr uint16_t ha_climate_heat_cool = 203;
|
||||
constexpr uint16_t ha_climate_auto = 204;
|
||||
constexpr uint16_t ha_climate_dry = 205;
|
||||
constexpr uint16_t ha_climate_fan_only = 206;
|
||||
constexpr uint16_t ha_hvac_action_heating = 207;
|
||||
constexpr uint16_t ha_hvac_action_cooling = 208;
|
||||
constexpr uint16_t ha_hvac_action_idle = 209;
|
||||
constexpr uint16_t ha_hvac_action_off = 210;
|
||||
constexpr uint16_t ha_hvac_action_drying = 211;
|
||||
constexpr uint16_t ha_hvac_action_fan = 212;
|
||||
constexpr uint16_t ha_hvac_action_preheating = 213;
|
||||
constexpr uint16_t ha_hvac_action_defrosting = 214;
|
||||
constexpr uint16_t ha_cover_open = 215;
|
||||
constexpr uint16_t ha_cover_closed = 216;
|
||||
constexpr uint16_t ha_cover_opening = 217;
|
||||
constexpr uint16_t ha_cover_closing = 218;
|
||||
constexpr uint16_t ha_media_playing = 219;
|
||||
constexpr uint16_t ha_media_paused = 220;
|
||||
constexpr uint16_t ha_media_idle = 221;
|
||||
constexpr uint16_t ha_media_standby = 222;
|
||||
constexpr uint16_t ha_person_home = 223;
|
||||
constexpr uint16_t ha_person_not_home = 224;
|
||||
constexpr uint16_t ha_sun_above_horizon = 225;
|
||||
constexpr uint16_t ha_sun_below_horizon = 226;
|
||||
constexpr uint16_t ha_vacuum_docked = 227;
|
||||
constexpr uint16_t ha_vacuum_cleaning = 228;
|
||||
constexpr uint16_t ha_vacuum_paused = 229;
|
||||
constexpr uint16_t ha_vacuum_returning = 230;
|
||||
constexpr uint16_t ha_vacuum_idle = 231;
|
||||
constexpr uint16_t ha_weather_sunny = 232;
|
||||
constexpr uint16_t ha_weather_clear_night = 233;
|
||||
constexpr uint16_t ha_weather_cloudy = 234;
|
||||
constexpr uint16_t ha_weather_partlycloudy = 235;
|
||||
constexpr uint16_t ha_weather_rainy = 236;
|
||||
constexpr uint16_t ha_weather_pouring = 237;
|
||||
constexpr uint16_t ha_weather_snowy = 238;
|
||||
constexpr uint16_t ha_weather_snowy_rainy = 239;
|
||||
constexpr uint16_t ha_weather_fog = 240;
|
||||
constexpr uint16_t ha_weather_hail = 241;
|
||||
constexpr uint16_t ha_weather_lightning = 242;
|
||||
constexpr uint16_t ha_weather_lightning_rainy = 243;
|
||||
constexpr uint16_t ha_weather_windy = 244;
|
||||
constexpr uint16_t ha_weather_exceptional = 245;
|
||||
constexpr uint16_t ha_binary_battery_on = 246;
|
||||
constexpr uint16_t ha_binary_battery_off = 247;
|
||||
constexpr uint16_t ha_binary_battery_charging_on = 248;
|
||||
constexpr uint16_t ha_binary_battery_charging_off = 249;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_on = 250;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_off = 251;
|
||||
constexpr uint16_t ha_binary_cold_on = 252;
|
||||
constexpr uint16_t ha_binary_cold_off = 253;
|
||||
constexpr uint16_t ha_binary_connectivity_on = 254;
|
||||
constexpr uint16_t ha_binary_connectivity_off = 255;
|
||||
constexpr uint16_t ha_binary_door_on = 256;
|
||||
constexpr uint16_t ha_binary_door_off = 257;
|
||||
constexpr uint16_t ha_binary_garage_door_on = 258;
|
||||
constexpr uint16_t ha_binary_garage_door_off = 259;
|
||||
constexpr uint16_t ha_binary_gas_on = 260;
|
||||
constexpr uint16_t ha_binary_gas_off = 261;
|
||||
constexpr uint16_t ha_binary_heat_on = 262;
|
||||
constexpr uint16_t ha_binary_heat_off = 263;
|
||||
constexpr uint16_t ha_binary_light_on = 264;
|
||||
constexpr uint16_t ha_binary_light_off = 265;
|
||||
constexpr uint16_t ha_binary_lock_on = 266;
|
||||
constexpr uint16_t ha_binary_lock_off = 267;
|
||||
constexpr uint16_t ha_binary_moisture_on = 268;
|
||||
constexpr uint16_t ha_binary_moisture_off = 269;
|
||||
constexpr uint16_t ha_binary_motion_on = 270;
|
||||
constexpr uint16_t ha_binary_motion_off = 271;
|
||||
constexpr uint16_t ha_binary_moving_on = 272;
|
||||
constexpr uint16_t ha_binary_moving_off = 273;
|
||||
constexpr uint16_t ha_binary_occupancy_on = 274;
|
||||
constexpr uint16_t ha_binary_occupancy_off = 275;
|
||||
constexpr uint16_t ha_binary_opening_on = 276;
|
||||
constexpr uint16_t ha_binary_opening_off = 277;
|
||||
constexpr uint16_t ha_binary_plug_on = 278;
|
||||
constexpr uint16_t ha_binary_plug_off = 279;
|
||||
constexpr uint16_t ha_binary_power_on = 280;
|
||||
constexpr uint16_t ha_binary_power_off = 281;
|
||||
constexpr uint16_t ha_binary_presence_on = 282;
|
||||
constexpr uint16_t ha_binary_presence_off = 283;
|
||||
constexpr uint16_t ha_binary_problem_on = 284;
|
||||
constexpr uint16_t ha_binary_problem_off = 285;
|
||||
constexpr uint16_t ha_binary_running_on = 286;
|
||||
constexpr uint16_t ha_binary_running_off = 287;
|
||||
constexpr uint16_t ha_binary_safety_on = 288;
|
||||
constexpr uint16_t ha_binary_safety_off = 289;
|
||||
constexpr uint16_t ha_binary_smoke_on = 290;
|
||||
constexpr uint16_t ha_binary_smoke_off = 291;
|
||||
constexpr uint16_t ha_binary_sound_on = 292;
|
||||
constexpr uint16_t ha_binary_sound_off = 293;
|
||||
constexpr uint16_t ha_binary_tamper_on = 294;
|
||||
constexpr uint16_t ha_binary_tamper_off = 295;
|
||||
constexpr uint16_t ha_binary_update_on = 296;
|
||||
constexpr uint16_t ha_binary_update_off = 297;
|
||||
constexpr uint16_t ha_binary_vibration_on = 298;
|
||||
constexpr uint16_t ha_binary_vibration_off = 299;
|
||||
constexpr uint16_t ha_binary_window_on = 300;
|
||||
constexpr uint16_t ha_binary_window_off = 301;
|
||||
constexpr uint16_t date_weekdays = 16;
|
||||
constexpr uint16_t number_group_min = 2;
|
||||
constexpr uint16_t time_just_now = 3;
|
||||
constexpr uint16_t time_minutes_ago = 4;
|
||||
constexpr uint16_t time_hours_ago = 5;
|
||||
constexpr uint16_t time_yesterday = 6;
|
||||
constexpr uint16_t time_days_ago = 7;
|
||||
constexpr uint16_t time_weeks_ago = 8;
|
||||
constexpr uint16_t time_months_ago = 9;
|
||||
constexpr uint16_t time_years_ago = 10;
|
||||
constexpr uint16_t time_in_minutes = 11;
|
||||
constexpr uint16_t time_in_hours = 12;
|
||||
constexpr uint16_t time_tomorrow = 13;
|
||||
constexpr uint16_t time_in_days = 14;
|
||||
constexpr uint16_t time_am = 15;
|
||||
constexpr uint16_t time_pm = 16;
|
||||
constexpr uint16_t date_top_bar = 62;
|
||||
constexpr uint16_t date_full = 63;
|
||||
constexpr uint16_t date_day_month = 64;
|
||||
constexpr uint16_t date_weekday_time = 65;
|
||||
constexpr uint16_t duration_seconds = 66;
|
||||
constexpr uint16_t duration_minutes = 67;
|
||||
constexpr uint16_t duration_hours = 68;
|
||||
constexpr uint16_t duration_hours_minutes = 69;
|
||||
constexpr uint16_t duration_days = 70;
|
||||
constexpr uint16_t duration_days_hours = 71;
|
||||
constexpr uint16_t status_connecting = 72;
|
||||
constexpr uint16_t status_waiting = 73;
|
||||
constexpr uint16_t status_loading_tiles = 74;
|
||||
constexpr uint16_t status_ha_not_connected = 75;
|
||||
constexpr uint16_t status_manager_not_active = 76;
|
||||
constexpr uint16_t status_choose_tiles = 77;
|
||||
constexpr uint16_t status_home = 78;
|
||||
constexpr uint16_t status_no_network = 79;
|
||||
constexpr uint16_t settings_title = 80;
|
||||
constexpr uint16_t settings_brightness = 81;
|
||||
constexpr uint16_t settings_night = 82;
|
||||
constexpr uint16_t settings_screen = 83;
|
||||
constexpr uint16_t settings_this_screen = 84;
|
||||
constexpr uint16_t settings_dark_mode = 85;
|
||||
constexpr uint16_t settings_auto_standby = 86;
|
||||
constexpr uint16_t settings_standby_after = 87;
|
||||
constexpr uint16_t settings_standby_brightness = 88;
|
||||
constexpr uint16_t settings_night_mode = 89;
|
||||
constexpr uint16_t settings_starts = 90;
|
||||
constexpr uint16_t settings_ends = 91;
|
||||
constexpr uint16_t settings_night_brightness = 92;
|
||||
constexpr uint16_t settings_back_to_page_1 = 93;
|
||||
constexpr uint16_t settings_after = 94;
|
||||
constexpr uint16_t settings_also_on_standby = 95;
|
||||
constexpr uint16_t settings_swipe_between_pages = 96;
|
||||
constexpr uint16_t settings_page_buttons = 97;
|
||||
constexpr uint16_t settings_rotation = 98;
|
||||
constexpr uint16_t settings_address = 99;
|
||||
constexpr uint16_t settings_firmware = 100;
|
||||
constexpr uint16_t settings_home_assistant = 101;
|
||||
constexpr uint16_t settings_restart = 102;
|
||||
constexpr uint16_t settings_connected = 103;
|
||||
constexpr uint16_t settings_not_connected = 104;
|
||||
constexpr uint16_t settings_tap_again_to_restart = 105;
|
||||
constexpr uint16_t settings_seconds = 106;
|
||||
constexpr uint16_t settings_minutes = 107;
|
||||
constexpr uint16_t settings_hours = 108;
|
||||
constexpr uint16_t settings_hours_minutes = 109;
|
||||
constexpr uint16_t tile_tap_to_open = 110;
|
||||
constexpr uint16_t tile_page = 111;
|
||||
constexpr uint16_t tile_unavailable = 112;
|
||||
constexpr uint16_t tile_refused = 113;
|
||||
constexpr uint16_t tile_command_sent = 114;
|
||||
constexpr uint16_t tile_confirmed = 115;
|
||||
constexpr uint16_t alert_notification = 116;
|
||||
constexpr uint16_t alert_ok = 117;
|
||||
constexpr uint16_t light_color = 118;
|
||||
constexpr uint16_t light_color_temperature = 119;
|
||||
constexpr uint16_t light_brightness = 120;
|
||||
constexpr uint16_t light_waiting = 121;
|
||||
constexpr uint16_t effects_effect = 122;
|
||||
constexpr uint16_t effects_nothing = 123;
|
||||
constexpr uint16_t effects_loading = 124;
|
||||
constexpr uint16_t effects_not_connected = 125;
|
||||
constexpr uint16_t climate_target = 126;
|
||||
constexpr uint16_t climate_mode = 127;
|
||||
constexpr uint16_t climate_fan = 128;
|
||||
constexpr uint16_t climate_swing = 129;
|
||||
constexpr uint16_t climate_now = 130;
|
||||
constexpr uint16_t vacuum_check_robot = 131;
|
||||
constexpr uint16_t vacuum_auto_suction = 132;
|
||||
constexpr uint16_t vacuum_robot_chooses = 133;
|
||||
constexpr uint16_t vacuum_per_room = 134;
|
||||
constexpr uint16_t vacuum_speed_quiet = 135;
|
||||
constexpr uint16_t vacuum_speed_balanced = 136;
|
||||
constexpr uint16_t vacuum_speed_turbo = 137;
|
||||
constexpr uint16_t vacuum_speed_max = 138;
|
||||
constexpr uint16_t vacuum_pause_cleaning = 139;
|
||||
constexpr uint16_t vacuum_pause = 140;
|
||||
constexpr uint16_t vacuum_resume = 141;
|
||||
constexpr uint16_t vacuum_start_cleaning = 142;
|
||||
constexpr uint16_t vacuum_clean = 143;
|
||||
constexpr uint16_t vacuum_dock = 144;
|
||||
constexpr uint16_t cover_position = 145;
|
||||
constexpr uint16_t cover_tilt = 146;
|
||||
constexpr uint16_t cover_tilt_value = 147;
|
||||
constexpr uint16_t weather_feels_like = 148;
|
||||
constexpr uint16_t weather_no_forecast = 149;
|
||||
constexpr uint16_t weather_coming_days = 150;
|
||||
constexpr uint16_t history_no_data = 151;
|
||||
constexpr uint16_t history_average = 152;
|
||||
constexpr uint16_t history_average_of = 153;
|
||||
constexpr uint16_t history_now = 154;
|
||||
constexpr uint16_t history_range_hour = 155;
|
||||
constexpr uint16_t history_range_day = 156;
|
||||
constexpr uint16_t history_range_week = 157;
|
||||
constexpr uint16_t history_high = 158;
|
||||
constexpr uint16_t history_low = 159;
|
||||
constexpr uint16_t history_times = 160;
|
||||
constexpr uint16_t history_loading = 161;
|
||||
constexpr uint16_t history_empty = 162;
|
||||
constexpr uint16_t history_unavailable = 163;
|
||||
constexpr uint16_t media_muted = 164;
|
||||
constexpr uint16_t media_not_playing = 165;
|
||||
constexpr uint16_t media_loading = 166;
|
||||
constexpr uint16_t timer_running = 167;
|
||||
constexpr uint16_t timer_paused = 168;
|
||||
constexpr uint16_t timer_stopped = 169;
|
||||
constexpr uint16_t timer_pause = 170;
|
||||
constexpr uint16_t timer_start = 171;
|
||||
constexpr uint16_t timer_cancel = 172;
|
||||
constexpr uint16_t timer_paused_left = 173;
|
||||
constexpr uint16_t sun_name = 174;
|
||||
constexpr uint16_t sun_sunrise = 175;
|
||||
constexpr uint16_t sun_sunset = 176;
|
||||
constexpr uint16_t sun_rise = 177;
|
||||
constexpr uint16_t sun_set = 178;
|
||||
constexpr uint16_t script_running = 179;
|
||||
constexpr uint16_t script_never_run = 180;
|
||||
constexpr uint16_t script_last_time = 181;
|
||||
constexpr uint16_t script_yesterday_time = 182;
|
||||
constexpr uint16_t script_last_date = 183;
|
||||
constexpr uint16_t camera_no_image = 184;
|
||||
constexpr uint16_t camera_loading = 185;
|
||||
constexpr uint16_t camera_live = 186;
|
||||
constexpr uint16_t camera_recording = 187;
|
||||
constexpr uint16_t camera_tap_to_view = 188;
|
||||
constexpr uint16_t camera_no_image_yet = 189;
|
||||
constexpr uint16_t button_activate = 190;
|
||||
constexpr uint16_t button_run = 191;
|
||||
constexpr uint16_t button_press = 192;
|
||||
constexpr uint16_t calibration_title = 193;
|
||||
constexpr uint16_t calibration_touch_check = 194;
|
||||
constexpr uint16_t calibration_hold = 195;
|
||||
constexpr uint16_t calibration_crosshair = 196;
|
||||
constexpr uint16_t calibration_gently = 197;
|
||||
constexpr uint16_t calibration_same = 198;
|
||||
constexpr uint16_t calibration_rejected = 199;
|
||||
constexpr uint16_t calibration_save_failed = 200;
|
||||
constexpr uint16_t ha_on = 201;
|
||||
constexpr uint16_t ha_off = 202;
|
||||
constexpr uint16_t ha_climate_off = 203;
|
||||
constexpr uint16_t ha_climate_heat = 204;
|
||||
constexpr uint16_t ha_climate_cool = 205;
|
||||
constexpr uint16_t ha_climate_heat_cool = 206;
|
||||
constexpr uint16_t ha_climate_auto = 207;
|
||||
constexpr uint16_t ha_climate_dry = 208;
|
||||
constexpr uint16_t ha_climate_fan_only = 209;
|
||||
constexpr uint16_t ha_hvac_action_heating = 210;
|
||||
constexpr uint16_t ha_hvac_action_cooling = 211;
|
||||
constexpr uint16_t ha_hvac_action_idle = 212;
|
||||
constexpr uint16_t ha_hvac_action_off = 213;
|
||||
constexpr uint16_t ha_hvac_action_drying = 214;
|
||||
constexpr uint16_t ha_hvac_action_fan = 215;
|
||||
constexpr uint16_t ha_hvac_action_preheating = 216;
|
||||
constexpr uint16_t ha_hvac_action_defrosting = 217;
|
||||
constexpr uint16_t ha_cover_open = 218;
|
||||
constexpr uint16_t ha_cover_closed = 219;
|
||||
constexpr uint16_t ha_cover_opening = 220;
|
||||
constexpr uint16_t ha_cover_closing = 221;
|
||||
constexpr uint16_t ha_media_playing = 222;
|
||||
constexpr uint16_t ha_media_paused = 223;
|
||||
constexpr uint16_t ha_media_idle = 224;
|
||||
constexpr uint16_t ha_media_standby = 225;
|
||||
constexpr uint16_t ha_person_home = 226;
|
||||
constexpr uint16_t ha_person_not_home = 227;
|
||||
constexpr uint16_t ha_sun_above_horizon = 228;
|
||||
constexpr uint16_t ha_sun_below_horizon = 229;
|
||||
constexpr uint16_t ha_vacuum_docked = 230;
|
||||
constexpr uint16_t ha_vacuum_cleaning = 231;
|
||||
constexpr uint16_t ha_vacuum_paused = 232;
|
||||
constexpr uint16_t ha_vacuum_returning = 233;
|
||||
constexpr uint16_t ha_vacuum_idle = 234;
|
||||
constexpr uint16_t ha_weather_sunny = 235;
|
||||
constexpr uint16_t ha_weather_clear_night = 236;
|
||||
constexpr uint16_t ha_weather_cloudy = 237;
|
||||
constexpr uint16_t ha_weather_partlycloudy = 238;
|
||||
constexpr uint16_t ha_weather_rainy = 239;
|
||||
constexpr uint16_t ha_weather_pouring = 240;
|
||||
constexpr uint16_t ha_weather_snowy = 241;
|
||||
constexpr uint16_t ha_weather_snowy_rainy = 242;
|
||||
constexpr uint16_t ha_weather_fog = 243;
|
||||
constexpr uint16_t ha_weather_hail = 244;
|
||||
constexpr uint16_t ha_weather_lightning = 245;
|
||||
constexpr uint16_t ha_weather_lightning_rainy = 246;
|
||||
constexpr uint16_t ha_weather_windy = 247;
|
||||
constexpr uint16_t ha_weather_exceptional = 248;
|
||||
constexpr uint16_t ha_binary_battery_on = 249;
|
||||
constexpr uint16_t ha_binary_battery_off = 250;
|
||||
constexpr uint16_t ha_binary_battery_charging_on = 251;
|
||||
constexpr uint16_t ha_binary_battery_charging_off = 252;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_on = 253;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_off = 254;
|
||||
constexpr uint16_t ha_binary_cold_on = 255;
|
||||
constexpr uint16_t ha_binary_cold_off = 256;
|
||||
constexpr uint16_t ha_binary_connectivity_on = 257;
|
||||
constexpr uint16_t ha_binary_connectivity_off = 258;
|
||||
constexpr uint16_t ha_binary_door_on = 259;
|
||||
constexpr uint16_t ha_binary_door_off = 260;
|
||||
constexpr uint16_t ha_binary_garage_door_on = 261;
|
||||
constexpr uint16_t ha_binary_garage_door_off = 262;
|
||||
constexpr uint16_t ha_binary_gas_on = 263;
|
||||
constexpr uint16_t ha_binary_gas_off = 264;
|
||||
constexpr uint16_t ha_binary_heat_on = 265;
|
||||
constexpr uint16_t ha_binary_heat_off = 266;
|
||||
constexpr uint16_t ha_binary_light_on = 267;
|
||||
constexpr uint16_t ha_binary_light_off = 268;
|
||||
constexpr uint16_t ha_binary_lock_on = 269;
|
||||
constexpr uint16_t ha_binary_lock_off = 270;
|
||||
constexpr uint16_t ha_binary_moisture_on = 271;
|
||||
constexpr uint16_t ha_binary_moisture_off = 272;
|
||||
constexpr uint16_t ha_binary_motion_on = 273;
|
||||
constexpr uint16_t ha_binary_motion_off = 274;
|
||||
constexpr uint16_t ha_binary_moving_on = 275;
|
||||
constexpr uint16_t ha_binary_moving_off = 276;
|
||||
constexpr uint16_t ha_binary_occupancy_on = 277;
|
||||
constexpr uint16_t ha_binary_occupancy_off = 278;
|
||||
constexpr uint16_t ha_binary_opening_on = 279;
|
||||
constexpr uint16_t ha_binary_opening_off = 280;
|
||||
constexpr uint16_t ha_binary_plug_on = 281;
|
||||
constexpr uint16_t ha_binary_plug_off = 282;
|
||||
constexpr uint16_t ha_binary_power_on = 283;
|
||||
constexpr uint16_t ha_binary_power_off = 284;
|
||||
constexpr uint16_t ha_binary_presence_on = 285;
|
||||
constexpr uint16_t ha_binary_presence_off = 286;
|
||||
constexpr uint16_t ha_binary_problem_on = 287;
|
||||
constexpr uint16_t ha_binary_problem_off = 288;
|
||||
constexpr uint16_t ha_binary_running_on = 289;
|
||||
constexpr uint16_t ha_binary_running_off = 290;
|
||||
constexpr uint16_t ha_binary_safety_on = 291;
|
||||
constexpr uint16_t ha_binary_safety_off = 292;
|
||||
constexpr uint16_t ha_binary_smoke_on = 293;
|
||||
constexpr uint16_t ha_binary_smoke_off = 294;
|
||||
constexpr uint16_t ha_binary_sound_on = 295;
|
||||
constexpr uint16_t ha_binary_sound_off = 296;
|
||||
constexpr uint16_t ha_binary_tamper_on = 297;
|
||||
constexpr uint16_t ha_binary_tamper_off = 298;
|
||||
constexpr uint16_t ha_binary_update_on = 299;
|
||||
constexpr uint16_t ha_binary_update_off = 300;
|
||||
constexpr uint16_t ha_binary_vibration_on = 301;
|
||||
constexpr uint16_t ha_binary_vibration_off = 302;
|
||||
constexpr uint16_t ha_binary_window_on = 303;
|
||||
constexpr uint16_t ha_binary_window_off = 304;
|
||||
constexpr uint16_t date_weekdays = 17;
|
||||
constexpr uint16_t date_weekdays_count = 7;
|
||||
constexpr uint16_t date_weekdays_short = 23;
|
||||
constexpr uint16_t date_weekdays_short = 24;
|
||||
constexpr uint16_t date_weekdays_short_count = 7;
|
||||
constexpr uint16_t date_weekdays_min = 30;
|
||||
constexpr uint16_t date_weekdays_min = 31;
|
||||
constexpr uint16_t date_weekdays_min_count = 7;
|
||||
constexpr uint16_t date_months = 37;
|
||||
constexpr uint16_t date_months = 38;
|
||||
constexpr uint16_t date_months_count = 12;
|
||||
constexpr uint16_t date_months_short = 49;
|
||||
constexpr uint16_t date_months_short = 50;
|
||||
constexpr uint16_t date_months_short_count = 12;
|
||||
} // namespace txt
|
||||
constexpr uint16_t KEY_COUNT = 302;
|
||||
constexpr uint32_t KEYS_HASH = 0x725A92EEu;
|
||||
constexpr uint16_t KEY_COUNT = 305;
|
||||
constexpr uint32_t KEYS_HASH = 0x8971C0EBu;
|
||||
} // namespace screen_text
|
||||
|
||||
+8
-6
@@ -156,7 +156,7 @@ esphome:
|
||||
id(active_climate_action) = t.extra().hvac_action;
|
||||
id(open_value_overlay).execute(t.name, t.entity, t.domain(), "auto", t.active(), 0,
|
||||
t.brightness, t.percentage, t.position, runtime_tiles::icon_for(t),
|
||||
"Off", "On", t.modes,
|
||||
screen_text::tr(screen_text::txt::ha_off), screen_text::tr(screen_text::txt::ha_on), t.modes,
|
||||
t.current, t.target, t.humidity, t.state, t.extra().hvac_modes,
|
||||
std::to_string(t.minimum), std::to_string(t.maximum), std::to_string(t.step));
|
||||
};
|
||||
@@ -218,7 +218,9 @@ esphome:
|
||||
settings_screen::name_text = []() { return std::string("${DEVICE_FRIENDLY_NAME}"); };
|
||||
settings_screen::address_text = []() { return id(wifi_ip).state.empty() ? std::string(screen_text::tr(screen_text::txt::status_no_network)) : id(wifi_ip).state; };
|
||||
settings_screen::firmware_text = []() { return std::string("${SCREEN_FIRMWARE_VERSION}"); };
|
||||
settings_screen::link_text = []() { return std::string(esphome::api_is_connected() ? "Connected" : "Not connected"); };
|
||||
settings_screen::link_text = []() {
|
||||
return std::string(screen_text::tr(esphome::api_is_connected() ? screen_text::txt::settings_connected : screen_text::txt::settings_not_connected));
|
||||
};
|
||||
settings_screen::restart_device = []() { ESP_LOGI("settings", "restart from the screen"); App.safe_reboot(); };
|
||||
// A dimmed screen, a calibration or an alert owns the glass; the page waits.
|
||||
settings_screen::may_open = []() {
|
||||
@@ -669,7 +671,7 @@ font:
|
||||
glyphs: ['<','>','—','&','@','!',',','.','?','"','%','(',')','+','-','_',':','°','0','1','2','3','4','5',
|
||||
'6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
|
||||
'U','V','W','X','Y','Z',' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
|
||||
'r','s','t','u','v','w','x','y','z','/','·',
|
||||
'r','s','t','u','v','w','x','y','z','/','·',"'",';','…',
|
||||
'À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø',
|
||||
'Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð',
|
||||
'ñ','ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','þ','ÿ','Ą','ą','Ć','ć','Ę','ę','Ł','ł','Ń','ń',
|
||||
@@ -686,7 +688,7 @@ font:
|
||||
glyphs: ['<','>','—','&','@','!',',','.','?','"','%','(',')','+','-','_',':','°','0','1','2','3','4','5',
|
||||
'6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
|
||||
'U','V','W','X','Y','Z',' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
|
||||
'r','s','t','u','v','w','x','y','z','/','·',
|
||||
'r','s','t','u','v','w','x','y','z','/','·',"'",';','…',
|
||||
'À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø',
|
||||
'Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð',
|
||||
'ñ','ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','þ','ÿ','Ą','ą','Ć','ć','Ę','ę','Ł','ł','Ń','ń',
|
||||
@@ -717,7 +719,7 @@ font:
|
||||
glyphs: ['<','>','—','&','@','!',',','.','?','"','%','(',')','+','-','_',':','°','0','1','2','3','4','5',
|
||||
'6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
|
||||
'U','V','W','X','Y','Z',' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
|
||||
'r','s','t','u','v','w','x','y','z','/','·',
|
||||
'r','s','t','u','v','w','x','y','z','/','·',"'",';','…',
|
||||
'À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø',
|
||||
'Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð',
|
||||
'ñ','ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','þ','ÿ','Ą','ą','Ć','ć','Ę','ę','Ł','ł','Ń','ń',
|
||||
@@ -734,7 +736,7 @@ font:
|
||||
glyphs: ['<','>','—','&','@','!',',','.','?','"','%','(',')','+','-','_',':','°','0','1','2','3','4','5',
|
||||
'6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
|
||||
'U','V','W','X','Y','Z',' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
|
||||
'r','s','t','u','v','w','x','y','z','/','…','·',
|
||||
'r','s','t','u','v','w','x','y','z','/','…','·',"'",';',
|
||||
'À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø',
|
||||
'Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð',
|
||||
'ñ','ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','þ','ÿ','Ą','ą','Ć','ć','Ę','ę','Ł','ł','Ń','ń',
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Deutsch",
|
||||
"english": "German",
|
||||
"script": "latin",
|
||||
"plural": "one_other",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": ".",
|
||||
"group_min": "1"
|
||||
},
|
||||
"time": {
|
||||
"am": "AM",
|
||||
"pm": "PM"
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"Sonntag",
|
||||
"Montag",
|
||||
"Dienstag",
|
||||
"Mittwoch",
|
||||
"Donnerstag",
|
||||
"Freitag",
|
||||
"Samstag"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"So",
|
||||
"Mo",
|
||||
"Di",
|
||||
"Mi",
|
||||
"Do",
|
||||
"Fr",
|
||||
"Sa"
|
||||
],
|
||||
"weekdays_min": [
|
||||
"So",
|
||||
"Mo",
|
||||
"Di",
|
||||
"Mi",
|
||||
"Do",
|
||||
"Fr",
|
||||
"Sa"
|
||||
],
|
||||
"months": [
|
||||
"Januar",
|
||||
"Februar",
|
||||
"März",
|
||||
"April",
|
||||
"Mai",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"August",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Dezember"
|
||||
],
|
||||
"months_short": [
|
||||
"Jan.",
|
||||
"Feb.",
|
||||
"März",
|
||||
"Apr.",
|
||||
"Mai",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"Aug.",
|
||||
"Sept.",
|
||||
"Okt.",
|
||||
"Nov.",
|
||||
"Dez."
|
||||
],
|
||||
"top_bar": "{weekday}, {day}. {month}",
|
||||
"full": "{weekday}, {day}. {month}",
|
||||
"day_month": "{day}. {month}",
|
||||
"weekday_time": "{weekday}, {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "Ein",
|
||||
"off": "Aus",
|
||||
"climate": {
|
||||
"off": "Aus",
|
||||
"heat": "Heizbetrieb",
|
||||
"cool": "Kühlbetrieb",
|
||||
"heat_cool": "Heizen/Kühlen",
|
||||
"auto": "Auto",
|
||||
"dry": "Entfeuchtung",
|
||||
"fan_only": "Nur Lüftung"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "Heizbetrieb",
|
||||
"cooling": "Kühlbetrieb",
|
||||
"idle": "Leerlauf",
|
||||
"off": "Aus",
|
||||
"drying": "Entfeuchtung",
|
||||
"fan": "Lüftung",
|
||||
"preheating": "Vorheizen",
|
||||
"defrosting": "Enteisung"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Geöffnet",
|
||||
"closed": "Geschlossen",
|
||||
"opening": "Wird geöffnet",
|
||||
"closing": "Wird geschlossen"
|
||||
},
|
||||
"media": {
|
||||
"playing": "Wiedergabe",
|
||||
"paused": "Pausiert",
|
||||
"idle": "Leerlauf",
|
||||
"standby": "Standby"
|
||||
},
|
||||
"person": {
|
||||
"home": "Zuhause",
|
||||
"not_home": "Abwesend"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Über dem Horizont",
|
||||
"below_horizon": "Unter dem Horizont"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "Angedockt",
|
||||
"cleaning": "Reinigt",
|
||||
"paused": "Pausiert",
|
||||
"returning": "Rückkehr zur Ladestation",
|
||||
"idle": "Leerlauf"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Sonnig",
|
||||
"clear_night": "Klare Nacht",
|
||||
"cloudy": "Bewölkt",
|
||||
"partlycloudy": "Teilweise bewölkt",
|
||||
"rainy": "Regnerisch",
|
||||
"pouring": "Strömender Regen",
|
||||
"snowy": "Schneefall",
|
||||
"snowy_rainy": "Schneeregen",
|
||||
"fog": "Nebel",
|
||||
"hail": "Hagel",
|
||||
"lightning": "Gewitter",
|
||||
"lightning_rainy": "Gewitter, regnerisch",
|
||||
"windy": "Windig",
|
||||
"exceptional": "Außergewöhnlich"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Niedrig",
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "Wird geladen",
|
||||
"battery_charging_off": "Wird nicht geladen",
|
||||
"carbon_monoxide_on": "Erkannt",
|
||||
"carbon_monoxide_off": "Frei",
|
||||
"cold_on": "Kalt",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Verbunden",
|
||||
"connectivity_off": "Getrennt",
|
||||
"door_on": "Geöffnet",
|
||||
"door_off": "Geschlossen",
|
||||
"garage_door_on": "Geöffnet",
|
||||
"garage_door_off": "Geschlossen",
|
||||
"gas_on": "Erkannt",
|
||||
"gas_off": "Frei",
|
||||
"heat_on": "Heiß",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Licht erkannt",
|
||||
"light_off": "Kein Licht",
|
||||
"lock_on": "Aufgeschlossen",
|
||||
"lock_off": "Abgeschlossen",
|
||||
"moisture_on": "Nass",
|
||||
"moisture_off": "Trocken",
|
||||
"motion_on": "Erkannt",
|
||||
"motion_off": "Frei",
|
||||
"moving_on": "Bewegt sich",
|
||||
"moving_off": "Bewegt sich nicht",
|
||||
"occupancy_on": "Erkannt",
|
||||
"occupancy_off": "Frei",
|
||||
"opening_on": "Geöffnet",
|
||||
"opening_off": "Geschlossen",
|
||||
"plug_on": "Eingesteckt",
|
||||
"plug_off": "Ausgesteckt",
|
||||
"power_on": "Ein",
|
||||
"power_off": "Aus",
|
||||
"presence_on": "Zuhause",
|
||||
"presence_off": "Abwesend",
|
||||
"problem_on": "Problem",
|
||||
"problem_off": "OK",
|
||||
"running_on": "In Betrieb",
|
||||
"running_off": "Außer Betrieb",
|
||||
"safety_on": "Unsicher",
|
||||
"safety_off": "Sicher",
|
||||
"smoke_on": "Erkannt",
|
||||
"smoke_off": "Frei",
|
||||
"sound_on": "Erkannt",
|
||||
"sound_off": "Frei",
|
||||
"tamper_on": "Manipulation erkannt",
|
||||
"tamper_off": "Frei",
|
||||
"update_on": "Update verfügbar",
|
||||
"update_off": "Aktuell",
|
||||
"vibration_on": "Erkannt",
|
||||
"vibration_off": "Frei",
|
||||
"window_on": "Geöffnet",
|
||||
"window_off": "Geschlossen"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
@@ -11,6 +11,130 @@
|
||||
"light": {
|
||||
"color": "Colour",
|
||||
"color_temperature": "Colour temperature"
|
||||
},
|
||||
"ha": {
|
||||
"on": "On",
|
||||
"off": "Off",
|
||||
"climate": {
|
||||
"off": "Off",
|
||||
"heat": "Heat",
|
||||
"cool": "Cool",
|
||||
"heat_cool": "Heat/Cool",
|
||||
"auto": "Auto",
|
||||
"dry": "Dry",
|
||||
"fan_only": "Fan only"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "Heating",
|
||||
"cooling": "Cooling",
|
||||
"idle": "Idle",
|
||||
"off": "Off",
|
||||
"drying": "Drying",
|
||||
"fan": "Fan",
|
||||
"preheating": "Preheating",
|
||||
"defrosting": "Defrosting"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Open",
|
||||
"closed": "Closed",
|
||||
"opening": "Opening",
|
||||
"closing": "Closing"
|
||||
},
|
||||
"media": {
|
||||
"playing": "Playing",
|
||||
"paused": "Paused",
|
||||
"idle": "Idle",
|
||||
"standby": "Standby"
|
||||
},
|
||||
"person": {
|
||||
"home": "Home",
|
||||
"not_home": "Away"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Above horizon",
|
||||
"below_horizon": "Below horizon"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "Docked",
|
||||
"cleaning": "Cleaning",
|
||||
"paused": "Paused",
|
||||
"returning": "Returning to dock",
|
||||
"idle": "Idle"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Sunny",
|
||||
"clear_night": "Clear, night",
|
||||
"cloudy": "Cloudy",
|
||||
"partlycloudy": "Partly cloudy",
|
||||
"rainy": "Rainy",
|
||||
"pouring": "Pouring",
|
||||
"snowy": "Snowy",
|
||||
"snowy_rainy": "Snowy, rainy",
|
||||
"fog": "Fog",
|
||||
"hail": "Hail",
|
||||
"lightning": "Lightning",
|
||||
"lightning_rainy": "Lightning, rainy",
|
||||
"windy": "Windy",
|
||||
"exceptional": "Exceptional"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Low",
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "Charging",
|
||||
"battery_charging_off": "Not charging",
|
||||
"carbon_monoxide_on": "Detected",
|
||||
"carbon_monoxide_off": "Clear",
|
||||
"cold_on": "Cold",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Connected",
|
||||
"connectivity_off": "Disconnected",
|
||||
"door_on": "Open",
|
||||
"door_off": "Closed",
|
||||
"garage_door_on": "Open",
|
||||
"garage_door_off": "Closed",
|
||||
"gas_on": "Detected",
|
||||
"gas_off": "Clear",
|
||||
"heat_on": "Hot",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Light detected",
|
||||
"light_off": "No light",
|
||||
"lock_on": "Unlocked",
|
||||
"lock_off": "Locked",
|
||||
"moisture_on": "Wet",
|
||||
"moisture_off": "Dry",
|
||||
"motion_on": "Detected",
|
||||
"motion_off": "Clear",
|
||||
"moving_on": "Moving",
|
||||
"moving_off": "Not moving",
|
||||
"occupancy_on": "Detected",
|
||||
"occupancy_off": "Clear",
|
||||
"opening_on": "Open",
|
||||
"opening_off": "Closed",
|
||||
"plug_on": "Plugged in",
|
||||
"plug_off": "Unplugged",
|
||||
"power_on": "On",
|
||||
"power_off": "Off",
|
||||
"presence_on": "Home",
|
||||
"presence_off": "Away",
|
||||
"problem_on": "Problem",
|
||||
"problem_off": "OK",
|
||||
"running_on": "Running",
|
||||
"running_off": "Not running",
|
||||
"safety_on": "Unsafe",
|
||||
"safety_off": "Safe",
|
||||
"smoke_on": "Detected",
|
||||
"smoke_off": "Clear",
|
||||
"sound_on": "Detected",
|
||||
"sound_off": "Clear",
|
||||
"tamper_on": "Tampering detected",
|
||||
"tamper_off": "Clear",
|
||||
"update_on": "Update available",
|
||||
"update_off": "Up-to-date",
|
||||
"vibration_on": "Detected",
|
||||
"vibration_off": "Clear",
|
||||
"window_on": "Open",
|
||||
"window_off": "Closed"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ".",
|
||||
"group": ","
|
||||
"group": ",",
|
||||
"group_min": "1"
|
||||
},
|
||||
"time": {
|
||||
"just_now": "Just now",
|
||||
@@ -131,6 +132,8 @@
|
||||
"firmware": "Firmware",
|
||||
"home_assistant": "Home Assistant",
|
||||
"restart": "Restart",
|
||||
"connected": "Connected",
|
||||
"not_connected": "Not connected",
|
||||
"tap_again_to_restart": "Tap again to restart",
|
||||
"seconds": "{n} sec",
|
||||
"minutes": "{n} min",
|
||||
@@ -299,8 +302,8 @@
|
||||
"not_home": "Away"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Above the horizon",
|
||||
"below_horizon": "Below the horizon"
|
||||
"above_horizon": "Above horizon",
|
||||
"below_horizon": "Below horizon"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "Docked",
|
||||
@@ -330,8 +333,8 @@
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "Charging",
|
||||
"battery_charging_off": "Not charging",
|
||||
"carbon_monoxide_on": "Danger",
|
||||
"carbon_monoxide_off": "Safe",
|
||||
"carbon_monoxide_on": "Detected",
|
||||
"carbon_monoxide_off": "Clear",
|
||||
"cold_on": "Cold",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Connected",
|
||||
@@ -340,21 +343,21 @@
|
||||
"door_off": "Closed",
|
||||
"garage_door_on": "Open",
|
||||
"garage_door_off": "Closed",
|
||||
"gas_on": "Danger",
|
||||
"gas_off": "Safe",
|
||||
"gas_on": "Detected",
|
||||
"gas_off": "Clear",
|
||||
"heat_on": "Hot",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Light",
|
||||
"light_off": "Dark",
|
||||
"lock_on": "Open",
|
||||
"light_on": "Light detected",
|
||||
"light_off": "No light",
|
||||
"lock_on": "Unlocked",
|
||||
"lock_off": "Locked",
|
||||
"moisture_on": "Wet",
|
||||
"moisture_off": "Dry",
|
||||
"motion_on": "Motion",
|
||||
"motion_off": "No motion",
|
||||
"motion_on": "Detected",
|
||||
"motion_off": "Clear",
|
||||
"moving_on": "Moving",
|
||||
"moving_off": "Still",
|
||||
"occupancy_on": "Occupied",
|
||||
"moving_off": "Not moving",
|
||||
"occupancy_on": "Detected",
|
||||
"occupancy_off": "Clear",
|
||||
"opening_on": "Open",
|
||||
"opening_off": "Closed",
|
||||
@@ -366,20 +369,20 @@
|
||||
"presence_off": "Away",
|
||||
"problem_on": "Problem",
|
||||
"problem_off": "OK",
|
||||
"running_on": "Active",
|
||||
"running_off": "Inactive",
|
||||
"running_on": "Running",
|
||||
"running_off": "Not running",
|
||||
"safety_on": "Unsafe",
|
||||
"safety_off": "Safe",
|
||||
"smoke_on": "Smoke",
|
||||
"smoke_off": "No smoke",
|
||||
"sound_on": "Sound",
|
||||
"sound_off": "Silent",
|
||||
"tamper_on": "Tampering",
|
||||
"tamper_off": "OK",
|
||||
"update_on": "Update",
|
||||
"update_off": "Up to date",
|
||||
"vibration_on": "Vibration",
|
||||
"vibration_off": "Still",
|
||||
"smoke_on": "Detected",
|
||||
"smoke_off": "Clear",
|
||||
"sound_on": "Detected",
|
||||
"sound_off": "Clear",
|
||||
"tamper_on": "Tampering detected",
|
||||
"tamper_off": "Clear",
|
||||
"update_on": "Update available",
|
||||
"update_off": "Up-to-date",
|
||||
"vibration_on": "Detected",
|
||||
"vibration_off": "Clear",
|
||||
"window_on": "Open",
|
||||
"window_off": "Closed"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Español",
|
||||
"english": "Spanish",
|
||||
"script": "latin",
|
||||
"plural": "one_other",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": ".",
|
||||
"group_min": "2"
|
||||
},
|
||||
"time": {
|
||||
"am": "a. m.",
|
||||
"pm": "p. m."
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"domingo",
|
||||
"lunes",
|
||||
"martes",
|
||||
"miércoles",
|
||||
"jueves",
|
||||
"viernes",
|
||||
"sábado"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"dom",
|
||||
"lun",
|
||||
"mar",
|
||||
"mié",
|
||||
"jue",
|
||||
"vie",
|
||||
"sáb"
|
||||
],
|
||||
"weekdays_min": [
|
||||
"dom",
|
||||
"lun",
|
||||
"mar",
|
||||
"mié",
|
||||
"jue",
|
||||
"vie",
|
||||
"sáb"
|
||||
],
|
||||
"months": [
|
||||
"enero",
|
||||
"febrero",
|
||||
"marzo",
|
||||
"abril",
|
||||
"mayo",
|
||||
"junio",
|
||||
"julio",
|
||||
"agosto",
|
||||
"septiembre",
|
||||
"octubre",
|
||||
"noviembre",
|
||||
"diciembre"
|
||||
],
|
||||
"months_short": [
|
||||
"ene",
|
||||
"feb",
|
||||
"mar",
|
||||
"abr",
|
||||
"may",
|
||||
"jun",
|
||||
"jul",
|
||||
"ago",
|
||||
"sept",
|
||||
"oct",
|
||||
"nov",
|
||||
"dic"
|
||||
],
|
||||
"top_bar": "{weekday}, {day} {month}",
|
||||
"full": "{weekday}, {day} de {month}",
|
||||
"day_month": "{day} {month}",
|
||||
"weekday_time": "{weekday}, {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "Encendido",
|
||||
"off": "Apagado",
|
||||
"climate": {
|
||||
"off": "Apagado",
|
||||
"heat": "Calor",
|
||||
"cool": "Frío",
|
||||
"heat_cool": "Calor/Frío",
|
||||
"auto": "Auto",
|
||||
"dry": "Seco",
|
||||
"fan_only": "Solo ventilador"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "Calefacción",
|
||||
"cooling": "Refrigeración",
|
||||
"idle": "Inactivo",
|
||||
"off": "Apagado",
|
||||
"drying": "Secando",
|
||||
"fan": "Ventilador",
|
||||
"preheating": "Precalentamiento",
|
||||
"defrosting": "Antihielo"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Abierto",
|
||||
"closed": "Cerrado",
|
||||
"opening": "Abriendo",
|
||||
"closing": "Cerrando"
|
||||
},
|
||||
"media": {
|
||||
"playing": "Reproduciendo",
|
||||
"paused": "En pausa",
|
||||
"idle": "Inactivo",
|
||||
"standby": "En espera"
|
||||
},
|
||||
"person": {
|
||||
"home": "En casa",
|
||||
"not_home": "Fuera"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Sobre el horizonte",
|
||||
"below_horizon": "Bajo el horizonte"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "En la base",
|
||||
"cleaning": "Limpiando",
|
||||
"paused": "En pausa",
|
||||
"returning": "Volviendo a la base",
|
||||
"idle": "Inactivo"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Soleado",
|
||||
"clear_night": "Despejado, de noche",
|
||||
"cloudy": "Nublado",
|
||||
"partlycloudy": "Parcialmente nublado",
|
||||
"rainy": "Lluvioso",
|
||||
"pouring": "Lluvia torrencial",
|
||||
"snowy": "Nevado",
|
||||
"snowy_rainy": "Nevado, lluvioso",
|
||||
"fog": "Niebla",
|
||||
"hail": "Granizo",
|
||||
"lightning": "Relámpagos",
|
||||
"lightning_rainy": "Relámpagos, lluvioso",
|
||||
"windy": "Ventoso",
|
||||
"exceptional": "Excepcional"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Bajo",
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "Cargando",
|
||||
"battery_charging_off": "No está cargando",
|
||||
"carbon_monoxide_on": "Detectado",
|
||||
"carbon_monoxide_off": "No detectado",
|
||||
"cold_on": "Frío",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Conectado",
|
||||
"connectivity_off": "Desconectado",
|
||||
"door_on": "Abierto",
|
||||
"door_off": "Cerrado",
|
||||
"garage_door_on": "Abierto",
|
||||
"garage_door_off": "Cerrado",
|
||||
"gas_on": "Detectado",
|
||||
"gas_off": "No detectado",
|
||||
"heat_on": "Caliente",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Luz detectada",
|
||||
"light_off": "Sin luz",
|
||||
"lock_on": "Desbloqueado",
|
||||
"lock_off": "Bloqueado",
|
||||
"moisture_on": "Húmedo",
|
||||
"moisture_off": "Seco",
|
||||
"motion_on": "Detectado",
|
||||
"motion_off": "No detectado",
|
||||
"moving_on": "En movimiento",
|
||||
"moving_off": "No se mueve",
|
||||
"occupancy_on": "Detectado",
|
||||
"occupancy_off": "No detectado",
|
||||
"opening_on": "Abierto",
|
||||
"opening_off": "Cerrado",
|
||||
"plug_on": "Enchufado",
|
||||
"plug_off": "Desenchufado",
|
||||
"power_on": "Encendido",
|
||||
"power_off": "Apagado",
|
||||
"presence_on": "En casa",
|
||||
"presence_off": "Fuera",
|
||||
"problem_on": "Problema",
|
||||
"problem_off": "OK",
|
||||
"running_on": "Ejecutando",
|
||||
"running_off": "No se está ejecutando",
|
||||
"safety_on": "Inseguro",
|
||||
"safety_off": "Seguro",
|
||||
"smoke_on": "Detectado",
|
||||
"smoke_off": "No detectado",
|
||||
"sound_on": "Detectado",
|
||||
"sound_off": "No detectado",
|
||||
"tamper_on": "Manipulación detectada",
|
||||
"tamper_off": "No detectado",
|
||||
"update_on": "Actualización disponible",
|
||||
"update_off": "Actualizado",
|
||||
"vibration_on": "Detectado",
|
||||
"vibration_off": "No detectado",
|
||||
"window_on": "Abierto",
|
||||
"window_off": "Cerrado"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Français",
|
||||
"english": "French",
|
||||
"script": "latin",
|
||||
"plural": "one_upto_1",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": " ",
|
||||
"group_min": "1"
|
||||
},
|
||||
"time": {
|
||||
"am": "AM",
|
||||
"pm": "PM"
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"dimanche",
|
||||
"lundi",
|
||||
"mardi",
|
||||
"mercredi",
|
||||
"jeudi",
|
||||
"vendredi",
|
||||
"samedi"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"dim.",
|
||||
"lun.",
|
||||
"mar.",
|
||||
"mer.",
|
||||
"jeu.",
|
||||
"ven.",
|
||||
"sam."
|
||||
],
|
||||
"weekdays_min": [
|
||||
"dim.",
|
||||
"lun.",
|
||||
"mar.",
|
||||
"mer.",
|
||||
"jeu.",
|
||||
"ven.",
|
||||
"sam."
|
||||
],
|
||||
"months": [
|
||||
"janvier",
|
||||
"février",
|
||||
"mars",
|
||||
"avril",
|
||||
"mai",
|
||||
"juin",
|
||||
"juillet",
|
||||
"août",
|
||||
"septembre",
|
||||
"octobre",
|
||||
"novembre",
|
||||
"décembre"
|
||||
],
|
||||
"months_short": [
|
||||
"janv.",
|
||||
"févr.",
|
||||
"mars",
|
||||
"avr.",
|
||||
"mai",
|
||||
"juin",
|
||||
"juil.",
|
||||
"août",
|
||||
"sept.",
|
||||
"oct.",
|
||||
"nov.",
|
||||
"déc."
|
||||
],
|
||||
"top_bar": "{weekday} {day} {month}",
|
||||
"full": "{weekday} {day} {month}",
|
||||
"day_month": "{day} {month}",
|
||||
"weekday_time": "{weekday} {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "Activé",
|
||||
"off": "Désactivé",
|
||||
"climate": {
|
||||
"off": "Éteint",
|
||||
"heat": "Chauffage",
|
||||
"cool": "Climatisation",
|
||||
"heat_cool": "Chauffage/Climatisation",
|
||||
"auto": "Auto",
|
||||
"dry": "Déshumidification",
|
||||
"fan_only": "Ventilation uniquement"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "Chauffe",
|
||||
"cooling": "Rafraîchit",
|
||||
"idle": "Inactif",
|
||||
"off": "Éteint",
|
||||
"drying": "Déshumidifie",
|
||||
"fan": "Ventile",
|
||||
"preheating": "Préchauffage",
|
||||
"defrosting": "Dégivrage"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Ouvert",
|
||||
"closed": "Fermé",
|
||||
"opening": "Ouverture",
|
||||
"closing": "Fermeture"
|
||||
},
|
||||
"media": {
|
||||
"playing": "Lecture en cours",
|
||||
"paused": "En pause",
|
||||
"idle": "Inactif",
|
||||
"standby": "En veille"
|
||||
},
|
||||
"person": {
|
||||
"home": "Maison",
|
||||
"not_home": "Absent"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Au-dessus de l'horizon",
|
||||
"below_horizon": "Sous l'horizon"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "À la station d'accueil",
|
||||
"cleaning": "Nettoyage",
|
||||
"paused": "En pause",
|
||||
"returning": "Retour à la station d'accueil",
|
||||
"idle": "Inactif"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Ensoleillé",
|
||||
"clear_night": "Nuit dégagée",
|
||||
"cloudy": "Nuageux",
|
||||
"partlycloudy": "Éclaircies",
|
||||
"rainy": "Pluvieux",
|
||||
"pouring": "Averses",
|
||||
"snowy": "Neigeux",
|
||||
"snowy_rainy": "Neigeux, pluvieux",
|
||||
"fog": "Brouillard",
|
||||
"hail": "Grêle",
|
||||
"lightning": "Orage",
|
||||
"lightning_rainy": "Orage / Pluie",
|
||||
"windy": "Venteux",
|
||||
"exceptional": "Exceptionnel"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Faible",
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "En charge",
|
||||
"battery_charging_off": "Pas en charge",
|
||||
"carbon_monoxide_on": "Détecté",
|
||||
"carbon_monoxide_off": "Non détecté",
|
||||
"cold_on": "Froid",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Connecté",
|
||||
"connectivity_off": "Déconnecté",
|
||||
"door_on": "Ouvert",
|
||||
"door_off": "Fermé",
|
||||
"garage_door_on": "Ouvert",
|
||||
"garage_door_off": "Fermé",
|
||||
"gas_on": "Détecté",
|
||||
"gas_off": "Non détecté",
|
||||
"heat_on": "Chaud",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Lumière détectée",
|
||||
"light_off": "Pas de lumière",
|
||||
"lock_on": "Déverrouillé",
|
||||
"lock_off": "Verrouillé",
|
||||
"moisture_on": "Humide",
|
||||
"moisture_off": "Sec",
|
||||
"motion_on": "Détecté",
|
||||
"motion_off": "Non détecté",
|
||||
"moving_on": "En mouvement",
|
||||
"moving_off": "Immobile",
|
||||
"occupancy_on": "Détecté",
|
||||
"occupancy_off": "Non détecté",
|
||||
"opening_on": "Ouvert",
|
||||
"opening_off": "Fermé",
|
||||
"plug_on": "Branché",
|
||||
"plug_off": "Débranché",
|
||||
"power_on": "Activé",
|
||||
"power_off": "Désactivé",
|
||||
"presence_on": "Maison",
|
||||
"presence_off": "Absent",
|
||||
"problem_on": "Problème",
|
||||
"problem_off": "OK",
|
||||
"running_on": "En cours",
|
||||
"running_off": "Arrêté",
|
||||
"safety_on": "Dangereux",
|
||||
"safety_off": "Sûr",
|
||||
"smoke_on": "Détectée",
|
||||
"smoke_off": "Non détectée",
|
||||
"sound_on": "Détecté",
|
||||
"sound_off": "Non détecté",
|
||||
"tamper_on": "Manipulation détectée",
|
||||
"tamper_off": "Non détectée",
|
||||
"update_on": "Mise à jour disponible",
|
||||
"update_off": "À jour",
|
||||
"vibration_on": "Détectée",
|
||||
"vibration_off": "Non détectée",
|
||||
"window_on": "Ouvert",
|
||||
"window_off": "Fermé"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Italiano",
|
||||
"english": "Italian",
|
||||
"script": "latin",
|
||||
"plural": "one_other",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": ".",
|
||||
"group_min": "2"
|
||||
},
|
||||
"time": {
|
||||
"am": "AM",
|
||||
"pm": "PM"
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"domenica",
|
||||
"lunedì",
|
||||
"martedì",
|
||||
"mercoledì",
|
||||
"giovedì",
|
||||
"venerdì",
|
||||
"sabato"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"dom",
|
||||
"lun",
|
||||
"mar",
|
||||
"mer",
|
||||
"gio",
|
||||
"ven",
|
||||
"sab"
|
||||
],
|
||||
"weekdays_min": [
|
||||
"dom",
|
||||
"lun",
|
||||
"mar",
|
||||
"mer",
|
||||
"gio",
|
||||
"ven",
|
||||
"sab"
|
||||
],
|
||||
"months": [
|
||||
"gennaio",
|
||||
"febbraio",
|
||||
"marzo",
|
||||
"aprile",
|
||||
"maggio",
|
||||
"giugno",
|
||||
"luglio",
|
||||
"agosto",
|
||||
"settembre",
|
||||
"ottobre",
|
||||
"novembre",
|
||||
"dicembre"
|
||||
],
|
||||
"months_short": [
|
||||
"gen",
|
||||
"feb",
|
||||
"mar",
|
||||
"apr",
|
||||
"mag",
|
||||
"giu",
|
||||
"lug",
|
||||
"ago",
|
||||
"set",
|
||||
"ott",
|
||||
"nov",
|
||||
"dic"
|
||||
],
|
||||
"top_bar": "{weekday} {day} {month}",
|
||||
"full": "{weekday} {day} {month}",
|
||||
"day_month": "{day} {month}",
|
||||
"weekday_time": "{weekday} {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "Acceso",
|
||||
"off": "Spento",
|
||||
"climate": {
|
||||
"off": "Spento",
|
||||
"heat": "Riscaldamento",
|
||||
"cool": "Freddo",
|
||||
"heat_cool": "Caldo/Freddo",
|
||||
"auto": "Automatico",
|
||||
"dry": "Deumidificazione",
|
||||
"fan_only": "Ventilazione"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "Riscaldamento",
|
||||
"cooling": "Raffreddando",
|
||||
"idle": "Inattivo",
|
||||
"off": "Spento",
|
||||
"drying": "In deumidificazione",
|
||||
"fan": "Ventilatore",
|
||||
"preheating": "Preriscaldamento",
|
||||
"defrosting": "Defrosting"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Aperto",
|
||||
"closed": "Chiuso",
|
||||
"opening": "In apertura",
|
||||
"closing": "In chiusura"
|
||||
},
|
||||
"media": {
|
||||
"playing": "In esecuzione",
|
||||
"paused": "In pausa",
|
||||
"idle": "Inattivo",
|
||||
"standby": "In attesa"
|
||||
},
|
||||
"person": {
|
||||
"home": "In casa",
|
||||
"not_home": "Fuori casa"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Sopra l'orizzonte",
|
||||
"below_horizon": "Sotto l'orizzonte"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "Alla base",
|
||||
"cleaning": "In pulizia",
|
||||
"paused": "In pausa",
|
||||
"returning": "Ritornando alla base",
|
||||
"idle": "Inattivo"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Soleggiato",
|
||||
"clear_night": "Sereno, notte",
|
||||
"cloudy": "Nuvoloso",
|
||||
"partlycloudy": "Parzialmente nuvoloso",
|
||||
"rainy": "Piovoso",
|
||||
"pouring": "Rovescio",
|
||||
"snowy": "Nevoso",
|
||||
"snowy_rainy": "Nevoso, piovoso",
|
||||
"fog": "Nebbia",
|
||||
"hail": "Grandine",
|
||||
"lightning": "Temporale",
|
||||
"lightning_rainy": "Temporale, piovoso",
|
||||
"windy": "Ventoso",
|
||||
"exceptional": "Eccezionale"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Basso/a",
|
||||
"battery_off": "Normale",
|
||||
"battery_charging_on": "In carica",
|
||||
"battery_charging_off": "Non in carica",
|
||||
"carbon_monoxide_on": "Rilevato",
|
||||
"carbon_monoxide_off": "Assente",
|
||||
"cold_on": "Freddo",
|
||||
"cold_off": "Normale",
|
||||
"connectivity_on": "Connesso",
|
||||
"connectivity_off": "Disconnesso",
|
||||
"door_on": "Aperto",
|
||||
"door_off": "Chiuso",
|
||||
"garage_door_on": "Aperto",
|
||||
"garage_door_off": "Chiuso",
|
||||
"gas_on": "Rilevato",
|
||||
"gas_off": "Assente",
|
||||
"heat_on": "Caldo",
|
||||
"heat_off": "Normale",
|
||||
"light_on": "Luce rilevata",
|
||||
"light_off": "Nessuna luce",
|
||||
"lock_on": "Sbloccato/a",
|
||||
"lock_off": "Bloccato/a",
|
||||
"moisture_on": "Bagnato",
|
||||
"moisture_off": "Asciutto",
|
||||
"motion_on": "Rilevato",
|
||||
"motion_off": "Assente",
|
||||
"moving_on": "In movimento",
|
||||
"moving_off": "Non si muove",
|
||||
"occupancy_on": "Rilevato",
|
||||
"occupancy_off": "Assente",
|
||||
"opening_on": "Aperto",
|
||||
"opening_off": "Chiuso",
|
||||
"plug_on": "Collegato",
|
||||
"plug_off": "Scollegato",
|
||||
"power_on": "Acceso",
|
||||
"power_off": "Spento",
|
||||
"presence_on": "In casa",
|
||||
"presence_off": "Fuori casa",
|
||||
"problem_on": "Problema",
|
||||
"problem_off": "OK",
|
||||
"running_on": "In esecuzione",
|
||||
"running_off": "Non in esecuzione",
|
||||
"safety_on": "Non Sicuro",
|
||||
"safety_off": "Sicuro",
|
||||
"smoke_on": "Rilevato",
|
||||
"smoke_off": "Assente",
|
||||
"sound_on": "Rilevato",
|
||||
"sound_off": "Assente",
|
||||
"tamper_on": "Rilevata manomissione",
|
||||
"tamper_off": "Assente",
|
||||
"update_on": "Aggiornamento disponibile",
|
||||
"update_off": "Aggiornato",
|
||||
"vibration_on": "Rilevato",
|
||||
"vibration_off": "Assente",
|
||||
"window_on": "Aperto",
|
||||
"window_off": "Chiuso"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Nederlands",
|
||||
"english": "Dutch",
|
||||
"script": "latin",
|
||||
"plural": "one_other",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": ".",
|
||||
"group_min": "1"
|
||||
},
|
||||
"time": {
|
||||
"am": "a.m.",
|
||||
"pm": "p.m."
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"zondag",
|
||||
"maandag",
|
||||
"dinsdag",
|
||||
"woensdag",
|
||||
"donderdag",
|
||||
"vrijdag",
|
||||
"zaterdag"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"zo",
|
||||
"ma",
|
||||
"di",
|
||||
"wo",
|
||||
"do",
|
||||
"vr",
|
||||
"za"
|
||||
],
|
||||
"weekdays_min": [
|
||||
"zo",
|
||||
"ma",
|
||||
"di",
|
||||
"wo",
|
||||
"do",
|
||||
"vr",
|
||||
"za"
|
||||
],
|
||||
"months": [
|
||||
"januari",
|
||||
"februari",
|
||||
"maart",
|
||||
"april",
|
||||
"mei",
|
||||
"juni",
|
||||
"juli",
|
||||
"augustus",
|
||||
"september",
|
||||
"oktober",
|
||||
"november",
|
||||
"december"
|
||||
],
|
||||
"months_short": [
|
||||
"jan",
|
||||
"feb",
|
||||
"mrt",
|
||||
"apr",
|
||||
"mei",
|
||||
"jun",
|
||||
"jul",
|
||||
"aug",
|
||||
"sep",
|
||||
"okt",
|
||||
"nov",
|
||||
"dec"
|
||||
],
|
||||
"top_bar": "{weekday} {day} {month}",
|
||||
"full": "{weekday} {day} {month}",
|
||||
"day_month": "{day} {month}",
|
||||
"weekday_time": "{weekday} {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "Aan",
|
||||
"off": "Uit",
|
||||
"climate": {
|
||||
"off": "Uit",
|
||||
"heat": "Verwarmen",
|
||||
"cool": "Koelen",
|
||||
"heat_cool": "Verwarmen/koelen",
|
||||
"auto": "Automatisch",
|
||||
"dry": "Droog",
|
||||
"fan_only": "Alleen ventilator"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "Verwarmen",
|
||||
"cooling": "Koelen",
|
||||
"idle": "Inactief",
|
||||
"off": "Uit",
|
||||
"drying": "Drogen",
|
||||
"fan": "Ventilator",
|
||||
"preheating": "Voorverwarmen",
|
||||
"defrosting": "Ontdooien"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Open",
|
||||
"closed": "Dicht",
|
||||
"opening": "Openen",
|
||||
"closing": "Sluiten"
|
||||
},
|
||||
"media": {
|
||||
"playing": "Speelt",
|
||||
"paused": "Gepauzeerd",
|
||||
"idle": "Inactief",
|
||||
"standby": "Stand-by"
|
||||
},
|
||||
"person": {
|
||||
"home": "Thuis",
|
||||
"not_home": "Afwezig"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Boven de horizon",
|
||||
"below_horizon": "Onder de horizon"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "Gedockt",
|
||||
"cleaning": "Schoonmaken",
|
||||
"paused": "Gepauzeerd",
|
||||
"returning": "Terugkeren naar dock",
|
||||
"idle": "Inactief"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Zonnig",
|
||||
"clear_night": "Helder, nacht",
|
||||
"cloudy": "Bewolkt",
|
||||
"partlycloudy": "Half bewolkt",
|
||||
"rainy": "Regenachtig",
|
||||
"pouring": "Regen",
|
||||
"snowy": "Sneeuwachtig",
|
||||
"snowy_rainy": "Sneeuw-, regenachtig",
|
||||
"fog": "Mist",
|
||||
"hail": "Hagel",
|
||||
"lightning": "Bliksem",
|
||||
"lightning_rainy": "Bliksem, regenachtig",
|
||||
"windy": "Winderig",
|
||||
"exceptional": "Uitzonderlijk"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Laag",
|
||||
"battery_off": "Normaal",
|
||||
"battery_charging_on": "Opladen",
|
||||
"battery_charging_off": "Niet aan het opladen",
|
||||
"carbon_monoxide_on": "Gedetecteerd",
|
||||
"carbon_monoxide_off": "Niet gedetecteerd",
|
||||
"cold_on": "Koud",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Verbonden",
|
||||
"connectivity_off": "Verbroken",
|
||||
"door_on": "Open",
|
||||
"door_off": "Dicht",
|
||||
"garage_door_on": "Open",
|
||||
"garage_door_off": "Dicht",
|
||||
"gas_on": "Gedetecteerd",
|
||||
"gas_off": "Niet gedetecteerd",
|
||||
"heat_on": "Heet",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Licht gedetecteerd",
|
||||
"light_off": "Geen licht",
|
||||
"lock_on": "Ontgrendeld",
|
||||
"lock_off": "Vergrendeld",
|
||||
"moisture_on": "Nat",
|
||||
"moisture_off": "Droog",
|
||||
"motion_on": "Gedetecteerd",
|
||||
"motion_off": "Niet gedetecteerd",
|
||||
"moving_on": "Beweging",
|
||||
"moving_off": "Geen beweging",
|
||||
"occupancy_on": "Gedetecteerd",
|
||||
"occupancy_off": "Niet gedetecteerd",
|
||||
"opening_on": "Open",
|
||||
"opening_off": "Dicht",
|
||||
"plug_on": "Ingeplugd",
|
||||
"plug_off": "Losgekoppeld",
|
||||
"power_on": "Aan",
|
||||
"power_off": "Uit",
|
||||
"presence_on": "Thuis",
|
||||
"presence_off": "Afwezig",
|
||||
"problem_on": "Probleem",
|
||||
"problem_off": "OK",
|
||||
"running_on": "Actief",
|
||||
"running_off": "Niet actief",
|
||||
"safety_on": "Onveilig",
|
||||
"safety_off": "Veilig",
|
||||
"smoke_on": "Gedetecteerd",
|
||||
"smoke_off": "Niet gedetecteerd",
|
||||
"sound_on": "Gedetecteerd",
|
||||
"sound_off": "Niet gedetecteerd",
|
||||
"tamper_on": "Sabotage ontdekt",
|
||||
"tamper_off": "Niet gedetecteerd",
|
||||
"update_on": "Update beschikbaar",
|
||||
"update_off": "Up-to-date",
|
||||
"vibration_on": "Gedetecteerd",
|
||||
"vibration_off": "Niet gedetecteerd",
|
||||
"window_on": "Open",
|
||||
"window_off": "Dicht"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Polski",
|
||||
"english": "Polish",
|
||||
"script": "latin",
|
||||
"plural": "slavic_pl",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": " ",
|
||||
"group_min": "2"
|
||||
},
|
||||
"time": {
|
||||
"am": "AM",
|
||||
"pm": "PM"
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"niedziela",
|
||||
"poniedziałek",
|
||||
"wtorek",
|
||||
"środa",
|
||||
"czwartek",
|
||||
"piątek",
|
||||
"sobota"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"niedz.",
|
||||
"pon.",
|
||||
"wt.",
|
||||
"śr.",
|
||||
"czw.",
|
||||
"pt.",
|
||||
"sob."
|
||||
],
|
||||
"weekdays_min": [
|
||||
"niedz.",
|
||||
"pon.",
|
||||
"wt.",
|
||||
"śr.",
|
||||
"czw.",
|
||||
"pt.",
|
||||
"sob."
|
||||
],
|
||||
"months": [
|
||||
"stycznia",
|
||||
"lutego",
|
||||
"marca",
|
||||
"kwietnia",
|
||||
"maja",
|
||||
"czerwca",
|
||||
"lipca",
|
||||
"sierpnia",
|
||||
"września",
|
||||
"października",
|
||||
"listopada",
|
||||
"grudnia"
|
||||
],
|
||||
"months_short": [
|
||||
"sty",
|
||||
"lut",
|
||||
"mar",
|
||||
"kwi",
|
||||
"maj",
|
||||
"cze",
|
||||
"lip",
|
||||
"sie",
|
||||
"wrz",
|
||||
"paź",
|
||||
"lis",
|
||||
"gru"
|
||||
],
|
||||
"top_bar": "{weekday}, {day} {month}",
|
||||
"full": "{weekday}, {day} {month}",
|
||||
"day_month": "{day} {month}",
|
||||
"weekday_time": "{weekday}, {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "włączono",
|
||||
"off": "wyłączono",
|
||||
"climate": {
|
||||
"off": "wyłączono",
|
||||
"heat": "grzanie",
|
||||
"cool": "chłodzenie",
|
||||
"heat_cool": "grzanie/chłodzenie",
|
||||
"auto": "Auto",
|
||||
"dry": "osuszanie",
|
||||
"fan_only": "tylko wentylator"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "grzanie",
|
||||
"cooling": "chłodzenie",
|
||||
"idle": "brak aktywności",
|
||||
"off": "wyłączono",
|
||||
"drying": "osuszanie",
|
||||
"fan": "wentylator",
|
||||
"preheating": "podgrzewanie wstępne",
|
||||
"defrosting": "rozmrażanie"
|
||||
},
|
||||
"cover": {
|
||||
"open": "otwarto",
|
||||
"closed": "zamknięto",
|
||||
"opening": "otwieranie",
|
||||
"closing": "zamykanie"
|
||||
},
|
||||
"media": {
|
||||
"playing": "odtwarzanie",
|
||||
"paused": "wstrzymano",
|
||||
"idle": "brak aktywności",
|
||||
"standby": "tryb czuwania"
|
||||
},
|
||||
"person": {
|
||||
"home": "w domu",
|
||||
"not_home": "poza domem"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "powyżej horyzontu",
|
||||
"below_horizon": "poniżej horyzontu"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "zadokowany",
|
||||
"cleaning": "sprzątanie",
|
||||
"paused": "wstrzymano",
|
||||
"returning": "wraca do stacji dokującej",
|
||||
"idle": "brak aktywności"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "słonecznie",
|
||||
"clear_night": "pogodna noc",
|
||||
"cloudy": "pochmurno",
|
||||
"partlycloudy": "częściowe zachmurzenie",
|
||||
"rainy": "deszczowo",
|
||||
"pouring": "ulewa",
|
||||
"snowy": "opady śniegu",
|
||||
"snowy_rainy": "deszcz ze śniegiem",
|
||||
"fog": "mgła",
|
||||
"hail": "grad",
|
||||
"lightning": "wyładowania atmosferyczne",
|
||||
"lightning_rainy": "burza",
|
||||
"windy": "wietrznie",
|
||||
"exceptional": "warunki nadzwyczajne"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Low",
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "Charging",
|
||||
"battery_charging_off": "brak ładowania",
|
||||
"carbon_monoxide_on": "wykryto",
|
||||
"carbon_monoxide_off": "brak",
|
||||
"cold_on": "zimno",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "połączono",
|
||||
"connectivity_off": "rozłączono",
|
||||
"door_on": "otwarto",
|
||||
"door_off": "zamknięto",
|
||||
"garage_door_on": "otwarto",
|
||||
"garage_door_off": "zamknięto",
|
||||
"gas_on": "wykryto",
|
||||
"gas_off": "brak",
|
||||
"heat_on": "gorąco",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "wykryto",
|
||||
"light_off": "brak",
|
||||
"lock_on": "odblokowano",
|
||||
"lock_off": "zablokowano",
|
||||
"moisture_on": "wykryto",
|
||||
"moisture_off": "brak",
|
||||
"motion_on": "wykryto",
|
||||
"motion_off": "brak",
|
||||
"moving_on": "w ruchu",
|
||||
"moving_off": "brak ruchu",
|
||||
"occupancy_on": "wykryto",
|
||||
"occupancy_off": "brak",
|
||||
"opening_on": "otwarto",
|
||||
"opening_off": "zamknięto",
|
||||
"plug_on": "podłączono",
|
||||
"plug_off": "odłączono",
|
||||
"power_on": "włączono",
|
||||
"power_off": "wyłączono",
|
||||
"presence_on": "Home",
|
||||
"presence_off": "Away",
|
||||
"problem_on": "problem",
|
||||
"problem_off": "ok",
|
||||
"running_on": "działa",
|
||||
"running_off": "nie działa",
|
||||
"safety_on": "zagrożenie",
|
||||
"safety_off": "brak zagrożenia",
|
||||
"smoke_on": "wykryto",
|
||||
"smoke_off": "brak",
|
||||
"sound_on": "wykryto",
|
||||
"sound_off": "brak",
|
||||
"tamper_on": "Tampering detected",
|
||||
"tamper_off": "brak",
|
||||
"update_on": "dostępna aktualizacja",
|
||||
"update_off": "brak aktualizacji",
|
||||
"vibration_on": "wykryto",
|
||||
"vibration_off": "brak",
|
||||
"window_on": "otwarto",
|
||||
"window_off": "zamknięto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"_meta": {
|
||||
"name": "Português",
|
||||
"english": "Portuguese",
|
||||
"script": "latin",
|
||||
"plural": "one_upto_1",
|
||||
"clock": "24",
|
||||
"checked": false
|
||||
},
|
||||
"screen": {
|
||||
"number": {
|
||||
"decimal": ",",
|
||||
"group": " ",
|
||||
"group_min": "2"
|
||||
},
|
||||
"time": {
|
||||
"am": "da manhã",
|
||||
"pm": "da tarde"
|
||||
},
|
||||
"date": {
|
||||
"weekdays": [
|
||||
"domingo",
|
||||
"segunda-feira",
|
||||
"terça-feira",
|
||||
"quarta-feira",
|
||||
"quinta-feira",
|
||||
"sexta-feira",
|
||||
"sábado"
|
||||
],
|
||||
"weekdays_short": [
|
||||
"domingo",
|
||||
"segunda",
|
||||
"terça",
|
||||
"quarta",
|
||||
"quinta",
|
||||
"sexta",
|
||||
"sábado"
|
||||
],
|
||||
"weekdays_min": [
|
||||
"domingo",
|
||||
"segunda",
|
||||
"terça",
|
||||
"quarta",
|
||||
"quinta",
|
||||
"sexta",
|
||||
"sábado"
|
||||
],
|
||||
"months": [
|
||||
"janeiro",
|
||||
"fevereiro",
|
||||
"março",
|
||||
"abril",
|
||||
"maio",
|
||||
"junho",
|
||||
"julho",
|
||||
"agosto",
|
||||
"setembro",
|
||||
"outubro",
|
||||
"novembro",
|
||||
"dezembro"
|
||||
],
|
||||
"months_short": [
|
||||
"jan.",
|
||||
"fev.",
|
||||
"mar.",
|
||||
"abr.",
|
||||
"mai.",
|
||||
"jun.",
|
||||
"jul.",
|
||||
"ago.",
|
||||
"set.",
|
||||
"out.",
|
||||
"nov.",
|
||||
"dez."
|
||||
],
|
||||
"top_bar": "{weekday}, {day} {month}",
|
||||
"full": "{weekday}, {day} de {month}",
|
||||
"day_month": "{day} {month}",
|
||||
"weekday_time": "{weekday}, {time}"
|
||||
},
|
||||
"ha": {
|
||||
"on": "Ligado",
|
||||
"off": "Desligado",
|
||||
"climate": {
|
||||
"off": "Desligado",
|
||||
"heat": "Aquecer",
|
||||
"cool": "Arrefecer",
|
||||
"heat_cool": "Aquecer/Arrefecer",
|
||||
"auto": "Auto",
|
||||
"dry": "Secar",
|
||||
"fan_only": "Ventilação"
|
||||
},
|
||||
"hvac_action": {
|
||||
"heating": "A aquecer",
|
||||
"cooling": "A arrefecer",
|
||||
"idle": "Inativo",
|
||||
"off": "Desligado",
|
||||
"drying": "Desumidificação",
|
||||
"fan": "Ventilação",
|
||||
"preheating": "Pré-Aquecimento",
|
||||
"defrosting": "Descongelação"
|
||||
},
|
||||
"cover": {
|
||||
"open": "Aberta",
|
||||
"closed": "Fechado",
|
||||
"opening": "A abrir",
|
||||
"closing": "A fechar"
|
||||
},
|
||||
"media": {
|
||||
"playing": "A reproduzir",
|
||||
"paused": "Pausado",
|
||||
"idle": "Inativo",
|
||||
"standby": "Standby"
|
||||
},
|
||||
"person": {
|
||||
"home": "Casa",
|
||||
"not_home": "Ausente"
|
||||
},
|
||||
"sun": {
|
||||
"above_horizon": "Acima do horizonte",
|
||||
"below_horizon": "Abaixo do horizonte"
|
||||
},
|
||||
"vacuum": {
|
||||
"docked": "Na Base",
|
||||
"cleaning": "A Limpar",
|
||||
"paused": "Em pausa",
|
||||
"returning": "A regressar à base",
|
||||
"idle": "Inativo"
|
||||
},
|
||||
"weather": {
|
||||
"sunny": "Ensolarado",
|
||||
"clear_night": "Limpo, noite",
|
||||
"cloudy": "Nublado",
|
||||
"partlycloudy": "Parcialmente nublado",
|
||||
"rainy": "Chuvoso",
|
||||
"pouring": "Aguaceiros",
|
||||
"snowy": "Nevoso",
|
||||
"snowy_rainy": "Nevoso, chuvoso",
|
||||
"fog": "Nevoeiro",
|
||||
"hail": "Granizo",
|
||||
"lightning": "Trovoada",
|
||||
"lightning_rainy": "Trovoada, chuva",
|
||||
"windy": "Ventoso",
|
||||
"exceptional": "Excecional"
|
||||
},
|
||||
"binary": {
|
||||
"battery_on": "Baixo",
|
||||
"battery_off": "Normal",
|
||||
"battery_charging_on": "A carregar",
|
||||
"battery_charging_off": "Não está a carregar",
|
||||
"carbon_monoxide_on": "Detetado",
|
||||
"carbon_monoxide_off": "Limpo",
|
||||
"cold_on": "Frio",
|
||||
"cold_off": "Normal",
|
||||
"connectivity_on": "Ligado",
|
||||
"connectivity_off": "Desligado",
|
||||
"door_on": "Aberto",
|
||||
"door_off": "Fechada",
|
||||
"garage_door_on": "Aberta",
|
||||
"garage_door_off": "Fechado",
|
||||
"gas_on": "Detetado",
|
||||
"gas_off": "Limpo",
|
||||
"heat_on": "Quente",
|
||||
"heat_off": "Normal",
|
||||
"light_on": "Luz detetada",
|
||||
"light_off": "Sem luz",
|
||||
"lock_on": "Destrancada",
|
||||
"lock_off": "Trancado",
|
||||
"moisture_on": "Húmido",
|
||||
"moisture_off": "Seco",
|
||||
"motion_on": "Detetado",
|
||||
"motion_off": "Limpo",
|
||||
"moving_on": "Em movimento",
|
||||
"moving_off": "Parado",
|
||||
"occupancy_on": "Detetado",
|
||||
"occupancy_off": "Limpo",
|
||||
"opening_on": "Aberta",
|
||||
"opening_off": "Fechada",
|
||||
"plug_on": "Ligado",
|
||||
"plug_off": "Desligado",
|
||||
"power_on": "Detetado",
|
||||
"power_off": "Desligado",
|
||||
"presence_on": "Em casa",
|
||||
"presence_off": "Ausente",
|
||||
"problem_on": "Problema",
|
||||
"problem_off": "OK",
|
||||
"running_on": "Em execução",
|
||||
"running_off": "Parado",
|
||||
"safety_on": "Inseguro",
|
||||
"safety_off": "Seguro",
|
||||
"smoke_on": "Detetado",
|
||||
"smoke_off": "Limpo",
|
||||
"sound_on": "Detetado",
|
||||
"sound_off": "Limpo",
|
||||
"tamper_on": "Adulteração detetada",
|
||||
"tamper_off": "Limpo",
|
||||
"update_on": "Atualização disponível",
|
||||
"update_off": "Atualizado",
|
||||
"vibration_on": "Detetado",
|
||||
"vibration_off": "Limpo",
|
||||
"window_on": "Aberto",
|
||||
"window_off": "Fechada"
|
||||
}
|
||||
}
|
||||
},
|
||||
"addon": {},
|
||||
"editor": {}
|
||||
}
|
||||
+29
-26
@@ -3,11 +3,12 @@
|
||||
#pragma once
|
||||
#include "components/smart_display/screen_text.h"
|
||||
|
||||
static_assert(screen_text::KEYS_HASH == 0x725A92EEu && screen_text::KEY_COUNT == 302,
|
||||
static_assert(screen_text::KEYS_HASH == 0x8971C0EBu && screen_text::KEY_COUNT == 305,
|
||||
"screen_text_keys.h does not match screen_manager/translations/en.json: run tools/i18n.py header");
|
||||
const char *const screen_text::TABLE[] = {
|
||||
".",
|
||||
",",
|
||||
"1",
|
||||
"Just now",
|
||||
"{n} min ago",
|
||||
"1 hour ago | {n} hours ago",
|
||||
@@ -108,6 +109,8 @@ const char *const screen_text::TABLE[] = {
|
||||
"Firmware",
|
||||
"Home Assistant",
|
||||
"Restart",
|
||||
"Connected",
|
||||
"Not connected",
|
||||
"Tap again to restart",
|
||||
"{n} sec",
|
||||
"{n} min",
|
||||
@@ -231,8 +234,8 @@ const char *const screen_text::TABLE[] = {
|
||||
"Standby",
|
||||
"Home",
|
||||
"Away",
|
||||
"Above the horizon",
|
||||
"Below the horizon",
|
||||
"Above horizon",
|
||||
"Below horizon",
|
||||
"Docked",
|
||||
"Cleaning",
|
||||
"Paused",
|
||||
@@ -256,8 +259,8 @@ const char *const screen_text::TABLE[] = {
|
||||
"Normal",
|
||||
"Charging",
|
||||
"Not charging",
|
||||
"Danger",
|
||||
"Safe",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Cold",
|
||||
"Normal",
|
||||
"Connected",
|
||||
@@ -266,21 +269,21 @@ const char *const screen_text::TABLE[] = {
|
||||
"Closed",
|
||||
"Open",
|
||||
"Closed",
|
||||
"Danger",
|
||||
"Safe",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Hot",
|
||||
"Normal",
|
||||
"Light",
|
||||
"Dark",
|
||||
"Open",
|
||||
"Light detected",
|
||||
"No light",
|
||||
"Unlocked",
|
||||
"Locked",
|
||||
"Wet",
|
||||
"Dry",
|
||||
"Motion",
|
||||
"No motion",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Moving",
|
||||
"Still",
|
||||
"Occupied",
|
||||
"Not moving",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Open",
|
||||
"Closed",
|
||||
@@ -292,20 +295,20 @@ const char *const screen_text::TABLE[] = {
|
||||
"Away",
|
||||
"Problem",
|
||||
"OK",
|
||||
"Active",
|
||||
"Inactive",
|
||||
"Running",
|
||||
"Not running",
|
||||
"Unsafe",
|
||||
"Safe",
|
||||
"Smoke",
|
||||
"No smoke",
|
||||
"Sound",
|
||||
"Silent",
|
||||
"Tampering",
|
||||
"OK",
|
||||
"Update",
|
||||
"Up to date",
|
||||
"Vibration",
|
||||
"Still",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Tampering detected",
|
||||
"Clear",
|
||||
"Update available",
|
||||
"Up-to-date",
|
||||
"Detected",
|
||||
"Clear",
|
||||
"Open",
|
||||
"Closed"
|
||||
};
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "screen_text_en.h"
|
||||
// The screen's texts (app 0.2.90): lookups, placeholders, plural forms and numbers, with the English table the tests
|
||||
// build with (tests/screen_text_en.h). A screen's own build writes its language's table instead.
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
using namespace screen_text;
|
||||
|
||||
int main() {
|
||||
assert(std::string(LANGUAGE) == "en");
|
||||
assert(std::string(tr(txt::settings_title)) == "Settings");
|
||||
assert(std::string(tr(KEY_COUNT)) == "" && std::string(tr(0xFFFF)) == "");
|
||||
// A list is its first key plus a count: the month names in order.
|
||||
assert(txt::date_months_short_count == 12 && std::string(tr(txt::date_months_short + 8)) == "Sep");
|
||||
assert(txt::date_weekdays_count == 7 && std::string(tr(txt::date_weekdays)) == "Sunday");
|
||||
|
||||
// Named placeholders, every occurrence; a translation is never a printf format.
|
||||
assert(fill(std::string("{n} of {n}"), "n", "3") == "3 of 3");
|
||||
assert(fill(txt::tile_page, "n", 2) == "Page 2");
|
||||
assert(fill(std::string("100%"), "n", "1") == "100%");
|
||||
|
||||
// Plural forms by the language's rule (English: one for 1, other for the rest); the one form may name the number.
|
||||
assert(plural(txt::time_hours_ago, 1) == "1 hour ago" && plural(txt::time_hours_ago, 2) == "2 hours ago");
|
||||
assert(plural(txt::time_hours_ago, 0) == "0 hours ago" && plural(txt::history_times, 1) == "once");
|
||||
assert(plural(txt::history_times, 21) == "21 times");
|
||||
// A text without forms is the same for every n.
|
||||
assert(plural(txt::time_minutes_ago, 5) == "5 min ago");
|
||||
|
||||
// Numbers: the language's marks unless Settings -> Language & region chose a format for every screen.
|
||||
number_style = 0;
|
||||
assert(localize("1234.5") == "1,234.5" && localize("-3") == "-3" && localize("123") == "123");
|
||||
assert(localize("1234567") == "1,234,567" && localize("0.25") == "0.25");
|
||||
for (const char *text : {"on", "1.2.3", "-", ".5", "5.", "12a", "", "1e5"}) assert(localize(text) == text);
|
||||
assert(decimal(21.54f, 1) == "21.5");
|
||||
number_style = 2; // 1.234,5
|
||||
assert(localize("1234.5") == "1.234,5" && localize("-1234") == "-1.234" && decimal(21.54f, 1) == "21,5");
|
||||
number_style = 3; // 1 234,5
|
||||
assert(localize("12345.75") == "12 345,75");
|
||||
number_style = 1; // 1,234.5
|
||||
assert(localize("1234.5") == "1,234.5");
|
||||
assert(number_style_of("auto") == 0 && number_style_of("point") == 1 && number_style_of("comma") == 2 &&
|
||||
number_style_of("space") == 3 && number_style_of("dot") == -1);
|
||||
number_style = 0;
|
||||
std::puts("test_screen_text: PASS");
|
||||
return 0;
|
||||
}
|
||||
@@ -184,9 +184,10 @@ int main() {
|
||||
rows = vacuum_rows(old_robot2, 0);
|
||||
assert(rows.suction && !rows.water && !choice_action(old_robot2, 'm', "mop").valid());
|
||||
|
||||
// Binary sensors (firmware 0.2.53+) in the words of their device class; no class or an unknown one says On and Off.
|
||||
// Binary sensors (firmware 0.2.53+) in the words of their device class, Home Assistant's own since app 0.2.90 (the
|
||||
// English table of the tests); no class or an unknown one says On and Off.
|
||||
assert(!strcmp(binary_state_text("door", true), "Open") && !strcmp(binary_state_text("door", false), "Closed"));
|
||||
assert(!strcmp(binary_state_text("motion", true), "Motion") && !strcmp(binary_state_text("motion", false), "No motion"));
|
||||
assert(!strcmp(binary_state_text("motion", true), "Detected") && !strcmp(binary_state_text("motion", false), "Clear"));
|
||||
assert(!strcmp(binary_state_text("moisture", true), "Wet") && !strcmp(binary_state_text("moisture", false), "Dry"));
|
||||
assert(!strcmp(binary_state_text("battery_charging", false), "Not charging") && !strcmp(binary_state_text("battery", true), "Low"));
|
||||
assert(!strcmp(binary_state_text("", true), "On") && !strcmp(binary_state_text("", false), "Off"));
|
||||
|
||||
+213
-4
@@ -3,10 +3,15 @@
|
||||
|
||||
python3 tools/i18n.py check every language against English: keys, placeholders, plural forms, letters
|
||||
the screens can't draw, screen texts much longer than the English
|
||||
python3 tools/i18n.py lint English words left in the firmware's code instead of the translations
|
||||
python3 tools/i18n.py header [--check] write (or compare) the key header and the tests' English table that the
|
||||
firmware's `screen` texts need, after changing the keys of en.json
|
||||
python3 tools/i18n.py cldr [--write] day and month names, date orders and the decimal mark from the Unicode CLDR
|
||||
(Node's Intl), into every language's screen.date and screen.number
|
||||
python3 tools/i18n.py ha-words [--write] Home Assistant's own words for states (screen.ha) in every language, from a
|
||||
Home Assistant (HA_URL and HA_TOKEN); needs aiohttp
|
||||
python3 tools/i18n.py new CODE NAME ENGLISH PLURAL
|
||||
a new language file, such as `new sv Svenska Swedish one_other`
|
||||
"""
|
||||
import argparse
|
||||
import importlib.util
|
||||
@@ -105,10 +110,13 @@ def check():
|
||||
if plural and forms and len(text.split('|')) not in (1, forms):
|
||||
problems.append(f'{code}: {key} needs {forms} forms separated by " | "')
|
||||
if key.startswith('screen.') and drawable:
|
||||
unknown = sorted(set(text) - drawable - {'\n'})
|
||||
shown = PLACEHOLDER.sub('', text).replace('|', '')
|
||||
unknown = sorted(set(shown) - drawable - {'\n'})
|
||||
if unknown:
|
||||
problems.append(f'{code}: {key} uses letters the screens can\'t draw: {"".join(unknown)}')
|
||||
if code != 'en' and len(text) > max(8, len(source) * 1.6) and not plural:
|
||||
# Home Assistant's words and the calendar's are what they are; our own texts should stay about as short.
|
||||
ours = not key.startswith(('screen.ha.', 'screen.date.', 'screen.number.'))
|
||||
if ours and code != 'en' and len(text) > max(8, len(source) * 1.6) and not plural:
|
||||
notes.append(f'{code}: {key} is much longer than the English ({len(text)} vs {len(source)})')
|
||||
for line in notes:
|
||||
print('note:', line)
|
||||
@@ -118,26 +126,227 @@ def check():
|
||||
return 1 if problems else 0
|
||||
|
||||
|
||||
# English that stays in the firmware on purpose, with why. Everything else a screen shows comes from the translations,
|
||||
# and `lint` fails on a new English text in the code, so it never slips back in.
|
||||
LINT_KEEP = {
|
||||
# Statuses the app reads and acts on (screen_manager/app/server.py RESEND_STATES, the "Error" prefix): protocol.
|
||||
'Synced', 'Loading tiles', 'Layout received', 'Resend needed', 'Ready for tile configuration',
|
||||
'Use the Easy Setup profile', 'Swipe test started', 'no answer', 'Error: message too large',
|
||||
'Error: invalid message', 'Error: protocol version', 'Error: screen settings', 'Error: outdated tile',
|
||||
'Error: no memory for ', 'Error: incomplete message', 'Error: invalid encoding',
|
||||
# Only a log line or the rate limiter's reason shows these.
|
||||
'history range', 'card button ', 'media key ', 'let go', 'too short (', 'already handled in this contact',
|
||||
'same button within the debounce window', 'no runtime tiles', 'setting off', 'screen dimmed', 'card open',
|
||||
'detail card open', 'camera open', 'USB calibration ready; no tile actions', 'GT911 touch test ready; no tile actions',
|
||||
'UI_TEST START: page/overlay render stress, no HA actions', 'Color', 'Color temperature', 'Brightness',
|
||||
# Home Assistant's own values and units the code compares with, not words it shows.
|
||||
'None', 'Auto', 'Wh',
|
||||
# Placeholders of the YAML tree that the runtime tiles replace before a screen shows them, and profile defaults.
|
||||
'Lamp', 'Plug', 'Evening', 'All off', 'AC', 'Vacuum', 'Tile 7', 'Tile 8', 'Tile 9', 'Tile 10', 'Light', 'Light Color',
|
||||
'Climate', 'Example lamp', 'My CYD', 'My Guition',
|
||||
}
|
||||
LINT_FILES = ('components/smart_display/*.h', 'packages/core.yaml', 'packages/boards/*.yaml')
|
||||
|
||||
|
||||
def lint():
|
||||
"""English words in the firmware's code that should be a key of the translations' `screen` section."""
|
||||
literal = re.compile(r'"((?:[^"\\]|\\.)*)"')
|
||||
found = []
|
||||
for pattern in LINT_FILES:
|
||||
for path in sorted(ROOT.glob(pattern)):
|
||||
for number, line in enumerate(path.read_text(encoding='utf-8').splitlines(), 1):
|
||||
stripped = line.strip()
|
||||
# Comments, logs, and Home Assistant's entity names (renaming one gives it a new entity id).
|
||||
if stripped.startswith(('//', '#', '*')) or 'ESP_LOG' in line or 'static_assert' in line or re.match(r'\s*name: "', line):
|
||||
continue
|
||||
code = line.split('//')[0]
|
||||
if path.suffix == '.yaml':
|
||||
code = re.split(r'\s#', code)[0]
|
||||
for match in literal.finditer(code):
|
||||
text = match.group(1)
|
||||
if text in LINT_KEEP or re.search(r'[();]|::|->|\$\{', text):
|
||||
continue
|
||||
if re.match(r'^[A-Z][a-z]', text) or re.search(r'[A-Za-z]{2,} [a-z]{2,}', text):
|
||||
found.append(f'{path.relative_to(ROOT)}:{number}: "{text}"')
|
||||
for line in found:
|
||||
print('English in the firmware (a key of screen_manager/translations/en.json, or tools/i18n.py LINT_KEEP):', line)
|
||||
return 1 if found else 0
|
||||
|
||||
|
||||
# Where screen.ha's words come from: Home Assistant's own translations (frontend/get_translations, `entity_component`),
|
||||
# so a screen says what Home Assistant says in the same language.
|
||||
def ha_sources():
|
||||
sources = {'on': 'component.switch.entity_component._.state.on', 'off': 'component.switch.entity_component._.state.off'}
|
||||
for mode in ('off', 'heat', 'cool', 'heat_cool', 'auto', 'dry', 'fan_only'):
|
||||
sources[f'climate.{mode}'] = f'component.climate.entity_component._.state.{mode}'
|
||||
for action in ('heating', 'cooling', 'idle', 'off', 'drying', 'fan', 'preheating', 'defrosting'):
|
||||
sources[f'hvac_action.{action}'] = f'component.climate.entity_component._.state_attributes.hvac_action.state.{action}'
|
||||
for state in ('open', 'closed', 'opening', 'closing'):
|
||||
sources[f'cover.{state}'] = f'component.cover.entity_component._.state.{state}'
|
||||
for state in ('playing', 'paused', 'idle', 'standby'):
|
||||
sources[f'media.{state}'] = f'component.media_player.entity_component._.state.{state}'
|
||||
for state in ('home', 'not_home'):
|
||||
sources[f'person.{state}'] = f'component.person.entity_component._.state.{state}'
|
||||
for state in ('above_horizon', 'below_horizon'):
|
||||
sources[f'sun.{state}'] = f'component.sun.entity_component._.state.{state}'
|
||||
for state in ('docked', 'cleaning', 'paused', 'returning', 'idle'):
|
||||
sources[f'vacuum.{state}'] = f'component.vacuum.entity_component._.state.{state}'
|
||||
english = json.loads((FOLDER / 'en.json').read_text(encoding='utf-8'))['screen']['ha']
|
||||
for key in english['weather']:
|
||||
sources[f'weather.{key}'] = f'component.weather.entity_component._.state.{key.replace("_", "-") if key != "partlycloudy" else key}'
|
||||
for key in english['binary']:
|
||||
device_class, state = key.rsplit('_', 1)
|
||||
sources[f'binary.{key}'] = f'component.binary_sensor.entity_component.{device_class}.state.{state}'
|
||||
return sources
|
||||
|
||||
|
||||
def ha_words(write):
|
||||
"""screen.ha of every language from a Home Assistant (HA_URL and HA_TOKEN, or .esphome/ha_url and ha_token): its own
|
||||
words for states, English included, so a screen says what Home Assistant says (Max, app 0.2.90)."""
|
||||
import asyncio
|
||||
import os
|
||||
try:
|
||||
import aiohttp
|
||||
except ImportError:
|
||||
raise SystemExit('ha-words needs aiohttp (.venv-portal/bin/python has it)')
|
||||
def setting(name, file):
|
||||
value = os.environ.get(name)
|
||||
for folder in (ROOT, ROOT.parent / 'esphome-cyd-display'):
|
||||
if not value and (folder / '.esphome' / file).exists():
|
||||
value = (folder / '.esphome' / file).read_text().strip()
|
||||
if not value:
|
||||
raise SystemExit(f'Set {name} or .esphome/{file}')
|
||||
return value
|
||||
url, token = setting('HA_URL', 'ha_url').rstrip('/'), setting('HA_TOKEN', 'ha_token')
|
||||
sources = ha_sources()
|
||||
|
||||
async def fetch(codes):
|
||||
found = {}
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.ws_connect(url.replace('http', 'ws', 1) + '/api/websocket') as ws:
|
||||
await ws.receive_json()
|
||||
await ws.send_json({'type': 'auth', 'access_token': token})
|
||||
if (await ws.receive_json()).get('type') != 'auth_ok':
|
||||
raise SystemExit('Home Assistant refused the token')
|
||||
for number, code in enumerate(codes, 1):
|
||||
await ws.send_json({'id': number, 'type': 'frontend/get_translations', 'language': code, 'category': 'entity_component'})
|
||||
answer = await ws.receive_json()
|
||||
found[code] = (answer.get('result') or {}).get('resources') or {}
|
||||
return found
|
||||
|
||||
langs = languages()
|
||||
found = asyncio.run(fetch(list(langs)))
|
||||
status = 0
|
||||
for code, data in langs.items():
|
||||
words = found.get(code) or {}
|
||||
own = {}
|
||||
for key, source in sources.items():
|
||||
if isinstance(words.get(source), str) and words[source]:
|
||||
own[key] = words[source]
|
||||
else:
|
||||
print(f'{code}: Home Assistant has no {source}')
|
||||
reference = dict(generator().flatten(data.get('screen', {}).get('ha', {})))
|
||||
if code == 'en':
|
||||
for key, word in own.items():
|
||||
if reference.get(key) != word:
|
||||
print(f'en: screen.ha.{key} "{reference.get(key)}" becomes Home Assistant\'s "{word}"')
|
||||
tree = {}
|
||||
for key, word in own.items():
|
||||
node = tree
|
||||
parts = key.split('.')
|
||||
for part in parts[:-1]:
|
||||
node = node.setdefault(part, {})
|
||||
node[parts[-1]] = word
|
||||
before = json.dumps(data, ensure_ascii=False)
|
||||
merge(data.setdefault('screen', {}).setdefault('ha', {}), tree)
|
||||
if json.dumps(data, ensure_ascii=False) != before:
|
||||
print(f'{code}: {"wrote" if write else "would change"} {len(own)} words from Home Assistant')
|
||||
if write:
|
||||
write_language(code, data)
|
||||
return status
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
sub = parser.add_subparsers(dest='command', required=True)
|
||||
sub.add_parser('check')
|
||||
sub.add_parser('lint')
|
||||
head = sub.add_parser('header')
|
||||
head.add_argument('--check', action='store_true')
|
||||
cldr = sub.add_parser('cldr')
|
||||
cldr.add_argument('--write', action='store_true')
|
||||
words = sub.add_parser('ha-words')
|
||||
words.add_argument('--write', action='store_true')
|
||||
fresh = sub.add_parser('new')
|
||||
fresh.add_argument('code')
|
||||
fresh.add_argument('name')
|
||||
fresh.add_argument('english')
|
||||
fresh.add_argument('plural')
|
||||
args = parser.parse_args()
|
||||
if args.command == 'new':
|
||||
return new_language(args.code, args.name, args.english, args.plural)
|
||||
if args.command == 'check':
|
||||
return check()
|
||||
if args.command == 'lint':
|
||||
return lint()
|
||||
if args.command == 'header':
|
||||
return header(args.check)
|
||||
if args.command == 'cldr':
|
||||
return cldr_dates(args.write)
|
||||
if args.command == 'ha-words':
|
||||
return ha_words(args.write)
|
||||
return 2
|
||||
|
||||
|
||||
def cldr_dates(write):
|
||||
raise SystemExit('not yet')
|
||||
# The CLDR locale of a file where it differs: Portuguese is Home Assistant's pt, the one of Portugal.
|
||||
CLDR_LOCALE = {'pt': 'pt-PT'}
|
||||
|
||||
|
||||
def write_language(code, data):
|
||||
(FOLDER / f'{code}.json').write_text(json.dumps(data, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
|
||||
|
||||
|
||||
def merge(target, source):
|
||||
"""`source` into `target` in place, keeping the order of what `target` already has."""
|
||||
for key, value in source.items():
|
||||
if isinstance(value, dict) and isinstance(target.get(key), dict):
|
||||
merge(target[key], value)
|
||||
else:
|
||||
target[key] = value
|
||||
|
||||
|
||||
def cldr_dates(write, codes=None):
|
||||
"""Day and month names, date orders, AM/PM, the number marks and the clock of every language but English (whose
|
||||
texts are the source) from Node's Intl, into screen.date, screen.time, screen.number and _meta.clock."""
|
||||
codes = codes or [code for code in languages() if not code.startswith('en')]
|
||||
if not codes:
|
||||
return 0
|
||||
locales = [CLDR_LOCALE.get(code, code) for code in codes]
|
||||
found = json.loads(subprocess.run(['node', str(ROOT / 'tools' / 'i18n_cldr.mjs'), *locales], check=True,
|
||||
capture_output=True, text=True).stdout)
|
||||
for code, locale in zip(codes, locales):
|
||||
path = FOLDER / f'{code}.json'
|
||||
data = json.loads(path.read_text(encoding='utf-8'))
|
||||
cldr = found[locale]
|
||||
before = json.dumps(data, ensure_ascii=False)
|
||||
data.setdefault('_meta', {})['clock'] = cldr['clock']
|
||||
merge(data.setdefault('screen', {}), {'number': cldr['number'], 'time': cldr['time'], 'date': cldr['date']})
|
||||
if json.dumps(data, ensure_ascii=False) != before:
|
||||
print(f'{code}: {"wrote" if write else "would change"} the CLDR texts')
|
||||
if write:
|
||||
write_language(code, data)
|
||||
return 0
|
||||
|
||||
|
||||
def new_language(code, name, english, plural):
|
||||
"""A new language file: its _meta and the CLDR texts, every other text still English until someone translates it."""
|
||||
if not re.fullmatch(r'[a-z]{2,3}(-[A-Za-z0-9]{2,8})?', code) or (FOLDER / f'{code}.json').exists():
|
||||
raise SystemExit(f'{code}: not a new language code')
|
||||
if plural not in FORMS:
|
||||
raise SystemExit(f'plural must be one of {", ".join(FORMS)}')
|
||||
write_language(code, {'_meta': {'name': name, 'english': english, 'script': 'latin', 'plural': plural, 'clock': '24',
|
||||
'checked': False}, 'screen': {}, 'addon': {}, 'editor': {}})
|
||||
return cldr_dates(True, [code])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Day and month names, date orders, the decimal mark and the clock of languages, from the Unicode CLDR that Node's Intl
|
||||
// carries (app 0.2.90); tools/i18n.py cldr writes them into the translations. Prints JSON: {code: {...}}.
|
||||
const codes = process.argv.slice(2);
|
||||
const space = (text) => text.replace(/[ ]/g, ' ');
|
||||
// 2026-03-01 is a Sunday: day i of that week is Sunday + i, as the screens count (ESPHome's day_of_week 1 is Sunday).
|
||||
const day = (i) => new Date(Date.UTC(2026, 2, 1 + i, 12));
|
||||
const month = (m) => new Date(Date.UTC(2026, m, 14, 12));
|
||||
const pattern = (code, options, names) => {
|
||||
const parts = new Intl.DateTimeFormat(code, { ...options, timeZone: 'UTC' }).formatToParts(new Date(Date.UTC(2026, 8, 14, 14, 5)));
|
||||
let out = '';
|
||||
for (const part of parts) {
|
||||
if (names[part.type]) out += `{${names[part.type]}}`;
|
||||
else if (part.type === 'literal') out += space(part.value);
|
||||
}
|
||||
return out.replace(/\{hour\}:\{minute\}/, '{time}').replace(/\{hour\}\.\{minute\}/, '{time}');
|
||||
};
|
||||
const result = {};
|
||||
for (const code of codes) {
|
||||
const short = new Intl.DateTimeFormat(code, { weekday: 'short', timeZone: 'UTC' });
|
||||
const long = new Intl.DateTimeFormat(code, { weekday: 'long', timeZone: 'UTC' });
|
||||
const monthLong = (m) => new Intl.DateTimeFormat(code, { day: 'numeric', month: 'long', timeZone: 'UTC' }).formatToParts(month(m)).find((p) => p.type === 'month').value;
|
||||
const monthShort = (m) => new Intl.DateTimeFormat(code, { day: 'numeric', month: 'short', timeZone: 'UTC' }).formatToParts(month(m)).find((p) => p.type === 'month').value;
|
||||
const numbers = new Intl.NumberFormat(code);
|
||||
const parts = numbers.formatToParts(12345.5);
|
||||
const decimal = parts.find((p) => p.type === 'decimal').value;
|
||||
const group = space(parts.find((p) => p.type === 'group').value);
|
||||
const period = (hour) => (new Intl.DateTimeFormat(code, { hour: 'numeric', hour12: true, timeZone: 'UTC' })
|
||||
.formatToParts(new Date(Date.UTC(2026, 0, 1, hour))).find((p) => p.type === 'dayPeriod') || { value: hour < 12 ? 'AM' : 'PM' }).value;
|
||||
const cycle = new Intl.DateTimeFormat(code, { hour: 'numeric', timeZone: 'UTC' }).resolvedOptions().hourCycle;
|
||||
// A locale that writes a short date with the month as a number (Portugal: "14/09") gets the standalone short names
|
||||
// and "day month" instead: the screens' calendar shows a month's name beside the big day.
|
||||
const numericMonth = /^\d+$/.test(monthShort(8));
|
||||
const standalone = (m) => space(new Intl.DateTimeFormat(code, { month: 'short', timeZone: 'UTC' }).format(month(m)));
|
||||
const withNames = (text) => (numericMonth ? text.replace(/\{day\}\W*\{month\}/, '{day} {month}') : text);
|
||||
result[code] = {
|
||||
clock: cycle === 'h12' || cycle === 'h11' ? '12' : '24',
|
||||
number: { decimal, group, group_min: numbers.format(1234).includes(parts.find((p) => p.type === 'group').value) ? '1' : '2' },
|
||||
time: { am: space(period(9)), pm: space(period(21)) },
|
||||
date: {
|
||||
weekdays: [0, 1, 2, 3, 4, 5, 6].map((i) => long.format(day(i))),
|
||||
weekdays_short: [0, 1, 2, 3, 4, 5, 6].map((i) => short.format(day(i))),
|
||||
weekdays_min: [0, 1, 2, 3, 4, 5, 6].map((i) => short.format(day(i))),
|
||||
months: [...Array(12).keys()].map(monthLong),
|
||||
months_short: [...Array(12).keys()].map(numericMonth ? standalone : monthShort),
|
||||
top_bar: withNames(pattern(code, { weekday: 'short', day: 'numeric', month: 'short' }, { weekday: 'weekday', day: 'day', month: 'month' })),
|
||||
full: pattern(code, { weekday: 'long', day: 'numeric', month: 'long' }, { weekday: 'weekday', day: 'day', month: 'month' }),
|
||||
day_month: withNames(pattern(code, { day: 'numeric', month: 'short' }, { day: 'day', month: 'month' })),
|
||||
weekday_time: pattern(code, { weekday: 'short', hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }, { weekday: 'weekday', hour: 'hour', minute: 'minute' }),
|
||||
},
|
||||
};
|
||||
}
|
||||
console.log(JSON.stringify(result, null, 1));
|
||||
Reference in New Issue
Block a user