From df930697c7036a53c7f6c87d17a3da07c8af7183 Mon Sep 17 00:00:00 2001 From: flb Date: Mon, 5 Oct 2020 17:14:10 +0200 Subject: [PATCH] Small touch-ups for tiansongyu's PR --- .gitmodules | 2 +- Makefile | 2 +- README.md | 2 + icon.jpg | Bin 13682 -> 24557 bytes include/constants.hpp | 4 + include/fs.hpp | 227 ------------------------------- include/lang.hpp | 3 +- include/language_option_page.hpp | 1 + res/lang/ch.json | 2 + res/lang/en.json | 16 ++- res/lang/fr.json | 152 +++++++++++++++++++++ source/changelog_page.cpp | 3 + source/lang.cpp | 36 ++--- source/language_option_page.cpp | 23 +++- source/list_download_tab.cpp | 1 + source/main.cpp | 28 +--- source/tools_tab.cpp | 6 + 17 files changed, 221 insertions(+), 287 deletions(-) mode change 100644 => 100755 icon.jpg delete mode 100644 include/fs.hpp create mode 100644 res/lang/fr.json diff --git a/.gitmodules b/.gitmodules index 000826a..54111f4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = https://github.com/HamletDuFromage/zipper [submodule "lib/borealis"] path = lib/borealis - url = https://github.com/tiansongyu/borealis + url = https://github.com/HamletDuFromage/borealis diff --git a/Makefile b/Makefile index fc65044..b0e4416 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ DATA := data INCLUDES := include lib/zipper/include APP_TITLE := All-in-One Switch Updater APP_AUTHOR := HamletDuFromage -APP_VERSION := 1.1.3 +APP_VERSION := 1.2.0 ROMFS = res BOREALIS_PATH := lib/borealis diff --git a/README.md b/README.md index 1cdaee5..b5cfaee 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ Downloads and extracts daily-updated cheat code. The program will only extract c ## Disclaimer I do not own, host nor distribute any of the files that can be downloaded with this homebrew tool. At the owner's request, I will immediately remove the ability to download the problematic files. +## Special thanks +- [tiansongyu](https://github.com/tiansongyu) for bringing support for multi-language and for his Chinese translation. ### Like the app? [//]: [![5cbed8a433a3f45a772abaf5_SupportMe_blue-p-500](https://user-images.githubusercontent.com/61667930/93899702-1a2b2680-fce4-11ea-9eaa-4e2b44eebe86.png)](https://ko-fi.com/hamletdufromage) diff --git a/icon.jpg b/icon.jpg old mode 100644 new mode 100755 index a6f7f4a9a6b43b3dc52a5fc20aa602b30ef0ee02..8a62d5942fc317bd14504c98fbbcdb5fd152b2e3 GIT binary patch literal 24557 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 K0+S}Elm8cpLvbGf literal 13682 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 -#include -#include -#include - -namespace fs { - -struct Directory { - FsDir handle = {}; - - constexpr inline Directory() = default; - constexpr inline Directory(const FsDir &handle): handle(handle) { } - - inline ~Directory() { - this->close(); - } - - inline Result open(FsFileSystem *fs, const std::string &path) { - auto tmp = path; - tmp.reserve(FS_MAX_PATH); // Fails otherwise - return fsFsOpenDirectory(fs, tmp.c_str(), FsDirOpenMode_ReadDirs | FsDirOpenMode_ReadFiles, &this->handle); - } - - inline void close() { - fsDirClose(&this->handle); - } - - inline bool is_open() const { - // TODO: Better heuristic? - return this->handle.s.session; - } - - inline std::size_t count() { - std::int64_t count = 0; - fsDirGetEntryCount(&this->handle, &count); - return count; - } - - std::vector list() { - std::int64_t total = 0; - auto c = this->count(); - auto entries = std::vector(c); - fsDirRead(&this->handle, &total, c, entries.data()); - return entries; - } -}; - -struct File { - FsFile handle = {}; - - constexpr inline File() = default; - constexpr inline File(const FsFile &handle): handle(handle) { } - - inline ~File() { - this->close(); - } - - inline Result open(FsFileSystem *fs, const std::string &path, std::uint32_t mode = FsOpenMode_Read) { - auto tmp = path; - tmp.reserve(FS_MAX_PATH); - return fsFsOpenFile(fs, tmp.c_str(), mode, &this->handle); - } - - inline void close() { - fsFileClose(&this->handle); - } - - inline bool is_open() const { - return this->handle.s.session; - } - - inline std::size_t size() { - std::int64_t tmp = 0; - fsFileGetSize(&this->handle, &tmp); - return tmp; - } - - inline void size(std::size_t size) { - fsFileSetSize(&this->handle, static_cast(size)); - } - - inline std::size_t read(void *buf, std::size_t size, std::size_t offset = 0) { - std::uint64_t tmp = 0; - auto rc = fsFileRead(&this->handle, static_cast(offset), buf, static_cast(size), FsReadOption_None, &tmp); - if (R_FAILED(rc)) - printf("Read failed with %#x\n", rc); - return tmp; - } - - inline void write(const void *buf, std::size_t size, std::size_t offset = 0) { - fsFileWrite(&this->handle, static_cast(offset), buf, size, FsWriteOption_None); - } - - inline void flush() { - fsFileFlush(&this->handle); - } -}; - -struct Filesystem { - FsFileSystem handle = {}; - - constexpr inline Filesystem() = default; - constexpr inline Filesystem(const FsFileSystem &handle): handle(handle) { } - - inline ~Filesystem() { - this->close(); - } - - inline Result open(FsBisPartitionId id) { - return fsOpenBisFileSystem(&this->handle, id, ""); - } - - inline Result open_sdmc() { - return fsOpenSdCardFileSystem(&this->handle); - } - - inline void close() { - flush(); - fsFsClose(&this->handle); - } - - inline bool is_open() const { - return this->handle.s.session; - } - - inline Result flush() { - return fsFsCommit(&this->handle); - } - - inline std::size_t total_space() { - std::int64_t tmp = 0; - fsFsGetTotalSpace(&this->handle, "/", &tmp); - return tmp; - } - - inline std::size_t free_space() { - std::int64_t tmp = 0; - fsFsGetFreeSpace(&this->handle, "/", &tmp); - return tmp; - } - - inline Result open_directory(Directory &d, const std::string &path) { - return d.open(&this->handle, path); - } - - inline Result open_file(File &f, const std::string &path, std::uint32_t mode = FsOpenMode_Read) { - return f.open(&this->handle, path, mode); - } - - inline Result create_directory(const std::string &path) { - return fsFsCreateDirectory(&this->handle, path.c_str()); - } - - inline Result create_file(const std::string &path, std::size_t size = 0) { - return fsFsCreateFile(&this->handle, path.c_str(), static_cast(size), 0); - } - - inline Result copy_file(const std::string &source, const std::string &destination) { - File source_f, dest_f; - if (auto rc = this->open_file(source_f, source) | this->open_file(dest_f, destination, FsOpenMode_Write); R_FAILED(rc)) - return rc; - - constexpr std::size_t buf_size = 0x100000; // 1 MiB - auto buf = std::vector(buf_size); - - std::size_t size = source_f.size(), offset = 0; - while (size) { - auto read = source_f.read(static_cast(buf.data()), buf_size, offset); - dest_f.write(buf.data(), read, offset); - offset += read; - size -= read; - } - - source_f.close(); - dest_f.close(); - - return 0; - } - - inline FsDirEntryType get_path_type(const std::string &path) { - FsDirEntryType type; - fsFsGetEntryType(&this->handle, path.c_str(), &type); - return type; - } - - inline bool is_directory(const std::string &path) { - return get_path_type(path) == FsDirEntryType_Dir; - } - - inline bool is_file(const std::string &path) { - return get_path_type(path) == FsDirEntryType_File; - } - - inline FsTimeStampRaw get_timestamp(const std::string &path) { - FsTimeStampRaw ts = {}; - fsFsGetFileTimeStampRaw(&this->handle, path.c_str(), &ts); - return ts; - } - - inline std::uint64_t get_timestamp_created(const std::string &path) { - return this->get_timestamp(path).created; - } - - inline std::uint64_t get_timestamp_modified(const std::string &path) { - return this->get_timestamp(path).modified; - } - - inline Result move_directory(const std::string &old_path, const std::string &new_path) { - return fsFsRenameDirectory(&this->handle, old_path.c_str(), new_path.c_str()); - } - - inline Result move_file(const std::string &old_path, const std::string &new_path) { - return fsFsRenameFile(&this->handle, old_path.c_str(), new_path.c_str()); - } - - inline Result delete_directory(const std::string &path) { - return fsFsDeleteDirectoryRecursively(&this->handle, path.c_str()); - } - - inline Result delete_file(const std::string &path) { - return fsFsDeleteFile(&this->handle, path.c_str()); - } -}; - -} // namespace fs diff --git a/include/lang.hpp b/include/lang.hpp index 76701e3..c8695a1 100644 --- a/include/lang.hpp +++ b/include/lang.hpp @@ -8,7 +8,8 @@ namespace lang { enum class Language { English, Chinese, - /* French, + French, + /* Dutch, Italian, German, diff --git a/include/language_option_page.hpp b/include/language_option_page.hpp index f600eb2..f04e379 100644 --- a/include/language_option_page.hpp +++ b/include/language_option_page.hpp @@ -10,6 +10,7 @@ class LanguageOptionPage : public brls::AppletFrame brls::List* list; brls::ListItem* English; brls::ListItem* Chinese; + brls::ListItem* French; brls::StagedAppletFrame* stagedFrame; diff --git a/res/lang/ch.json b/res/lang/ch.json index 8ad0ad0..3cfca5b 100644 --- a/res/lang/ch.json +++ b/res/lang/ch.json @@ -29,6 +29,8 @@ "v1_1_2_text": "\uE016 Added GUI to disable cheat updates for specific titles.", "v1_1_3": "v1.1.3", "v1_1_3_text": "\uE016 现在显示最新安装的金手指版本.\n\uE016 如果有新的更新可用,现在在应用程序标题中警告", + "v1_2_0": "v1.2.0", + "v1_2_0_text": "\uE016 现在可以使用多种语言(感谢'github.com/tiansongyu').\n\uE016 目前支持中文和法文.", "Ok_button": "确定", "cheats_page.cpp":"", diff --git a/res/lang/en.json b/res/lang/en.json index 257c959..fd465eb 100644 --- a/res/lang/en.json +++ b/res/lang/en.json @@ -2,7 +2,7 @@ "about_tab.cpp":"", "About_Title": "All-in-One Nintendo Switch Updater", "copyright": "AIO-switch-updater is licensed under GPL-3.0\n\u00A9 2020 HamletDuFromage", - "Disclaimers": "\uE016 Aside from cheat codes that are mirrored from the main Gbatemp thread, HamletDuFromage isn't hosting anything. All credits go to respective owners\n\uE016 Links are refreshed every three hours. If a link remains broken after 3 hours have passed, please open a Github issue.\n", + "Disclaimers": "\uE016 Aside from cheat codes that are mirrored from the main Gbatemp thread, HamletDuFromage isn't hosting anything. All credits go to respective owners.\n\uE016 Links are refreshed every three hours. If a link remains broken after 3 hours have passed, please open a Github issue.\n", "app_page.cpp":"", "app_title": "Installed cheats", @@ -30,6 +30,8 @@ "v1_1_2_text": "\uE016 Added GUI to disable cheat updates for specific titles.", "v1_1_3": "v1.1.3", "v1_1_3_text": "\uE016 Now displays the latest installed cheat version.\n\uE016 Now warns in the app title if a new update is available.", + "v1_2_0": "v1.2.0", + "v1_2_0_text": "\uE016 Now multilingual (thanks to 'github.com/tiansongyu').\n\uE016 Chinese and French are currently supported.", "Ok_button": "Ok", "cheats_page.cpp":"", @@ -38,12 +40,12 @@ "cheat_exclude": "Exclude games from recieving cheat updates", "cheat_delete_all_ex": "Delete all existing cheat codes", "cheat_delete_all_cheat": "Delete all cheats", - "cheat_Deleting": "Deleting", + "cheat_Deleting": "Deleting...", "cheat_All_done": "All done!", "choice_page.cpp":"", - "choice_yes":"yes", - "choice_no":"no", + "choice_yes":"Yes", + "choice_no":"No", "chnfirm_page.cpp":"", "Back": "Back", @@ -57,12 +59,12 @@ "getting_paylaod": "getting payload files", "down": "Downloading...", "download_all_done": "All done!", - "description": "Could not find a download link, make sure the Switch has access to the internet.\nIf this problem persists, please open an issue on Github", + "description": "Could not find a download link, make sure the Switch has access to the internet.\nIf this problem persists, please open an issue on Github.", "back": "Back", "Language_option_page.cpp":"", "Language_Option":"Language Option", - "reset_machine":"language has changed .please reboot the app to use the new language", + "reset_machine":"Language has changed. Please reboot the app for the change to take effect", "exclude_page.cpp":"", "exclude_titles": "Exclude titles", @@ -80,7 +82,7 @@ "jc_all_done": "All done!", "jc_con_color": "Joy-Con color swapper", "jc_change": "Changing color. Make sure the Joy-Con are docked. If the process hangs, try docking/undocking the JCs.", - "jc_all_": "All done! You may need to dock/undock your Joy-Cons for the change to take effect", + "jc_all_": "All done! You may need to dock/undock your Joy-Cons for the change to take effect.", "list_donwload.cpp":"", "Getting": "Getting ", diff --git a/res/lang/fr.json b/res/lang/fr.json new file mode 100644 index 0000000..9909237 --- /dev/null +++ b/res/lang/fr.json @@ -0,0 +1,152 @@ +{ + "about_tab.cpp":"", + "About_Title": "All-in-One Nintendo Switch Updater", + "copyright": "AIO-switch-updater est distribuée sous la license GPL-3.0\n\u00A9 2020 HamletDuFromage", + "Disclaimers": "\uE016 A part les cheat codes qui proviennent d'un mirroir d'un topic Gbatemp, HamletDuFromage n'héberge rien. All credits go to respective owners\n\uE016 Les liens sont actualisés toutes les 3 heures. Si un lien demeure brisé après 3 heures, merci de bien vouloir ouvrir une issue.\n", + + "app_page.cpp":"", + "app_title": "Cheats installés", + "app_label": "Les titres suivants ont obtenu des codes de triche lors de la dernière utilisation de l'app. Sachez que même si un jeu a reçu des codes, il se peut que ceux_ci soient incompatibles avec la version actuelle de votre jeu..", + "text_download": "Télécharge:\nDerniers codes de cheat\n\nDe:\n", + "text_download_list": "Télécharger les derniers codes de triche", + "text_title": "Obtension des codes de triche", + "Downloading": "Téléchargement...", + "Extracting": "Extraction...", + "All_done": "Fini!", + + "changelog_page.cpp":"", + "Changelog":"Changelog", + "v1_0_1": "v1.0.1", + "v1_0_1_text": "\uE016 Added dialogue box asking about ini files.\n\uE016 Fixed update app link when not connected to the internet.\n\uE016 Minor fixes here and there.", + "v1_0_2": "v1.0.2", + "v1_0_2_text": "\uE016 Fixed .ini files being handled poorly when installing sigpatches. Now prompts the user if they want to replace hetake_ipl.ini.", + "v1_0_3": "v1.0.3", + "v1_0_3_text": "\uE016 Fixed progress bar sometimes being stuck when extracting.", + "v1_1_0": "v1.1.0", + "v1_1_0_text": "\uE016 Added an option to download payloads to '/bootloader/payloads'.\n\uE016 Cleaned up some stuff, made .ini overwriting cleaner.\n", + "v1_1_1": "v1.1.1", + "v1_1_1_text": "\uE016 Added some safety checks before downloading/extracting.\n\uE016 Added the possibility to copy a payload to '/atmosphere/reboot_payload.bin'\n\uE016 Added changelog in 'Tools'\n", + "v1_1_2": "v1.1.2", + "v1_1_2_text": "\uE016 Added GUI to disable cheat updates for specific titles.", + "v1_1_3": "v1.1.3", + "v1_1_3_text": "\uE016 Now displays the latest installed cheat version.\n\uE016 Now warns in the app title if a new update is available.", + "v1_2_0": "v1.2.0", + "v1_2_0_text": "\uE016 Now multilingual (thanks to 'github.com/tiansongyu').\n\uE016 Chinese and French are currently supported.", + + "Ok_button": "Ok", + + "cheats_page.cpp":"", + "cheat_menu": "Menu de cheat", + "cheat_view": "Voir les codes de triche installés", + "cheat_exclude": "Exclure l'obtension de codes de triche pour certains jeux", + "cheat_delete_all_ex": "Supprimer tous les codes présents sur la carte SD", + "cheat_delete_all_cheat": "Supprimer tous les codes", + "cheat_Deleting": "Suppression...", + "cheat_All_done": "Fini!", + + "choice_page.cpp":"", + "choice_yes":"Oui", + "choice_no":"Non", + + "chnfirm_page.cpp":"", + "Back": "Retour", + "Continue": "Continuer", + + "download_payload_page.cpp":"", + "Download_payloads": "Télécharger des payloads", + "select": "Choisir un payload à télécharger vers '", + "Download": "Télécharger:\n", + "from": "\n\nDe:\n", + "getting_paylaod": "obtension du payload", + "down": "Téléchargement...", + "download_all_done": "Fini!", + "description": "Impossible de trouver un lien de téléchargement, assurez vous que la Switch soit connectée à internet.\nSi ce problème persiste, veuillez ouvrir une issue sur Github.", + "back": "Retour", + + "Language_option_page.cpp":"", + "Language_Option":"Options de langue", + "reset_machine":"La langue a changé, veuillez redémarrer pour que le changement devienne effectif.", + + "exclude_page.cpp":"", + "exclude_titles": "Exclure des titres", + "you_can": "Vous pouvez desactiver les mises-à-jour de codes dans ce menu", + "save": "Sauvegarde et retour", + + "JC_page.cpp":"", + "joy_con": "Changement de couleur des Joy-Cons", + "jc_you_can_1": "Vous pouvez changer la couleur interne de vos Joy-Cons. Assurez vous qu'ils soient bien ancrés à la Swich.\nLes profils de couleur se trouvent dans '", + "jc_you_can_goto": "'. Visitez 'http://bit.ly/JC-color' ", + "jc_you_can_2": "pour générer des profils personalisés.", + "jc_backup": "Sauvegarde du profil actuel", + "jc_color": "Joy-Con color swapper", + "jc_backing": "Sauvegarde du profile actuel, assurez vous que les Joy-Cons soient bien ancrés à la Switch.", + "jc_all_done": "Fini!", + "jc_con_color": "Changement de couleur des Joy-Cons", + "jc_change": "Changement de couleur. Assurez vous que les Joy-Cons soient bien ancrés à la Switch.", + "jc_all_": "Fini! Vous devrez peut-être ancrer/détacher votre Joy-Cons pour que le changement prenne effet", + + "list_donwload.cpp":"", + "Getting": "Obtension ", + "firmware_text": "\uE016 Firmware dumps de 'https://darthsternie.net/switch-firmwares/'. Une fois téléchargés, ils seront dans '/firmware'. Vous pouvez ensuite les installer avec Daybreak ou ChoiDuJour.\n\uE016 FW actuel: ", + "currentCeatsver": "\uE016 Cela téléchargera une archive mise à jour quotidiennement des codes de triche de 'gbatemp.net'. Les codes de triche pour les jeux que vous n'avez pas installés ne seront pas extraits sur votre carte SD. Vous pouvez désactiver les mises à jour pour pour une selection de jeux dans le menu 'Outils->Menu de cheat'.\n\uE016 Version actuelle des cheats : ", + "operation_1": "sigpatches", + "list_sigpatches": "\uE016 Les Sigpatches permettent à votre Switch d'installer et d'exécuter des fichiers NSP non officiels. Assurez-vous de choisir les bons patchs pour votre configuration (Atmosphere pur ou Hekate+Atmosphere).", + "operation_2": "firmware", + "list_not": "not found", + "list_latest": "Dernière version", + "list_app": "app", + "list_cfw": "CFW", + "list_main": "\uE016 Principaux CFWs. Si vous souhaitez utiliser Atmosphere avec Hekate, téléchargez Atmosphere, puis Hekate.", + "list_latest_ver": "Derniers (ver ", + "list_cheats": "codes de triche", + "list_down": "Télécharger:\n", + "list_from": "\n\nFrom:\n", + "list_downing": "Téléchargement...", + "list_extracting": "Exctraction...", + "list_All": "Fini!", + "list_could_done": "Impossible de trouver un lien de téléchargement, assurez vous que la Switch soit connectée à internet.\nSi ce problème persiste, veuillez ouvrir une issue sur Github.", + + "main_frame.cpp":"", + "main_app": " - Nouvelle màj de l'app disponible", + "main_v": " v", + "main_about": "A propos", + "main_update_cfw": "MàJ du CFW", + "main_update_si": "MàJ des sigpatches", + "main_firmwares": "Téléch. des firmwares", + "main_cheats": "Télécharger des cheats", + "main_tools": "Outils", + + "payload_page.cpp":"", + "payload_reboot": "Menu de redémarrage", + "payload_select": " Selectionner un payload à redémarrer.", + "payload_set": "Définit comme reboot_payload.bin", + "payload_success": "Copié avec succès '", + "payload_to": "' vers '", + "payload_ok": "Ok", + "payload_shut": "Eteindre", + "payload_reboot_2": "Redemarrer", + + "tools_tab.cpp":"", + "tool_cheats": "Menu de cheat", + "tool_change": "Changer la couleur des Joy-Cons", + "tool_download": "Télécharger des payloads vers ", + "tool_inject": "Injecter un payload", + "tool_update": "Mettre à jour l'app (v", + "tool_DownLoad": "Télécharger:\nAIO-switch-updater\n\nDe:\n", + "tool_updating": "Mis à jour de l'app", + "tool_downloading":"Téléchargement...", + "tool_extracting": "Extraction....", + "tool_all_done": " Fini!", + "tool_changelog": "Changelog", + + "utils.cpp":"", + "utils_because": "En raison de la taille de l'archive FW, le téléchargement de firmwares en mode Applet n'est pas pris en charge. Veuillez lancer l'application avec un accès total à la RAM.", + "utils_ok": "Ok", + "utils_do": " Voulez-vous écraser l'existant ", + "utils_no": "Non", + "utils_yes": "Oui", + "utils_the": "Le fichier téléchargé n'est pas une archive de sigpatches. Cela est probablement dû à un lien brisé. Si le problème persiste après plus de 3 heures, veuillez ouvrir une issue sur Github.", + "utils_the_downloaded": "Le fichier téléchargé n'est pas une archive de firmare. Cela est probablement dû à un lien rompu. Si le problème persiste après plus de 3 heures, veuillez ouvrir une issue sur Github.", + "ultils_overwrite": "Voulez-vous écraser les fichiers de configuration .ini déja présents?", + "ultis_file": "Le fichier téléchargé n'est pas une archive de CFW. Cela est probablement dû à un lien rompu. Si le problème persiste après plus de 3 heures, veuillez ouvrir une issue sur Github." +} diff --git a/source/changelog_page.cpp b/source/changelog_page.cpp index 9bfd3e3..7657921 100644 --- a/source/changelog_page.cpp +++ b/source/changelog_page.cpp @@ -30,6 +30,9 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) verTitles.push_back("v1_1_3"_lang); changes.push_back("v1_1_3_text"_lang); + verTitles.push_back("v1_2_0"_lang); + changes.push_back("v1_2_0_text"_lang); + int nbVersions = verTitles.size(); items.reserve(nbVersions); for(int i = nbVersions -1 ; i >= 0; i--){ diff --git a/source/lang.cpp b/source/lang.cpp index 78d2373..05df9ee 100644 --- a/source/lang.cpp +++ b/source/lang.cpp @@ -1,8 +1,8 @@ #include -#include - -#include -#include +#include "json.hpp" +#include "lang.hpp" +#include +#include using json = nlohmann::json; @@ -32,9 +32,10 @@ Result set_language(Language lang) { break; //if you need add a new language //use it ! - /*case Language::French: + case Language::French: path = "romfs:/lang/fr.json"; break; + /* case Language::Dutch: path = "romfs:/lang/nl.json"; break; @@ -54,22 +55,12 @@ Result set_language(Language lang) { break; } - auto *fp = fopen(path, "r"); - if (!fp) - return 1; - - fseek(fp, 0, SEEK_END); - std::size_t size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - std::string contents(size, 0); - - if (auto read = fread(contents.data(), 1, size, fp); read != size) - return read; - fclose(fp); - - lang_json = json::parse(contents); - + std::fstream langFile; + if(std::filesystem::exists(path)){ + langFile.open(path, std::fstream::in); + langFile >> lang_json; + langFile.close(); + } return 0; } @@ -100,8 +91,9 @@ Result initialize_to_system_language() { return set_language(Language::Chinese); //if you need add a new language //use it ! - /*case SetLanguage_FR: + case SetLanguage_FR: return set_language(Language::French); + /* case SetLanguage_NL: return set_language(Language::Dutch); case SetLanguage_IT: diff --git a/source/language_option_page.cpp b/source/language_option_page.cpp index 4d692e6..ad7f87d 100644 --- a/source/language_option_page.cpp +++ b/source/language_option_page.cpp @@ -15,12 +15,12 @@ LanguageOptionPage::LanguageOptionPage() : AppletFrame(true, true) nlohmann::json json_file; json_file["language"]=(int)lang::Language::English; - std::ofstream o("/switch/AIO-switch-updater/config.ini"); + std::ofstream o(APP_LANG); o<addStage( - new ConfirmPage(stagedFrame, "reset_machine"_lang,false) + new ConfirmPage(stagedFrame, "reset_machine"_lang, true) ); brls::Application::pushView(stagedFrame); @@ -30,15 +30,30 @@ LanguageOptionPage::LanguageOptionPage() : AppletFrame(true, true) Chinese->getClickEvent()->subscribe([&](brls::View* view){ nlohmann::json json_file; json_file["language"]=(int)lang::Language::Chinese; - std::ofstream o("/switch/AIO-switch-updater/config.ini"); + std::ofstream o(APP_LANG); o<addStage( - new ConfirmPage(stagedFrame, "reset_machine"_lang,false) + new ConfirmPage(stagedFrame, "reset_machine"_lang, true) ); brls::Application::pushView(stagedFrame); }); list->addView(Chinese); + + French = new brls::ListItem("Français"); + French->getClickEvent()->subscribe([&](brls::View* view){ + nlohmann::json json_file; + json_file["language"]=(int)lang::Language::French; + std::ofstream o(APP_LANG); + o<addStage( + new ConfirmPage(stagedFrame, "reset_machine"_lang, true) + ); + brls::Application::pushView(stagedFrame); + }); + list->addView(French); this->setContentView(list); } \ No newline at end of file diff --git a/source/list_download_tab.cpp b/source/list_download_tab.cpp index bafacae..a3dcc74 100644 --- a/source/list_download_tab.cpp +++ b/source/list_download_tab.cpp @@ -73,6 +73,7 @@ ListDownloadTab::ListDownloadTab(archiveType type) : std::string url = std::get<1>(links)[i]; std::string text("list_down"_lang + std::get<0>(links)[i] + "list_from"_lang + url); linkItems[i] = new brls::ListItem(std::get<0>(links)[i]); + linkItems[i]->setHeight(LISTITEM_HEIGHT); linkItems[i]->getClickEvent()->subscribe([&, text, url, type, operation](brls::View* view) { brls::StagedAppletFrame* stagedFrame = new brls::StagedAppletFrame(); stagedFrame->setTitle(operation); diff --git a/source/main.cpp b/source/main.cpp index f9ae83b..4f3632e 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -49,30 +49,10 @@ int main(int argc, char* argv[]) brls::Logger::setLogLevel(brls::LogLevel::DEBUG); brls::Logger::debug("Start"); - - //start code by tiansongyu please clean the code if you want - //checkout the /switch/AIO-switch-updater/config.ini - //save the language mode - //or you can use this - /* - if (auto rc = lang::initialize_to_system_language(); R_FAILED(rc)) - brls::Logger::debug("Failed to init language: %#x, will fall back to key names\n", rc); - */ - //this code will automatically choose the machine language that the user use - //there are two ways to set the language . choose that you like way :D - const char* switch_dir= "/switch/"; - if(opendir(switch_dir)==NULL) - { - mkdir(switch_dir,0755); - } - const char* aio_config_file = "/switch/AIO-switch-updater/"; - if(opendir(aio_config_file)==NULL) - { - mkdir(aio_config_file,0755); - } - if(access("/switch/AIO-switch-updater/config.ini",F_OK) ==0) + //start code by tiansongyu + if(std::filesystem::exists(APP_LANG)) { - std::ifstream i("/switch/AIO-switch-updater/config.ini"); + std::ifstream i(APP_LANG); nlohmann::json lang_json; i>>lang_json; int tmp_number =lang_json["language"]; @@ -86,7 +66,7 @@ int main(int argc, char* argv[]) int language_number = (int)lang::get_current_language(); nlohmann::json json_file; json_file["language"]=language_number; - std::ofstream o("/switch/AIO-switch-updater/config.ini"); + std::ofstream o(APP_LANG); o<getClickEvent()->subscribe([&](brls::View* view){ brls::Application::pushView(new CheatsPage()); }); + cheats->setHeight(LISTITEM_HEIGHT); this->addView(cheats); JCcolor = new brls::ListItem("tool_change"_lang); JCcolor->getClickEvent()->subscribe([&](brls::View* view){ brls::Application::pushView(new JCPage()); }); + JCcolor->setHeight(LISTITEM_HEIGHT); this->addView(JCcolor); downloadPayload = new brls::ListItem("tool_download"_lang + std::string(BOOTLOADER_PL_PATH)); @@ -25,6 +27,7 @@ ToolsTab::ToolsTab(std::string tag) : brls::List() rebootPayload->getClickEvent()->subscribe([&](brls::View* view){ brls::Application::pushView(new PayloadPage()); }); + rebootPayload->setHeight(LISTITEM_HEIGHT); this->addView(rebootPayload); if(!tag.empty() && tag != APP_VERSION){ @@ -47,6 +50,7 @@ ToolsTab::ToolsTab(std::string tag) : brls::List() ); brls::Application::pushView(stagedFrame); }); + updateApp->setHeight(LISTITEM_HEIGHT); this->addView(updateApp); } @@ -54,11 +58,13 @@ ToolsTab::ToolsTab(std::string tag) : brls::List() changelog->getClickEvent()->subscribe([&](brls::View* view){ brls::Application::pushView(new ChangelogPage()); }); + changelog->setHeight(LISTITEM_HEIGHT); this->addView(changelog); language = new brls::ListItem("Language_Option"_lang); language->getClickEvent()->subscribe([&](brls::View* view){ brls::Application::pushView(new LanguageOptionPage()); }); + language->setHeight(LISTITEM_HEIGHT); this->addView(language); } \ No newline at end of file