From ec21e47b53a370a9e57284acff1196792177dc9f Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Sun, 22 Mar 2026 18:22:38 -0400 Subject: [PATCH] sysclk: rework selection method and fix translation bugs --- Source/sys-clk/overlay/lang/en.json | 330 ++++++++++++------ .../overlay/src/ui/gui/freq_choice_gui.cpp | 9 +- .../overlay/src/ui/gui/value_choice_gui.cpp | 25 +- Source/sys-clk/overlay/template_gen.py | 105 ++++++ 4 files changed, 348 insertions(+), 121 deletions(-) create mode 100644 Source/sys-clk/overlay/template_gen.py diff --git a/Source/sys-clk/overlay/lang/en.json b/Source/sys-clk/overlay/lang/en.json index ede58e2e..da7a5105 100644 --- a/Source/sys-clk/overlay/lang/en.json +++ b/Source/sys-clk/overlay/lang/en.json @@ -1,79 +1,101 @@ { - "Horizon OC Zeus": "Horizon OC Zeus", - "Edit App Profile": "Edit App Profile", - "Advanced": "Advanced", - "Edit Global Profile": "Edit Global Profile", - "Temporary Overrides": "Temporary Overrides", - "Temporary Overrides Reset": "Temporary Overrides Reset", - "Settings": "Settings", "Information": "Information", - "Enable": "Enable", - "Uncapped Clocks": "Uncapped Clocks", - "Override Boost Mode": "Override Boost Mode", - "CPU Max Display Clock": "CPU Max Display Clock", - "Thermal Throttle": "Thermal Throttle", - "Thermal Throttle Threshold": "Thermal Throttle Threshold", - "Handheld TDP": "Handheld TDP", - "Handheld TDP Limit": "Handheld TDP Limit", - "Lite TDP Limit": "Lite TDP Limit", - "Enforce Board Limit": "Enforce Board Limit", - "Battery Charge Current": "Battery Charge Current", - "Display Refresh Rate Changing": "Display Refresh Rate Changing", - "Fix CPU Volt Bug": "Fix CPU Volt Bug", - "[cfg] no enum format string": "[cfg] no enum format string", - "KIP": "KIP", - "Save KIP Settings": "Save KIP Settings", - "RAM Settings": "RAM Settings", - "CPU Settings": "CPU Settings", - "GPU Settings": "GPU Settings", - "Experimental": "Experimental", - "Charge Current Override": "Charge Current Override", + "Speedo:": "Speedo:", + "IDDQ:": "IDDQ:", + "Module: ": "Module: ", + "sys-dock status:": "sys-dock status:", + "SaltyNX status:": "SaltyNX status:", + "RR Display status:": "RR Display status:", + "Wafer Position:": "Wafer Position:", + "Credits": "Credits", + "Developers": "Developers", + "Souldbminer": "Souldbminer", + "Lightos_": "Lightos_", + "Contributors": "Contributors", + "Dom": "Dom", + "Blaise25": "Blaise25", + "Testers": "Testers", + "Samybigio2011": "Samybigio2011", + "Delta": "Delta", + "Miki1305": "Miki1305", + "Happy": "Happy", + "Flopsider": "Flopsider", + "Winnerboi77": "Winnerboi77", + "WE1ZARD": "WE1ZARD", + "Alvise": "Alvise", + "TDRR": "TDRR", + "agjeococh": "agjeococh", + "Xenshen": "Xenshen", + "Frost": "Frost", + "Special Thanks": "Special Thanks", + "ScriesM - Atmosphere CFW": "ScriesM - Atmosphere CFW", + "KazushiMe - Switch OC Suite": "KazushiMe - Switch OC Suite", + "hanai3bi - Switch OC Suite & EOS": "hanai3bi - Switch OC Suite & EOS", + "NaGaa95 - L4T-OC-Kernel": "NaGaa95 - L4T-OC-Kernel", + "B3711 - EOS": "B3711 - EOS", + "RetroNX - sys-clk": "RetroNX - sys-clk", + "b0rd2death - Ultrahand": "b0rd2death - Ultrahand", + "MasaGratoR - Status Monitor": "MasaGratoR - Status Monitor", + "Cat": "Cat", + "HB-MGCH 4GB": "HB-MGCH 4GB", + "HM-MGCH 6GB": "HM-MGCH 6GB", + "HM-MGXX 8GB": "HM-MGXX 8GB", + "NLE": "NLE", + "WT:C": "WT:C", + "NEE": "NEE", + "AM-MGCJ 4GB": "AM-MGCJ 4GB", + "AM-MGCJ 8GB": "AM-MGCJ 8GB", + "NME": "NME", + "WT:E": "WT:E", + "AA-MGCL 4GB": "AA-MGCL 4GB", + "AA-MGCL 8GB": "AA-MGCL 8GB", + "AB-MGCL 4GB": "AB-MGCL 4GB", + "WT:F": "WT:F", + "WT:B": "WT:B", + "Unknown": "Unknown", + "Installed": "Installed", + "Not Installed": "Not Installed", + "X: %u Y: %u": "X: %u Y: %u", + "THE BEER-WARE LICENSE": "THE BEER-WARE LICENSE", + "Default": "Default", + "Governor": "Governor", + "CPU": "CPU", + "GPU": "GPU", + "VRR": "VRR", + "Do Not Override": "Do Not Override", "Disabled": "Disabled", - "HP Mode": "HP Mode", - "EMC Max Clock": "EMC Max Clock", - "EMC VDD2 Voltage": "EMC VDD2 Voltage", - "EMC VDDQ Voltage": "EMC VDDQ Voltage", - "DVB Shift": "DVB Shift", - "Memory Timings": "Memory Timings", - "Memory Latencies": "Memory Latencies", - "t1 tRCD": "t1 tRCD", - "t2 tRP": "t2 tRP", - "t3 tRAS": "t3 tRAS", - "t4 tRRD": "t4 tRRD", - "t5 tRFC": "t5 tRFC", - "t6 tRTW": "t6 tRTW", - "t7 tWTR": "t7 tWTR", - "t8 tREFI": "t8 tREFI", - "Update RAM Timings": "Update RAM Timings", - "\uE150 This feature is EXPERIMENTAL": "\uE150 This feature is EXPERIMENTAL", - "and should only be used for testing!": "and should only be used for testing!", - "Read Latency": "Read Latency", - "Write Latency": "Write Latency", - "CPU UV": "CPU UV", - "CPU Unlock": "CPU Unlock", - "CPU VMIN": "CPU VMIN", - "CPU Max Voltage": "CPU Max Voltage", - "CPU UV Table": "CPU UV Table", - "CPU Low UV": "CPU Low UV", - "CPU High UV": "CPU High UV", - "CPU Max Clock": "CPU Max Clock", - "CPU Low VMIN": "CPU Low VMIN", - "CPU High VMIN": "CPU High VMIN", - "GPU Undervolt Table": "GPU Undervolt Table", - "Calculate GPU Vmin": "Calculate GPU Vmin", - "GPU VMIN": "GPU VMIN", - "GPU VMAX": "GPU VMAX", - "GPU Volt Offset": "GPU Volt Offset", - "GPU Custom Table": "GPU Custom Table", - "GPU Custom Table (mV)": "GPU Custom Table (mV)", - "\uE150 Setting GPU Clocks past": "\uE150 Setting GPU Clocks past", - "1075MHz without UV, 1152MHz on SLT or ": "1075MHz without UV, 1152MHz on SLT or ", - "1228MHz on HiOPT can cause ": "1228MHz on HiOPT can cause ", - "permanent damage to your Switch!": "permanent damage to your Switch!", - "Proceed at your own risk!": "Proceed at your own risk!", - "921MHz without UV and 960MHz on": "921MHz without UV and 960MHz on", - "SLT or HiOPT can cause ": "SLT or HiOPT can cause ", - "Auto": "Auto", + "Enabled": "Enabled", + " \\ue0e3 Reset": " \\ue0e3 Reset", + "Display": "Display", + "Application changed\\n\\n": "Application changed\\n\\n", + "The running application changed\\n\\n": "The running application changed\\n\\n", + "while editing was going on.": "while editing was going on.", + "Horizon OC Zeus": "Horizon OC Zeus", + "App ID": "App ID", + "Profile": "Profile", + "MEM": "MEM", + "SoC": "SoC", + "Board": "Board", + "Skin": "Skin", + "Now": "Now", + "Avg": "Avg", + "BAT": "BAT", + "PMIC": "PMIC", + "FAN": "FAN", + "DISP": "DISP", + "FPS": "FPS", + "RES": "RES", + "USB Charger": "USB Charger", + "%u.%u%u mV": "%u.%u%u mV", + "N/A": "N/A", + "Could not connect to hoc-clk sysmodule.\\n\\n": "Could not connect to hoc-clk sysmodule.\\n\\n", + "Please make sure everything is\\n\\n": "Please make sure everything is\\n\\n", + "correctly installed and enabled.": "correctly installed and enabled.", + "Fatal error": "Fatal error", + "cpu": "cpu", + "gpu": "gpu", + "mem": "mem", + "Temporary Overrides ": "Temporary Overrides ", "Sleep Mode": "Sleep Mode", "Stock": "Stock", "Dev OC": "Dev OC", @@ -81,52 +103,138 @@ "Safe Max": "Safe Max", "Unsafe Max": "Unsafe Max", "Absolute Max": "Absolute Max", - "Boost Mode & Safe Max": "Boost Mode & Safe Max", + "Handheld": "Handheld", + "Handheld Safe Max": "Handheld Safe Max", + "Docked": "Docked", + "Enable": "Enable", + "Edit App Profile": "Edit App Profile", + "Edit Global Profile": "Edit Global Profile", + "Temporary Overrides": "Temporary Overrides", + "Misc": "Misc", + "Settings": "Settings", + "About": "About", + "Compiling with minimal features": "Compiling with minimal features", + "General Settings": "General Settings", + "Governor Settings": "Governor Settings", + "Safety Settings": "Safety Settings", + "KIP": "KIP", + "Save KIP Settings": "Save KIP Settings", + "RAM Settings": "RAM Settings", + "CPU Settings": "CPU Settings", + "GPU Settings": "GPU Settings", + "Display Settings": "Display Settings", + "Experimental": "Experimental", + "INI": "INI", + "NV Service": "NV Service", + "GPU Scheduling Override Method": "GPU Scheduling Override Method", + "can be dangerous and may cause": "can be dangerous and may cause", + "damage to your battery or charger!": "damage to your battery or charger!", + "Charge Current Override": "Charge Current Override", + "VDD2 + VDDQ": "VDD2 + VDDQ", + "VDD2 + Usage": "VDD2 + Usage", + "VDDQ + Usage": "VDDQ + Usage", + "RAM Voltage Display Mode": "RAM Voltage Display Mode", + "Polling Interval": "Polling Interval", + "CPU Governor Minimum Frequency": "CPU Governor Minimum Frequency", + "refresh rates may cause stress": "refresh rates may cause stress", + "or damage to your display! ": "or damage to your display! ", + "Proceed at your own risk!": "Proceed at your own risk!", + "Max Handheld Display": "Max Handheld Display", + "Display Clock": "Display Clock", "Official Rating": "Official Rating", + "TDP Threshold": "TDP Threshold", + "Power": "Power", + "Thermal Throttle Limit": "Thermal Throttle Limit", + "Temp": "Temp", + "HP Mode": "HP Mode", "Default (Mariko)": "Default (Mariko)", "Default (Erista)": "Default (Erista)", "Rating": "Rating", "Safe Max (Mariko)": "Safe Max (Mariko)", "Safe Max (Erista)": "Safe Max (Erista)", - "Default": "Default", + "RAM VDD2 Voltage": "RAM VDD2 Voltage", + "Voltage": "Voltage", + "RAM VDDQ Voltage": "RAM VDDQ Voltage", + "SoC DVB Shift": "SoC DVB Shift", + "RAM Frequency Editor": "RAM Frequency Editor", + "JEDEC.": "JEDEC.", + "High speedo needed!": "High speedo needed!", + "3333MHz (Needs extreme Speedo/PLL)": "3333MHz (Needs extreme Speedo/PLL)", + "3366MHz (Needs extreme Speedo/PLL)": "3366MHz (Needs extreme Speedo/PLL)", + "3400MHz (Needs extreme Speedo/PLL)": "3400MHz (Needs extreme Speedo/PLL)", + "3433MHz (Needs ridiculous Speedo/PLL)": "3433MHz (Needs ridiculous Speedo/PLL)", + "3466MHz (Needs ridiculous Speedo/PLL)": "3466MHz (Needs ridiculous Speedo/PLL)", + "3500MHz (Needs ridiculous Speedo/PLL)": "3500MHz (Needs ridiculous Speedo/PLL)", + "Ram Max Clock": "Ram Max Clock", + "RAM Latency Editor": "RAM Latency Editor", + "RAM Timing Reductions": "RAM Timing Reductions", + "Memory Timings": "Memory Timings", + "t1 tRCD": "t1 tRCD", + "tRCD": "tRCD", + "t2 tRP": "t2 tRP", + "tRP": "tRP", + "t3 tRAS": "t3 tRAS", + "tRAS": "tRAS", + "t4 tRRD": "t4 tRRD", + "tRRD": "tRRD", + "t5 tRFC": "t5 tRFC", + "tRFC": "tRFC", + "t6 tRTW": "t6 tRTW", + "tRTW": "tRTW", + "t7 tWTR": "t7 tWTR", + "tWTR": "tWTR", + "t8 tREFI": "t8 tREFI", + "tREFI": "tREFI", + "Advanced": "Advanced", + "t6 tRTW Fine Tune": "t6 tRTW Fine Tune", + "tRTW Fine Tune": "tRTW Fine Tune", + "t7 tWTR Fine Tune": "t7 tWTR Fine Tune", + "tWTR Fine Tune": "tWTR Fine Tune", + "Memory Latencies": "Memory Latencies", + "1333 RL": "1333 RL", + "1600 RL": "1600 RL", + "1866 RL": "1866 RL", + "2133 RL": "2133 RL", + "Read Latency": "Read Latency", + "Write Latency": "Write Latency", + "CPU Boost Clock": "CPU Boost Clock", + "CPU UV": "CPU UV", + "CPU Unlock": "CPU Unlock", + "CPU VMIN": "CPU VMIN", + "CPU Max Voltage": "CPU Max Voltage", + "CPU Max Clock": "CPU Max Clock", + "Auto": "Auto", "1581MHz Tbreak": "1581MHz Tbreak", "1683MHz Tbreak": "1683MHz Tbreak", "Extreme UV Table": "Extreme UV Table", - "No UV": "No UV", + "CPU UV Table": "CPU UV Table", + "CPU Low UV": "CPU Low UV", + "CPU High UV": "CPU High UV", + "CPU Low VMIN": "CPU Low VMIN", + "CPU High VMIN": "CPU High VMIN", + "No Undervolt": "No Undervolt", "SLT Table": "SLT Table", "HiOPT Table": "HiOPT Table", - "Power": "Power", - "Temp": "Temp", - "Voltage": "Voltage", - "TDP Threshold": "TDP Threshold", - "Lite TDP Threshold": "Lite TDP Threshold", - "Thermal Throttle Limit": "Thermal Throttle Limit", - "1600BL": "1600BL", - "1866BL": "1866BL", - "2133BL": "2133BL", - "BAT": "BAT", - "FAN": "FAN", - "DISP": "DISP", - "Board": "Board", - "Skin": "Skin", - "Now": "Now", - "Avg": "Avg", - "App ID": "App ID", - "Profile": "Profile", - "CPU": "CPU", - "GPU": "GPU", - "Memory": "Memory", - "Display": "Display", - "Governor": "Governor", - "SOC": "SOC", - "PCB": "PCB", - "PMIC": "PMIC", - "Docked": "Docked", - "Handheld": "Handheld", - "Charging": "Charging", - "USB Charger": "USB Charger", - "PD Charger": "PD Charger", - "VDD2": "VDD2", - "VDDQ": "VDDQ", - "GPU DVFS": "GPU DVFS" -} \ No newline at end of file + "GPU Undervolt Table": "GPU Undervolt Table", + "GPU Minimum Voltage": "GPU Minimum Voltage", + "Calculate GPU Vmin": "Calculate GPU Vmin", + "GPU VMIN": "GPU VMIN", + "GPU Maximum Voltage": "GPU Maximum Voltage", + "GPU Voltage Offset": "GPU Voltage Offset", + "Do not override": "Do not override", + "Enabled (Default)": "Enabled (Default)", + "96.6% limit": "96.6% limit", + "99.7% limit": "99.7% limit", + "GPU Scheduling Override": "GPU Scheduling Override", + "PCV Hijack": "PCV Hijack", + "Official Service": "Official Service", + "GPU DVFS Mode": "GPU DVFS Mode", + "GPU DVFS Offset": "GPU DVFS Offset", + "GPU Voltage Table": "GPU Voltage Table", + "GPU Custom Table (mV)": "GPU Custom Table (mV)", + "1075MHz without UV, 1152MHz on SLT": "1075MHz without UV, 1152MHz on SLT", + "or 1228MHz on HiOPT can cause ": "or 1228MHz on HiOPT can cause ", + "permanent damage to your Switch!": "permanent damage to your Switch!", + "921MHz without UV and 960MHz on": "921MHz without UV and 960MHz on", + "SLT or HiOPT can cause ": "SLT or HiOPT can cause " +} diff --git a/Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.cpp index 68fce9d8..311ce921 100644 --- a/Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.cpp @@ -56,14 +56,15 @@ FreqChoiceGui::~FreqChoiceGui() tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool selected, int safety) { std::string text = formatListFreqHz(hz); - if (selected) - text += " \uE14B"; std::string rightText = ""; auto it = labels.find(hz); if (it != labels.end()) rightText = it->second; + if (selected) + const_cast(rightText) = "\uE14B"; + tsl::elm::ListItem* listItem = new tsl::elm::ListItem(text, rightText, false); @@ -84,8 +85,10 @@ tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool sel } // Make annotation grey - if (!rightText.empty()) + if (!rightText.empty() && !selected) listItem->setValueColor(tsl::Color(180, 180, 180, 255)); + else if(selected) + listItem->setValueColor(tsl::infoTextColor); listItem->setClickListener([this, hz](u64 keys) { diff --git a/Source/sys-clk/overlay/src/ui/gui/value_choice_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/value_choice_gui.cpp index eb15316e..9b8d6265 100644 --- a/Source/sys-clk/overlay/src/ui/gui/value_choice_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/value_choice_gui.cpp @@ -83,14 +83,17 @@ int ValueChoiceGui::getSafetyLevel(std::uint32_t value) tsl::elm::ListItem* ValueChoiceGui::createValueListItem(std::uint32_t value, bool selected, int safety) { std::string text = formatValue(value); - if (selected) { - text += " \uE14B"; - } std::string rightText = ""; + auto it = labels.find(value); if (it != labels.end()) { rightText = it->second; } + + if (selected) { + const_cast(rightText) = "\uE14B"; + } + tsl::elm::ListItem* listItem = new tsl::elm::ListItem(text, rightText, false); switch (safety) { @@ -107,8 +110,13 @@ tsl::elm::ListItem* ValueChoiceGui::createValueListItem(std::uint32_t value, boo listItem->setValueColor(tsl::Color(255, 0, 0, 255)); break; } - if (!rightText.empty()) + + // Make annotation grey + if (!rightText.empty() && !selected) listItem->setValueColor(tsl::Color(180, 180, 180, 255)); + else if(selected) + listItem->setValueColor(tsl::infoTextColor); + listItem->setClickListener([this, value](u64 keys) { if ((keys & HidNpadButton_A) == HidNpadButton_A && this->listener) { @@ -126,7 +134,7 @@ tsl::elm::ListItem* ValueChoiceGui::createNamedValueListItem(const NamedValue& n { std::string text = namedValue.name; if (selected) { - text += " \uE14B"; + const_cast(namedValue.rightText) = "\uE14B"; } tsl::elm::ListItem* listItem = new tsl::elm::ListItem(text, namedValue.rightText, false); @@ -145,9 +153,12 @@ tsl::elm::ListItem* ValueChoiceGui::createNamedValueListItem(const NamedValue& n listItem->setValueColor(tsl::Color(255, 0, 0, 255)); break; } - if (!namedValue.rightText.empty()) + + if (!namedValue.rightText.empty() && !selected) listItem->setValueColor(tsl::Color(180, 180, 180, 255)); - + else if(selected) + listItem->setValueColor(tsl::infoTextColor); + listItem->setClickListener([this, value = namedValue.value](u64 keys) { if ((keys & HidNpadButton_A) == HidNpadButton_A && this->listener) { diff --git a/Source/sys-clk/overlay/template_gen.py b/Source/sys-clk/overlay/template_gen.py new file mode 100644 index 00000000..ebb2e4cb --- /dev/null +++ b/Source/sys-clk/overlay/template_gen.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +import os +import re +import json + +SOURCE_DIR = os.path.join("src", "ui", "gui") +OUTPUT_FILE = os.path.join("lang", "en.json") + +IGNORED_PREFIXES = ( + "/", "\\", + "sysclk", "hocclk", "horizonoc", + "\\u", +) + + +def extract_strings_from_file(filepath: str) -> list[str]: + with open(filepath, "r", encoding="utf-8", errors="ignore") as f: + content = f.read() + + pattern = r'"((?:[^"\\]|\\.)*)"' + return re.findall(pattern, content) + + +def should_include(s: str) -> bool: + if not s or s.isspace(): + return False + + stripped = s.strip() + lower = stripped.lower() + + for prefix in IGNORED_PREFIXES: + if s.startswith(prefix): + return False + + if re.match(r"^\\u[0-9a-fA-F]", s): + return False + + if re.fullmatch(r"[a-zA-Z0-9_./\\-]+\.(h|hpp|cpp|c)", stripped): + return False + + if re.fullmatch(r"[%\d.*\-+lfdsuxXpLh ]*", stripped) and "%" in stripped: + return False + + if re.fullmatch(r"[\\nt ]*", stripped): + return False + + if re.fullmatch(r"[+\- ]*\d+\.?\d*\s*(MHz|mV|mA|mW|Hz|ms|°C|%%|p)?", stripped): + return False + + if re.fullmatch(r"[%\d./*+\-ufdsxXlLhp ,°CM:HzWmVA\\n]+", stripped): + return False + + if re.match(r"^hocClkIpc", stripped): + return False + + if len(stripped) <= 2 and not stripped.isalpha(): + return False + + if re.fullmatch(r"(\\[nt])+", stripped): + return False + + if re.fullmatch(r"[\s]*(\\u[0-9a-fA-F]{4}[\s]*)+", stripped): + return False + + return True + + +def main(): + seen: set[str] = set() + strings: list[str] = [] + + if not os.path.isdir(SOURCE_DIR): + print(f"Error: directory '{SOURCE_DIR}' not found.") + return + + for filename in sorted(os.listdir(SOURCE_DIR)): + if not filename.endswith((".cpp", ".h")): + continue + + filepath = os.path.join(SOURCE_DIR, filename) + for s in extract_strings_from_file(filepath): + if s not in seen and should_include(s): + seen.add(s) + strings.append(s) + + translations = {s: s for s in strings} + + os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True) + + with open(OUTPUT_FILE, "w", encoding="utf-8") as f: + f.write("{\n") + items = list(translations.items()) + for i, (key, val) in enumerate(items): + k = json.dumps(key, ensure_ascii=False) + v = json.dumps(val, ensure_ascii=False) + comma = "," if i < len(items) - 1 else "" + f.write(f" {k}: {v}{comma}\n") + f.write("}\n") + + print(f"Extracted {len(translations)} unique strings from {SOURCE_DIR}") + print(f"Written to {OUTPUT_FILE}") + + +if __name__ == "__main__": + main() \ No newline at end of file