#!/usr/bin/python # Author: @xstraok # Modified by Observer KRypt0n_ import os import sys import glob import re import pydoc valid_commands = ["diff", "unused", "missing"] if len(sys.argv) >= 2 and sys.argv[1] != "diff": path = "assets/locales/en/" elif len(sys.argv) < 3: print(f"Command format: ./fluentscan.py [command] [locale]\nAvailable commands: {valid_commands}") sys.exit() else: path = "assets/locales/" + sys.argv[2] + "/" command = sys.argv[1] if command not in valid_commands: print(f"Invalid command \"{command}\". Available commands: {valid_commands}") sys.exit() try: open(path + "/main.ftl", "r").close() except: print(f"{path} does not exist") sys.exit() def dict_compare(d1, d2): d1_keys = set(d1.keys()) d2_keys = set(d2.keys()) shared_keys = d1_keys.intersection(d2_keys) added = d1_keys - d2_keys removed = d2_keys - d1_keys same = set(o for o in shared_keys if d1[o] == d2[o]) return added, removed, same def to_dict(text): result={} for i in text: if " =" in i: try: result[i.split()[0]] = ' '.join(i.split()[2:]) except: pass elif i: result[list(result.keys())[-1]] += i return result def get_line_num(file,pattern): line = 1 file.seek(0) text = file.read() for i in text.split("\n"): if sys.argv[1] == "diff": if i == pattern: return line if pattern in i: return line line += 1 # format = {variable : file name} used_entries = {} unused_entries = {} missing_entries = {} # format = {variable : [file name, line number]} script_entries = {} all_entries = {} # format = {variable : definition} every_variable = {} files = glob.glob("src/**/*.rs", recursive=True) output="" for filename in os.listdir("assets/locales/en"): with open(os.path.join("assets/locales/en", filename), 'r') as locale_file: created_locale = open(path + filename) en_variables = to_dict(locale_file) every_variable.update(en_variables) for i in en_variables: all_entries[i] = [filename, get_line_num(locale_file, i)] # resets the file read locale_file.seek(0) locale_variables = to_dict(created_locale) added, removed, same = dict_compare(en_variables, locale_variables) # perhaps theres a better way to do this # FIXME : output isn't sorted if command == "diff" and (added or removed or same): output += f"[{created_locale.name[15:]}]\n" if added: output += " [Added]\n" for i in added: output += f" {get_line_num(locale_file,i)} | {i} = {en_variables[i].strip()}\n" if removed: output += " [Removed]\n" for i in removed: output += f" {get_line_num(created_locale,i)} | {i} = {locale_variables[i].strip()}\n" if same: output += " [Untranslated]\n" for i in same: output += f" {get_line_num(locale_file,i)} | {i} = {en_variables[i].strip()}\n" output += "\n" continue # on some cycles the code below runs, even if there are differences #else: #print(f"No differences spotted between \"en\" and \"{sys.argv[2]}\" locale") #sys.exit() # for "missing" and "unused" command for i in files: with open(i, "r") as script: # for unused entries for j in list(en_variables.keys()): script.seek(0) if f"\"{j}\"" in script.read(): used_entries[j] = script.name script.seek(0) # forgive me for my programming war crimes, this is 6 indentations!!!!!! # FIXME: it only indexes the first match for line in script.read().split("\n"): if ("tr(\"" in line) and ("#" not in line): index = line.find('tr!("') indexLast = line.find('")',index) var_name = re.sub('[^\\w-]+', '', line[index:indexLast].replace('tr!("', '').replace("Some", "")) script_entries[var_name] = [script.name, get_line_num(script, var_name)] ## results stage ## if command == "unused": printed = [] for i in all_entries: if i not in used_entries: unused_entries[i] = all_entries[i] for i in unused_entries: if all_entries[i][0] not in printed: printed.append(all_entries[i][0]) output += f"[en/{all_entries[i][0]}]\n [Unused]\n" output += f" {all_entries[i][1]} | {i} = {every_variable[i].strip()}\n" output = re.sub("\\[en", "\n[en", output) if not output: print("Nothing is unused") sys.exit() # The way "unused" and "missing" process the data is very similar, perhaps it will be possible to do this in a function instead? elif command == "missing": printed = [] for i in script_entries: if i not in all_entries: missing_entries[i] = script_entries[i][0] for i in missing_entries: if script_entries[i][0] not in printed: printed.append(script_entries[i][0]) output += f"[{missing_entries[i]}]\n [Missing]\n" output += f" {script_entries[i][1]} | {i}\n" output = re.sub("\\[src/", "\n[src/", output) if not output: print("Nothing is missing") sys.exit() pydoc.pager(output)