From ca4426b9bf02e99c1f18bf6741b3fcc85c67ffc9 Mon Sep 17 00:00:00 2001 From: M-Factory Date: Sat, 27 Sep 2025 01:28:32 +0900 Subject: [PATCH] Added Russian Language - Added Russian Language - Bugfixes ESP8266 --- ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino | 31 +++++++++++---------- ESPTimeCast_ESP32/data/index.html | 1 + ESPTimeCast_ESP32/days_lookup.h | 1 + ESPTimeCast_ESP32/months_lookup.h | 1 + ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino | 21 ++++++++++---- ESPTimeCast_ESP8266/data/index.html | 1 + ESPTimeCast_ESP8266/days_lookup.h | 1 + ESPTimeCast_ESP8266/months_lookup.h | 1 + 8 files changed, 39 insertions(+), 19 deletions(-) diff --git a/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino b/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino index 69d0d5c..e659a49 100644 --- a/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino +++ b/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino @@ -1043,10 +1043,12 @@ String normalizeWeatherDescription(String str) { str.replace("д", "d"); str.replace("ђ", "dj"); str.replace("е", "e"); + str.replace("ё", "e"); // Russian str.replace("ж", "z"); str.replace("з", "z"); str.replace("и", "i"); - str.replace("ј", "j"); + str.replace("й", "j"); // Russian + str.replace("ј", "j"); // Serbian str.replace("к", "k"); str.replace("л", "l"); str.replace("љ", "lj"); @@ -1066,6 +1068,11 @@ String normalizeWeatherDescription(String str) { str.replace("ч", "c"); str.replace("џ", "dz"); str.replace("ш", "s"); + str.replace("щ", "sh"); // Russian + str.replace("ы", "y"); // Russian + str.replace("э", "e"); // Russian + str.replace("ю", "yu"); // Russian + str.replace("я", "ya"); // Russian // Latin diacritics → ASCII str.replace("å", "a"); @@ -1247,13 +1254,12 @@ void fetchWeather() { Serial.print(F("[WEATHER] URL: ")); // Use F() with Serial.print Serial.println(url); - HTTPClient http; // Create an HTTPClient object WiFiClientSecure client; // use secure client for HTTPS - client.setInsecure(); // disable certificate validation - + client.stop(); // ensure previous session closed + client.setInsecure(); // no cert validation + HTTPClient http; // Create an HTTPClient object http.begin(client, url); // Pass the WiFiClient object and the URL - - http.setTimeout(10000); // Sets both connection and stream timeout to 10 seconds + http.setTimeout(10000); // Sets both connection and stream timeout to 10 seconds Serial.println(F("[WEATHER] Sending GET request...")); int httpCode = http.GET(); // Send the GET request @@ -1394,8 +1400,7 @@ void advanceDisplayMode() { } else if (weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) { displayMode = 1; Serial.println(F("[DISPLAY] Switching to display mode: WEATHER (from Clock)")); - } else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && - countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { + } else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { displayMode = 3; Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Clock, weather skipped)")); } else if (nightscoutConfigured) { @@ -1409,8 +1414,7 @@ void advanceDisplayMode() { if (weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) { displayMode = 1; Serial.println(F("[DISPLAY] Switching to display mode: WEATHER (from Date)")); - } else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && - countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { + } else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { displayMode = 3; Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Date, weather skipped)")); } else if (nightscoutConfigured) { @@ -1424,8 +1428,7 @@ void advanceDisplayMode() { if (showWeatherDescription && weatherAvailable && weatherDescription.length() > 0) { displayMode = 2; Serial.println(F("[DISPLAY] Switching to display mode: DESCRIPTION (from Weather)")); - } else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && - countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { + } else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { displayMode = 3; Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Weather)")); } else if (nightscoutConfigured) { @@ -1436,8 +1439,7 @@ void advanceDisplayMode() { Serial.println(F("[DISPLAY] Switching to display mode: CLOCK (from Weather)")); } } else if (displayMode == 2) { // Weather Description - if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && - countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { + if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) { displayMode = 3; Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Description)")); } else if (nightscoutConfigured) { @@ -2428,6 +2430,7 @@ void loop() { "pl", // Polish "pt", // Portuguese "ro", // Romanian + "ru", // Russian "sk", // Slovak "sl", // Slovenian "sr", // Serbian diff --git a/ESPTimeCast_ESP32/data/index.html b/ESPTimeCast_ESP32/data/index.html index 12e1de2..0b2977b 100644 --- a/ESPTimeCast_ESP32/data/index.html +++ b/ESPTimeCast_ESP32/data/index.html @@ -455,6 +455,7 @@ textarea::placeholder { + diff --git a/ESPTimeCast_ESP32/days_lookup.h b/ESPTimeCast_ESP32/days_lookup.h index 8c884dc..6ffcaf4 100644 --- a/ESPTimeCast_ESP32/days_lookup.h +++ b/ESPTimeCast_ESP32/days_lookup.h @@ -29,6 +29,7 @@ const DaysOfWeekMapping days_mappings[] = { { "pl", { "n&i&e", "p&o&n", "w&t&o", "s&r&o", "c&z&w", "p&i&a", "s&o&b" } }, { "pt", { "d&o&m", "s&e&g", "t&e&r", "q&u&a", "q&u&i", "s&e&x", "s&a&b" } }, { "ro", { "d&u&m", "l&u&n", "m&a&r", "m&i&e", "j&o&i", "v&i&n", "s&a&m" } }, + { "ru", { "p&n", "v&t", "s&r", "c&h", "p&t", "s&b", "v&s" } }, { "sk", { "n&e&d", "p&o&n", "u&t&o", "s&t&r", "s&t&v", "p&i&a", "s&o&b" } }, { "sl", { "n&e&d", "p&o&n", "t&o&r", "s&r&e", "c&e&t", "p&e&t", "s&o&b" } }, { "sr", { "n&e&d", "p&o&n", "u&t&o", "s&r&e", "c&e&t", "p&e&t", "s&u&b" } }, diff --git a/ESPTimeCast_ESP32/months_lookup.h b/ESPTimeCast_ESP32/months_lookup.h index acd4ec5..44a0ca0 100644 --- a/ESPTimeCast_ESP32/months_lookup.h +++ b/ESPTimeCast_ESP32/months_lookup.h @@ -29,6 +29,7 @@ const MonthsMapping months_mappings[] = { { "pl", { "s&t&y", "l&u&t", "m&a&r", "k&w&i", "m&a&j", "c&z&e", "l&i&p", "s&i&e", "w&r&z", "p&a&z", "l&i&s", "g&r&u" } }, // Polish { "pt", { "j&a&n", "f&e&v", "m&a&r", "a&b&r", "m&a&i", "j&u&n", "j&u&l", "a&g&o", "s&e&t", "o&u&t", "n&o&v", "d&e&z" } }, // Portuguese { "ro", { "i&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&i", "i&u&n", "i&u&l", "a&u&g", "s&e&p", "o&c&t", "n&o&v", "d&e&c" } }, // Romanian + { "ru", { "i&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&i", "i&u&n", "i&u&l", "a&u&g", "s&e&p", "o&c&t", "n&o&i", "d&e&c" } }, // Russian { "sk", { "j&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&j", "j&u&n", "j&u&l", "a&u&g", "s&e&p", "o&k&t", "n&o&v", "d&e&c" } }, // Slovak { "sl", { "j&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&j", "j&u&n", "j&u&l", "a&v&g", "s&e&p", "o&k&t", "n&o&v", "d&e&c" } }, // Slovenian { "sr", { "j&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&j", "j&u&n", "j&u&l", "a&v&g", "s&e&p", "o&k&t", "n&o&v", "d&e&c" } }, // Serbian diff --git a/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino b/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino index 877c072..1bec6bb 100644 --- a/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino +++ b/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino @@ -1042,10 +1042,12 @@ String normalizeWeatherDescription(String str) { str.replace("д", "d"); str.replace("ђ", "dj"); str.replace("е", "e"); + str.replace("ё", "e"); // Russian str.replace("ж", "z"); str.replace("з", "z"); str.replace("и", "i"); - str.replace("ј", "j"); + str.replace("й", "j"); // Russian + str.replace("ј", "j"); // Serbian str.replace("к", "k"); str.replace("л", "l"); str.replace("љ", "lj"); @@ -1065,6 +1067,11 @@ String normalizeWeatherDescription(String str) { str.replace("ч", "c"); str.replace("џ", "dz"); str.replace("ш", "s"); + str.replace("щ", "sh"); // Russian + str.replace("ы", "y"); // Russian + str.replace("э", "e"); // Russian + str.replace("ю", "yu"); // Russian + str.replace("я", "ya"); // Russian // Latin diacritics → ASCII str.replace("å", "a"); @@ -1245,12 +1252,12 @@ void fetchWeather() { String url = buildWeatherURL(); Serial.println(F("[WEATHER] URL: ") + url); - HTTPClient http; // Create an HTTPClient object WiFiClientSecure client; // use secure client for HTTPS - client.setInsecure(); // disable certificate validation - + client.stop(); // ensure previous session closed + client.setInsecure(); // no cert validation + HTTPClient http; // Create an HTTPClient object http.begin(client, url); // Pass the WiFiClient object and the URL - + client.setBufferSizes(512, 512); http.setTimeout(10000); // Sets both connection and stream timeout to 10 seconds Serial.println(F("[WEATHER] Sending GET request...")); @@ -1774,6 +1781,9 @@ void loop() { weatherFetchInitiated = false; shouldFetchWeatherNow = false; } + + + const char *const *daysOfTheWeek = getDaysOfWeek(language); const char *daySymbol = daysOfTheWeek[timeinfo.tm_wday]; @@ -2409,6 +2419,7 @@ void loop() { "pl", // Polish "pt", // Portuguese "ro", // Romanian + "ru", // Russian "sk", // Slovak "sl", // Slovenian "sr", // Serbian diff --git a/ESPTimeCast_ESP8266/data/index.html b/ESPTimeCast_ESP8266/data/index.html index 12e1de2..0b2977b 100644 --- a/ESPTimeCast_ESP8266/data/index.html +++ b/ESPTimeCast_ESP8266/data/index.html @@ -455,6 +455,7 @@ textarea::placeholder { + diff --git a/ESPTimeCast_ESP8266/days_lookup.h b/ESPTimeCast_ESP8266/days_lookup.h index 8c884dc..6ffcaf4 100644 --- a/ESPTimeCast_ESP8266/days_lookup.h +++ b/ESPTimeCast_ESP8266/days_lookup.h @@ -29,6 +29,7 @@ const DaysOfWeekMapping days_mappings[] = { { "pl", { "n&i&e", "p&o&n", "w&t&o", "s&r&o", "c&z&w", "p&i&a", "s&o&b" } }, { "pt", { "d&o&m", "s&e&g", "t&e&r", "q&u&a", "q&u&i", "s&e&x", "s&a&b" } }, { "ro", { "d&u&m", "l&u&n", "m&a&r", "m&i&e", "j&o&i", "v&i&n", "s&a&m" } }, + { "ru", { "p&n", "v&t", "s&r", "c&h", "p&t", "s&b", "v&s" } }, { "sk", { "n&e&d", "p&o&n", "u&t&o", "s&t&r", "s&t&v", "p&i&a", "s&o&b" } }, { "sl", { "n&e&d", "p&o&n", "t&o&r", "s&r&e", "c&e&t", "p&e&t", "s&o&b" } }, { "sr", { "n&e&d", "p&o&n", "u&t&o", "s&r&e", "c&e&t", "p&e&t", "s&u&b" } }, diff --git a/ESPTimeCast_ESP8266/months_lookup.h b/ESPTimeCast_ESP8266/months_lookup.h index acd4ec5..44a0ca0 100644 --- a/ESPTimeCast_ESP8266/months_lookup.h +++ b/ESPTimeCast_ESP8266/months_lookup.h @@ -29,6 +29,7 @@ const MonthsMapping months_mappings[] = { { "pl", { "s&t&y", "l&u&t", "m&a&r", "k&w&i", "m&a&j", "c&z&e", "l&i&p", "s&i&e", "w&r&z", "p&a&z", "l&i&s", "g&r&u" } }, // Polish { "pt", { "j&a&n", "f&e&v", "m&a&r", "a&b&r", "m&a&i", "j&u&n", "j&u&l", "a&g&o", "s&e&t", "o&u&t", "n&o&v", "d&e&z" } }, // Portuguese { "ro", { "i&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&i", "i&u&n", "i&u&l", "a&u&g", "s&e&p", "o&c&t", "n&o&v", "d&e&c" } }, // Romanian + { "ru", { "i&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&i", "i&u&n", "i&u&l", "a&u&g", "s&e&p", "o&c&t", "n&o&i", "d&e&c" } }, // Russian { "sk", { "j&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&j", "j&u&n", "j&u&l", "a&u&g", "s&e&p", "o&k&t", "n&o&v", "d&e&c" } }, // Slovak { "sl", { "j&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&j", "j&u&n", "j&u&l", "a&v&g", "s&e&p", "o&k&t", "n&o&v", "d&e&c" } }, // Slovenian { "sr", { "j&a&n", "f&e&b", "m&a&r", "a&p&r", "m&a&j", "j&u&n", "j&u&l", "a&v&g", "s&e&p", "o&k&t", "n&o&v", "d&e&c" } }, // Serbian