123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- #!/usr/bin/env python3
- #
- # This script checks for duplicate shortcut keys in all translation files.
- #
- import collections
- import os
- import sys
- from typing import Optional
- COLOR_WARNING = '\033[93m'
- COLOR_ENDC = '\033[0m'
- regex_patter = '(&[\w])' #"&[a-zA-Z0-9]" - Search char '&' and at least one character after it
- # Directory where this python file resides
- SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
- class ShortcutKeysChecker:
- MSGCTXT = "msgctxt" # Scope of the text . Like : msgctxt "@action:inmenu menubar:help"
- MSGID = "msgid" # The id tag, also English text version
- MSGSTR = "msgstr" # The translation tag
- def has_duplicates(self, filename: str) -> bool:
- """
- Checks if the given file has duplicate shortcut keys.
- """
- with open(filename, "r", encoding = "utf-8") as f:
- all_lines = f.readlines()
- all_lines = [l.strip() for l in all_lines]
- shortcut_dict = collections.defaultdict(dict)
- found_ctxt = False
- current_data = dict()
- current_field = None
- start_line = None
- for idx, line in enumerate(all_lines):
- if line.startswith(self.MSGCTXT):
- found_ctxt = True
- current_data.clear()
- current_field = self.MSGCTXT
- current_data[current_field] = self._fetch_data(line)
- start_line = idx
- continue
- elif found_ctxt and line.startswith(self.MSGID):
- current_field = self.MSGID
- current_data[current_field] = self._fetch_data(line)
- continue
- elif found_ctxt and line.startswith(self.MSGSTR):
- current_field = self.MSGSTR
- current_data[current_field] = self._fetch_data(line)
- continue
- elif found_ctxt and line.startswith('"'):
- data = line[1:-1] # strip the beginning and ending double-quotes
- current_data[current_field] += data
- continue
- if current_data:
- self._process_translation(shortcut_dict, current_data, start_line)
- current_data.clear()
- current_field = None
- found_ctxt = False
- start_line = None
- return self._show_all_duplicates(shortcut_dict, filename)
- def _fetch_data(self, line: str) -> str:
- return (line.split(" ", 1)[-1])[1:-1]
- def _process_translation(self, shortcut_dict: dict, data_dict: dict, start_line: int) -> None:
- # Only check the ones with shortcuts
- msg = data_dict[self.MSGID]
- if data_dict[self.MSGSTR]:
- msg = data_dict[self.MSGSTR]
- shortcut_key = self._get_shortcut_key(msg)
- if shortcut_key is None:
- return
- msg_section = data_dict[self.MSGCTXT]
- keys_dict = shortcut_dict[msg_section]
- if shortcut_key not in keys_dict:
- keys_dict[shortcut_key] = {"shortcut_key": shortcut_key,
- "section": msg_section,
- "existing_lines": dict(),
- }
- existing_data_dict = keys_dict[shortcut_key]["existing_lines"]
- existing_data_dict[start_line] = {"message": msg,
- }
- def _get_shortcut_key(self, text: str) -> Optional[str]:
- key = None
- if text.count("&") == 1:
- idx = text.find("&") + 1
- if idx < len(text):
- character = text[idx]
- if not character.isspace():
- key = character.lower()
- return key
- def _show_all_duplicates(self, shortcut_dict: dict, filename: str) -> bool:
- has_duplicates = False
- for keys_dict in shortcut_dict.values():
- for shortcut_key, data_dict in keys_dict.items():
- if len(data_dict["existing_lines"]) == 1:
- continue
- has_duplicates = True
- print("")
- print("The following messages have the same shortcut key '%s':" % shortcut_key)
- print(" shortcut: '%s'" % data_dict["shortcut_key"])
- print(" section : '%s'" % data_dict["section"])
- for line, msg in data_dict["existing_lines"].items():
- relative_filename = (filename.rsplit("..", 1)[-1])[1:]
- print(" - [%s] L%7d : '%s'" % (relative_filename, line, msg["message"]))
- return has_duplicates
- if __name__ == "__main__":
- checker = ShortcutKeysChecker()
- all_dirnames = [""]
- for _, dirnames, _ in os.walk(os.path.join(SCRIPT_DIR, "..", "resources", "i18n")):
- all_dirnames += [dn for dn in dirnames]
- break
- found_duplicates = False
- for dirname in all_dirnames:
- file_name = "cura.pot" if not dirname else "cura.po"
- file_path = os.path.join(SCRIPT_DIR, "..", "resources", "i18n", dirname, file_name)
- found_duplicates = found_duplicates or checker.has_duplicates(file_path)
- sys.exit(0 if not found_duplicates else 1)
|