-
-
Notifications
You must be signed in to change notification settings - Fork 515
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add API endpoint to retrieve custom languages and complete language pack
- Loading branch information
Showing
10 changed files
with
239 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#pragma once | ||
|
||
#include <TaskSchedulerDeclarations.h> | ||
#include <WString.h> | ||
#include <list> | ||
|
||
struct LanguageInfo_t { | ||
String code; | ||
String name; | ||
String filename; | ||
}; | ||
|
||
class I18nClass { | ||
public: | ||
I18nClass(); | ||
void init(Scheduler& scheduler); | ||
std::list<LanguageInfo_t> getAvailableLanguages(); | ||
|
||
private: | ||
void readLangPacks(); | ||
void readConfig(String file); | ||
|
||
std::list<LanguageInfo_t> _availLanguages; | ||
}; | ||
|
||
extern I18nClass I18n; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#pragma once | ||
|
||
#include <ESPAsyncWebServer.h> | ||
#include <TaskSchedulerDeclarations.h> | ||
|
||
class WebApiI18nClass { | ||
public: | ||
void init(AsyncWebServer& server, Scheduler& scheduler); | ||
|
||
private: | ||
void onI18nLanguages(AsyncWebServerRequest* request); | ||
void onI18nLanguage(AsyncWebServerRequest* request); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -108,3 +108,5 @@ | |
#define LED_BRIGHTNESS 100U | ||
|
||
#define MAX_INVERTER_LIMIT 2250 | ||
|
||
#define LANG_PACK_SUFFIX ".lang.json" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
/* | ||
* Copyright (C) 2024 Thomas Basler and others | ||
*/ | ||
#include "I18n.h" | ||
#include "MessageOutput.h" | ||
#include "Utils.h" | ||
#include "defaults.h" | ||
#include <ArduinoJson.h> | ||
#include <LittleFS.h> | ||
|
||
I18nClass I18n; | ||
|
||
I18nClass::I18nClass() | ||
{ | ||
} | ||
|
||
void I18nClass::init(Scheduler& scheduler) | ||
{ | ||
readLangPacks(); | ||
} | ||
|
||
std::list<LanguageInfo_t> I18nClass::getAvailableLanguages() | ||
{ | ||
return _availLanguages; | ||
} | ||
|
||
void I18nClass::readLangPacks() | ||
{ | ||
auto root = LittleFS.open("/"); | ||
auto file = root.getNextFileName(); | ||
|
||
while (file != "") { | ||
if (file.endsWith(LANG_PACK_SUFFIX)) { | ||
MessageOutput.printf("Read File %s\r\n", file.c_str()); | ||
readConfig(file); | ||
} | ||
file = root.getNextFileName(); | ||
} | ||
root.close(); | ||
} | ||
|
||
void I18nClass::readConfig(String file) | ||
{ | ||
JsonDocument filter; | ||
filter["meta"] = true; | ||
|
||
File f = LittleFS.open(file, "r", false); | ||
|
||
JsonDocument doc; | ||
|
||
// Deserialize the JSON document | ||
const DeserializationError error = deserializeJson(doc, f, DeserializationOption::Filter(filter)); | ||
if (error) { | ||
MessageOutput.printf("Failed to read file %s\r\n", file.c_str()); | ||
f.close(); | ||
return; | ||
} | ||
|
||
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) { | ||
return; | ||
} | ||
|
||
LanguageInfo_t lang; | ||
lang.code = String(doc["meta"]["code"]); | ||
lang.name = String(doc["meta"]["name"]); | ||
lang.filename = file; | ||
|
||
_availLanguages.push_back(lang); | ||
|
||
f.close(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
/* | ||
* Copyright (C) 2024 Thomas Basler and others | ||
*/ | ||
#include "WebApi_i18n.h" | ||
#include "I18n.h" | ||
#include "Utils.h" | ||
#include "WebApi.h" | ||
#include <AsyncJson.h> | ||
#include <LittleFS.h> | ||
|
||
#include "MessageOutput.h" | ||
|
||
void WebApiI18nClass::init(AsyncWebServer& server, Scheduler& scheduler) | ||
{ | ||
using std::placeholders::_1; | ||
|
||
server.on("/api/i18n/languages", HTTP_GET, std::bind(&WebApiI18nClass::onI18nLanguages, this, _1)); | ||
server.on("/api/i18n/language", HTTP_GET, std::bind(&WebApiI18nClass::onI18nLanguage, this, _1)); | ||
} | ||
|
||
void WebApiI18nClass::onI18nLanguages(AsyncWebServerRequest* request) | ||
{ | ||
AsyncJsonResponse* response = new AsyncJsonResponse(true); | ||
auto& root = response->getRoot(); | ||
const auto& languages = I18n.getAvailableLanguages(); | ||
|
||
for (auto& language : languages) { | ||
auto jsonLang = root.add<JsonObject>(); | ||
|
||
jsonLang["code"] = language.code; | ||
jsonLang["name"] = language.name; | ||
} | ||
|
||
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__); | ||
} | ||
|
||
void WebApiI18nClass::onI18nLanguage(AsyncWebServerRequest* request) | ||
{ | ||
if (request->hasParam("code")) { | ||
String code = request->getParam("code")->value(); | ||
|
||
const auto& languages = I18n.getAvailableLanguages(); | ||
auto it = std::find_if(languages.begin(), languages.end(), [code](const LanguageInfo_t& elem) { | ||
return elem.code == code; | ||
}); | ||
|
||
if (it != languages.end()) { | ||
String md5 = Utils::generateMd5FromFile(it->filename); | ||
|
||
String expectedEtag; | ||
expectedEtag = "\""; | ||
expectedEtag += md5; | ||
expectedEtag += "\""; | ||
|
||
bool eTagMatch = false; | ||
if (request->hasHeader("If-None-Match")) { | ||
const AsyncWebHeader* h = request->getHeader("If-None-Match"); | ||
eTagMatch = h->value().equals(expectedEtag); | ||
} | ||
|
||
// begin response 200 or 304 | ||
AsyncWebServerResponse* response; | ||
if (eTagMatch) { | ||
response = request->beginResponse(304); | ||
} else { | ||
response = request->beginResponse(LittleFS, it->filename, asyncsrv::T_application_json); | ||
} | ||
|
||
// HTTP requires cache headers in 200 and 304 to be identical | ||
response->addHeader("Cache-Control", "public, must-revalidate"); | ||
response->addHeader("ETag", expectedEtag); | ||
|
||
request->send(response); | ||
return; | ||
} | ||
} | ||
|
||
request->send(404); | ||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters