From 5fcdda16f6816e95e4e79ff99a4899c2338673ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Mon, 24 Apr 2023 13:48:34 +0200 Subject: [PATCH] filter translation strings and only include the ones needed --- Translations/make_translation.py | 46 +++++++++++++++++++--- Translations/translations_definitions.json | 35 ++++++++++++++++ build.sh | 0 source/Makefile | 21 +++++++--- 4 files changed, 91 insertions(+), 11 deletions(-) mode change 100644 => 100755 build.sh diff --git a/Translations/make_translation.py b/Translations/make_translation.py index dbe4c9a4..6af0d6e0 100755 --- a/Translations/make_translation.py +++ b/Translations/make_translation.py @@ -66,6 +66,29 @@ def read_translation(json_root: Union[str, Path], lang_code: str) -> dict: return lang +def filter_translation(lang: dict, defs: dict, macros: frozenset): + def check_excluded(record): + if "include" in record and not any(m in macros for m in record["include"]): + return True + + if "exclude" in record and any(m in macros for m in record["exclude"]): + return True + + return False + + for category in ("menuOptions", "menuGroups"): + for index, record in enumerate(defs[category]): + if check_excluded(record): + lang[category][record["id"]]["displayText"] = "" + lang[category][record["id"]]["description"] = "" + + for index, record in enumerate(defs["messagesWarn"]): + if check_excluded(record): + lang["messagesWarn"][record["id"]]["message"] = "" + + return lang + + def validate_langcode_matches_content(filename: str, content: dict) -> None: # Extract lang code from file name lang_code = filename[12:-5].upper() @@ -252,7 +275,6 @@ def get_letter_counts(defs: dict, lang: dict, build_version: str) -> Dict: # collapse all strings down into the composite letters and store totals for these # Doing this seperately for small and big font def sort_and_count(list_in: List[str]): - symbol_counts: dict[str, int] = {} for line in list_in: line = line.replace("\n", "").replace("\r", "") @@ -441,7 +463,6 @@ class FontMapsPerFont: def get_font_map_per_font( text_list_small_font: List[str], text_list_large_font: List[str] ) -> FontMapsPerFont: - pending_small_symbols = set(text_list_small_font) pending_large_symbols = set(text_list_large_font) @@ -1031,7 +1052,6 @@ def get_translation_strings_and_indices_text( large_font_symbol_conversion_table: Dict[str, bytes], suffix: str = "", ) -> str: - # For all strings; we want to convert them to their byte encoded form (using font index lookups) # Then we want to sort by their reversed format to see if we can remove any duplicates by combining the tails (last n bytes;n>0) # Finally we look for any that are contained inside one another, and if they are we update them to point to this @@ -1120,7 +1140,6 @@ def get_translation_strings_and_indices_text( translation_strings_text = " /* .strings = */ {\n" for i, encoded_bytes in enumerate(byte_encoded_strings): - if i > 0: translation_strings_text += ' "\\0"\n' @@ -1287,6 +1306,13 @@ def parse_args() -> argparse.Namespace: required=False, dest="compress_font", ) + parser.add_argument( + "--macros", + help="Extracted macros to filter translation strings by", + type=argparse.FileType("r"), + required=True, + dest="macros", + ) parser.add_argument( "--output", "-o", help="Target file", type=argparse.FileType("w"), required=True ) @@ -1307,6 +1333,12 @@ def main() -> None: logging.error("error: Both --output-pickled and --input-pickled are specified") sys.exit(1) + macros = ( + frozenset(re.findall(r"#define ([^ ]+)", args.macros.read())) + if args.macros + else frozenset() + ) + language_data: LanguageData if args.input_pickled: logging.info(f"Reading pickled language data from {args.input_pickled.name}...") @@ -1331,11 +1363,13 @@ def main() -> None: defs_ = load_json(os.path.join(json_dir, "translations_definitions.json")) if len(args.languageCodes) == 1: - lang_ = read_translation(json_dir, args.languageCodes[0]) + lang_ = filter_translation( + read_translation(json_dir, args.languageCodes[0]), defs_, macros + ) language_data = prepare_language(lang_, defs_, build_version) else: langs_ = [ - read_translation(json_dir, lang_code) + filter_translation(read_translation(json_dir, lang_code), defs_, macros) for lang_code in args.languageCodes ] language_data = prepare_languages(langs_, defs_, build_version) diff --git a/Translations/translations_definitions.json b/Translations/translations_definitions.json index 875dd2cb..2229ddf9 100644 --- a/Translations/translations_definitions.json +++ b/Translations/translations_definitions.json @@ -17,6 +17,7 @@ }, { "id": "NoPowerDeliveryMessage", + "include": ["POW_PD"], "description": "The IC required for USB-PD could not be communicated with. This is an error warning that USB-PD WILL NOT FUNCTION. Generally indicative of either a hardware or software issues." }, { @@ -49,42 +50,50 @@ { "id": "UVLOWarningString", "maxLen": 8, + "include": ["POW_DC"], "description": "Warning text shown when the unit turns off due to undervoltage in simple mode." }, { "id": "UndervoltageString", "maxLen": 15, + "include": ["POW_DC"], "description": "Warning text shown when the unit turns off due to undervoltage in advanced mode." }, { "id": "InputVoltageString", "maxLen": 11, "note": "Preferably end with a space", + "include": ["POW_DC"], "description": "Prefix text for 'Input Voltage' shown before showing the input voltage reading." }, { "id": "ProfilePreheatString", "maxLen": 9, + "include": ["PROFILE_SUPPORT"], "description": "Shown when the soldering profile is preheating" }, { "id": "ProfileCooldownString", "maxLen": 9, + "include": ["PROFILE_SUPPORT"], "description": "Shown when the soldering profile is done and cooling down" }, { "id": "SleepingSimpleString", "maxLen": 4, + "exclude": ["NO_SLEEP_MODE"], "description": "The text shown to indicate the unit is in sleep mode when the advanced view is NOT on." }, { "id": "SleepingAdvancedString", "maxLen": 15, + "exclude": ["NO_SLEEP_MODE"], "description": "The text shown to indicate the unit is in sleep mode when the advanced view is turned on." }, { "id": "SleepingTipAdvancedString", "maxLen": 6, + "exclude": ["NO_SLEEP_MODE"], "description": "The prefix text shown before tip temperature when the unit is sleeping with advanced view on." }, { @@ -100,6 +109,7 @@ { "id": "TooHotToStartProfileWarning", "default": "Too hot to\nstart profile", + "include": ["PROFILE_SUPPORT"], "description": "Shown when profile mode is started while the device is too hot." } ], @@ -181,6 +191,7 @@ "id": "PowerMenu", "maxLen": 5, "maxLen2": 11, + "include": ["POW_DC", "POW_QC"], "description": "Menu for settings related to power. Main settings to do with the input voltage." }, { @@ -212,30 +223,35 @@ "id": "DCInCutoff", "maxLen": 5, "maxLen2": 11, + "include": ["POW_DC"], "description": "When the device is powered by a battery, this adjusts the low voltage threshold for when the unit should turn off the heater to protect the battery." }, { "id": "MinVolCell", "maxLen": 4, "maxLen2": 9, + "include": ["POW_DC"], "description": "When powered by a battery, this adjusts the minimum voltage per cell before shutdown. (This is multiplied by the cell count.)" }, { "id": "QCMaxVoltage", "maxLen": 8, "maxLen2": 15, + "include": ["POW_QC"], "description": "This adjusts the maximum voltage the QC negotiation will adjust to. Does NOT affect USB-PD. Should be set safely based on the current rating of your power supply." }, { "id": "PDNegTimeout", "maxLen": 8, "maxLen2": 15, + "include": ["POW_PD"], "description": "How long until firmware stops trying to negotiate for USB-PD and tries QC instead. Longer times may help dodgy / old PD adapters, faster times move onto PD quickly. Units of 100ms. Recommended to keep small values." }, { "id": "PDVpdo", "maxLen": 7, "maxLen2": 15, + "include": ["POW_PD"], "description": "Enabled PPS & EPR modes." }, { @@ -272,84 +288,98 @@ "id": "ProfilePhases", "maxLen": 6, "maxLen2": 13, + "include": ["PROFILE_SUPPORT"], "description": "set the number of phases for the soldering profile." }, { "id": "ProfilePreheatTemp", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "For the soldering profile, preheat to this temperature before proceeding with phase 1." }, { "id": "ProfilePreheatSpeed", "maxLen": 5, "maxLen2": 11, + "include": ["PROFILE_SUPPORT"], "description": "How fast the temperature is allowed to rise during the heatup phase of the soldering profile." }, { "id": "ProfilePhase1Temp", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Target temperature for the end of phase 1 of the soldering profile." }, { "id": "ProfilePhase1Duration", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Duration of phase 1 of the soldering profile. The phase might actually take longer if it takes longer to reach the target temperature." }, { "id": "ProfilePhase2Temp", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Target temperature for the end of phase 2 of the soldering profile." }, { "id": "ProfilePhase2Duration", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Duration of phase 2 of the soldering profile. The phase might actually take longer if it takes longer to reach the target temperature." }, { "id": "ProfilePhase3Temp", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Target temperature for the end of phase 3 of the soldering profile." }, { "id": "ProfilePhase3Duration", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Duration of phase 3 of the soldering profile. The phase might actually take longer if it takes longer to reach the target temperature." }, { "id": "ProfilePhase4Temp", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Target temperature for the end of phase 5 of the soldering profile." }, { "id": "ProfilePhase4Duration", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Duration of phase 5 of the soldering profile. The phase might actually take longer if it takes longer to reach the target temperature." }, { "id": "ProfilePhase5Temp", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Target temperature for the end of phase 5 of the soldering profile." }, { "id": "ProfilePhase5Duration", "maxLen": 4, "maxLen2": 9, + "include": ["PROFILE_SUPPORT"], "description": "Duration of phase 5 of the soldering profile. The phase might actually take longer if it takes longer to reach the target temperature." }, { "id": "ProfileCooldownSpeed", "maxLen": 5, "maxLen2": 11, + "include": ["PROFILE_SUPPORT"], "description": "How fast the temperature is allowed to drop after the last phase of the soldering profile." }, { @@ -362,12 +392,14 @@ "id": "SleepTemperature", "maxLen": 4, "maxLen2": 9, + "exclude": ["NO_SLEEP_MODE"], "description": "Temperature the device will drop down to while asleep. Typically around halfway between off and soldering temperature." }, { "id": "SleepTimeout", "maxLen": 4, "maxLen2": 9, + "exclude": ["NO_SLEEP_MODE"], "description": "How long of a period without movement / button-pressing is required before the device drops down to the sleep temperature." }, { @@ -380,6 +412,7 @@ "id": "HallEffSensitivity", "maxLen": 6, "maxLen2": 13, + "include": ["HALL_SENSOR"], "description": "If the unit has a hall effect sensor (Pinecil), this adjusts how sensitive it is at detecting a magnet to put the device into sleep mode." }, { @@ -392,6 +425,7 @@ "id": "DisplayRotation", "maxLen": 6, "maxLen2": 13, + "exclude": ["NO_DISPLAY_ROTATE"], "description": "If the display should rotate automatically or if it should be fixed for left- or right-handed mode." }, { @@ -458,6 +492,7 @@ "id": "BluetoothLE", "maxLen": 7, "maxLen2": 15, + "include": ["BLE_ENABLED"], "description": "Should BLE be enabled at boot time." }, { diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/source/Makefile b/source/Makefile index b6b663a3..4668d729 100644 --- a/source/Makefile +++ b/source/Makefile @@ -608,15 +608,21 @@ Core/Gen/Translation.%.cpp $(OUTPUT_DIR)/Core/Gen/translation.files/%.pickle: .. ../Translations/make_translation.py \ ../Translations/translations_definitions.json \ ../Translations/font_tables.py \ - Makefile ../Translations/wqy-bitmapsong/wenquanyi_9pt.bdf + Makefile ../Translations/wqy-bitmapsong/wenquanyi_9pt.bdf \ + Core/Gen/macros.txt @test -d Core/Gen || mkdir -p Core/Gen @test -d $(OUTPUT_DIR)/Core/Gen/translation.files || mkdir -p $(OUTPUT_DIR)/Core/Gen/translation.files @echo 'Generating translations for language $*' @python3 ../Translations/make_translation.py \ + --macros $(PWD)/Core/Gen/macros.txt \ -o $(PWD)/Core/Gen/Translation.$*.cpp \ --output-pickled $(OUTPUT_DIR)/Core/Gen/translation.files/$*.pickle \ $* +Core/Gen/macros.txt: Makefile + @test -d Core/Gen || mkdir -p Core/Gen + echo "#include " | $(CC) -dM -E $(CFLAGS) - > $(PWD)/Core/Gen/macros.txt + # # The recipes to produce compressed translation data: # @@ -636,19 +642,21 @@ $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so: Core/brieflz/brieflz.c Core/brieflz/de @echo Building host brieflz shared library $@ @$(HOST_CC) -fPIC -shared -DBLZ_DLL -DBLZ_DLL_EXPORTS -O $^ -o $@ -Core/Gen/Translation_brieflz.%.cpp: $(OUTPUT_DIR)/Core/Gen/translation.files/%.o $(OUTPUT_DIR)/Core/Gen/translation.files/%.pickle $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so +Core/Gen/Translation_brieflz.%.cpp: $(OUTPUT_DIR)/Core/Gen/translation.files/%.o $(OUTPUT_DIR)/Core/Gen/translation.files/%.pickle $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so Core/Gen/macros.txt @test -d $(@D) || mkdir -p $(@D) @echo Generating BriefLZ compressed translation for $* @OBJCOPY=$(OBJCOPY) python3 ../Translations/make_translation.py \ + --macros $(PWD)/Core/Gen/macros.txt \ -o $(PWD)/Core/Gen/Translation_brieflz.$*.cpp \ --input-pickled $(OUTPUT_DIR)/Core/Gen/translation.files/$*.pickle \ --strings-obj $(OUTPUT_DIR)/Core/Gen/translation.files/$*.o \ $* -Core/Gen/Translation_brieflz_font.%.cpp: $(OUTPUT_DIR)/Core/Gen/translation.files/%.pickle $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so +Core/Gen/Translation_brieflz_font.%.cpp: $(OUTPUT_DIR)/Core/Gen/translation.files/%.pickle $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so Core/Gen/macros.txt @test -d $(@D) || mkdir -p $(@D) @echo Generating BriefLZ compressed translation for $* @python3 ../Translations/make_translation.py \ + --macros $(PWD)/Core/Gen/macros.txt \ -o $(PWD)/Core/Gen/Translation_brieflz_font.$*.cpp \ --input-pickled $(OUTPUT_DIR)/Core/Gen/translation.files/$*.pickle \ --compress-font \ @@ -689,21 +697,24 @@ Core/Gen/Translation_multi.$(1).cpp: $(patsubst %,../Translations/translation_%. ../Translations/make_translation.py \ ../Translations/translations_definitions.json \ ../Translations/font_tables.py \ - Makefile ../Translations/wqy-bitmapsong/wenquanyi_9pt.bdf + Makefile ../Translations/wqy-bitmapsong/wenquanyi_9pt.bdf \ + Core/Gen/macros.txt @test -d Core/Gen || mkdir -p Core/Gen @test -d $(OUTPUT_DIR)/Core/Gen/translation.files || mkdir -p $(OUTPUT_DIR)/Core/Gen/translation.files @echo 'Generating translations for multi-language $(2)' @python3 ../Translations/make_translation.py \ + --macros $(PWD)/Core/Gen/macros.txt \ -o $(PWD)/Core/Gen/Translation_multi.$(1).cpp \ --output-pickled $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).pickle \ $(3) $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).pickle: Core/Gen/Translation_multi.$(1).cpp -Core/Gen/Translation_brieflz_multi.$(1).cpp: $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).o $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).pickle $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so +Core/Gen/Translation_brieflz_multi.$(1).cpp: $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).o $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).pickle $(HOST_OUTPUT_DIR)/brieflz/libbrieflz.so Core/Gen/macros.txt @test -d $$(@D) || mkdir -p $$(@D) @echo Generating BriefLZ compressed translation for multi-language $(2) @OBJCOPY=$(OBJCOPY) python3 ../Translations/make_translation.py \ + --macros $(PWD)/Core/Gen/macros.txt \ -o $(PWD)/Core/Gen/Translation_brieflz_multi.$(1).cpp \ --input-pickled $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).pickle \ --strings-obj $(OUTPUT_DIR)/Core/Gen/translation.files/multi.$(1).o \