Added Serbian Language

This commit is contained in:
M-Factory
2025-08-06 22:10:26 +09:00
parent 0b26ff3c37
commit 5e531c4cf2
6 changed files with 79 additions and 8 deletions

View File

@@ -891,6 +891,39 @@ void handleCaptivePortal(AsyncWebServerRequest *request) {
String normalizeWeatherDescription(String str) {
// Serbian Cyrillic → Latin
str.replace("а", "a");
str.replace("б", "b");
str.replace("в", "v");
str.replace("г", "g");
str.replace("д", "d");
str.replace("ђ", "dj");
str.replace("е", "e");
str.replace("ж", "z");
str.replace("з", "z");
str.replace("и", "i");
str.replace("ј", "j");
str.replace("к", "k");
str.replace("л", "l");
str.replace("љ", "lj");
str.replace("м", "m");
str.replace("н", "n");
str.replace("њ", "nj");
str.replace("о", "o");
str.replace("п", "p");
str.replace("р", "r");
str.replace("с", "s");
str.replace("т", "t");
str.replace("ћ", "c");
str.replace("у", "u");
str.replace("ф", "f");
str.replace("х", "h");
str.replace("ц", "c");
str.replace("ч", "c");
str.replace("џ", "dz");
str.replace("ш", "s");
// Latin diacritics → ASCII
str.replace("å", "a");
str.replace("ä", "a");
str.replace("à", "a");
@@ -981,17 +1014,19 @@ String normalizeWeatherDescription(String str) {
str.replace("ź", "z");
str.replace("ż", "z");
str.toLowerCase();
str.toUpperCase();
String result = "";
for (unsigned int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((c >= 'a' && c <= 'z') || c == ' ') {
if ((c >= 'A' && c <= 'Z') || c == ' ') {
result += c;
}
}
return result;
}
bool isNumber(const char *str) {
for (int i = 0; str[i]; i++) {
if (!isdigit(str[i]) && str[i] != '.' && str[i] != '-') return false;

View File

@@ -441,6 +441,7 @@ textarea::placeholder {
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>

View File

@@ -30,6 +30,7 @@ const DaysOfWeekMapping days_mappings[] = {
{ "ro", { "d&u&m", "l&u&n", "m&a&r", "m&i&e", "j&o&i", "v&i&n", "s&a&m" } },
{ "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" } },
{ "sv", { "s&o&n", "m&a&n", "t&i&s", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "sw", { "j&p&l", "j&u&m", "j&t&t", "j&t&n", "a&l&k", "i&j&m", "j&m&s" } },
{ "tr", { "p&a&z", "p&a&z", "s&a&l", "c&a&r", "p&e&r", "c&u&m", "c&u&m" } }

View File

@@ -888,9 +888,40 @@ void handleCaptivePortal(AsyncWebServerRequest *request) {
request->redirect(String("http://") + WiFi.softAPIP().toString() + "/");
}
String normalizeWeatherDescription(String str) {
// Serbian Cyrillic → Latin
str.replace("а", "a");
str.replace("б", "b");
str.replace("в", "v");
str.replace("г", "g");
str.replace("д", "d");
str.replace("ђ", "dj");
str.replace("е", "e");
str.replace("ж", "z");
str.replace("з", "z");
str.replace("и", "i");
str.replace("ј", "j");
str.replace("к", "k");
str.replace("л", "l");
str.replace("љ", "lj");
str.replace("м", "m");
str.replace("н", "n");
str.replace("њ", "nj");
str.replace("о", "o");
str.replace("п", "p");
str.replace("р", "r");
str.replace("с", "s");
str.replace("т", "t");
str.replace("ћ", "c");
str.replace("у", "u");
str.replace("ф", "f");
str.replace("х", "h");
str.replace("ц", "c");
str.replace("ч", "c");
str.replace("џ", "dz");
str.replace("ш", "s");
// Latin diacritics → ASCII
str.replace("å", "a");
str.replace("ä", "a");
str.replace("à", "a");
@@ -981,17 +1012,19 @@ String normalizeWeatherDescription(String str) {
str.replace("ź", "z");
str.replace("ż", "z");
str.toLowerCase();
str.toUpperCase();
String result = "";
for (unsigned int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((c >= 'a' && c <= 'z') || c == ' ') {
if ((c >= 'A' && c <= 'Z') || c == ' ') {
result += c;
}
}
return result;
}
bool isNumber(const char *str) {
for (int i = 0; str[i]; i++) {
if (!isdigit(str[i]) && str[i] != '.' && str[i] != '-') return false;
@@ -1625,8 +1658,7 @@ void loop() {
// --- WEATHER DESCRIPTION Display Mode ---
if (displayMode == 2 && showWeatherDescription && weatherAvailable && weatherDescription.length() > 0) {
String desc = weatherDescription;
desc.toUpperCase();
if (desc.length() > 8) {
if (!descScrolling) {
P.displayClear();

View File

@@ -441,6 +441,7 @@ textarea::placeholder {
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>

View File

@@ -30,6 +30,7 @@ const DaysOfWeekMapping days_mappings[] = {
{ "ro", { "d&u&m", "l&u&n", "m&a&r", "m&i&e", "j&o&i", "v&i&n", "s&a&m" } },
{ "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" } },
{ "sv", { "s&o&n", "m&a&n", "t&i&s", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "sw", { "j&p&l", "j&u&m", "j&t&t", "j&t&n", "a&l&k", "i&j&m", "j&m&s" } },
{ "tr", { "p&a&z", "p&a&z", "s&a&l", "c&a&r", "p&e&r", "c&u&m", "c&u&m" } }