mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	Add: check for duplicate keys (#2749)
# Description of Changes introduces the check for duplicate keys --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
		
							parent
							
								
									af1b156ba6
								
							
						
					
					
						commit
						8353c399d2
					
				
							
								
								
									
										78
									
								
								.github/scripts/check_language_properties.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										78
									
								
								.github/scripts/check_language_properties.py
									
									
									
									
										vendored
									
									
								
							@ -21,25 +21,60 @@ import argparse
 | 
				
			|||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def find_duplicate_keys(file_path):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Identifies duplicate keys in a .properties file.
 | 
				
			||||||
 | 
					    :param file_path: Path to the .properties file.
 | 
				
			||||||
 | 
					    :return: List of tuples (key, first_occurrence_line, duplicate_line).
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    keys = {}
 | 
				
			||||||
 | 
					    duplicates = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(file_path, "r", encoding="utf-8") as file:
 | 
				
			||||||
 | 
					        for line_number, line in enumerate(file, start=1):
 | 
				
			||||||
 | 
					            stripped_line = line.strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Skip empty lines and comments
 | 
				
			||||||
 | 
					            if not stripped_line or stripped_line.startswith("#"):
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Split the line into key and value
 | 
				
			||||||
 | 
					            if "=" in stripped_line:
 | 
				
			||||||
 | 
					                key, _ = stripped_line.split("=", 1)
 | 
				
			||||||
 | 
					                key = key.strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # Check if the key already exists
 | 
				
			||||||
 | 
					                if key in keys:
 | 
				
			||||||
 | 
					                    duplicates.append((key, keys[key], line_number))
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    keys[key] = line_number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return duplicates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Maximum size for properties files (e.g., 200 KB)
 | 
					# Maximum size for properties files (e.g., 200 KB)
 | 
				
			||||||
MAX_FILE_SIZE = 200 * 1024
 | 
					MAX_FILE_SIZE = 200 * 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def parse_properties_file(file_path):
 | 
					def parse_properties_file(file_path):
 | 
				
			||||||
    """Parses a .properties file and returns a list of objects (including comments, empty lines, and line numbers)."""
 | 
					    """
 | 
				
			||||||
 | 
					    Parses a .properties file and returns a structured list of its contents.
 | 
				
			||||||
 | 
					    :param file_path: Path to the .properties file.
 | 
				
			||||||
 | 
					    :return: List of dictionaries representing each line in the file.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    properties_list = []
 | 
					    properties_list = []
 | 
				
			||||||
    with open(file_path, "r", encoding="utf-8") as file:
 | 
					    with open(file_path, "r", encoding="utf-8") as file:
 | 
				
			||||||
        for line_number, line in enumerate(file, start=1):
 | 
					        for line_number, line in enumerate(file, start=1):
 | 
				
			||||||
            stripped_line = line.strip()
 | 
					            stripped_line = line.strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Empty lines
 | 
					            # Handle empty lines
 | 
				
			||||||
            if not stripped_line:
 | 
					            if not stripped_line:
 | 
				
			||||||
                properties_list.append(
 | 
					                properties_list.append(
 | 
				
			||||||
                    {"line_number": line_number, "type": "empty", "content": ""}
 | 
					                    {"line_number": line_number, "type": "empty", "content": ""}
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Comments
 | 
					            # Handle comments
 | 
				
			||||||
            if stripped_line.startswith("#"):
 | 
					            if stripped_line.startswith("#"):
 | 
				
			||||||
                properties_list.append(
 | 
					                properties_list.append(
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -50,7 +85,7 @@ def parse_properties_file(file_path):
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Key-value pairs
 | 
					            # Handle key-value pairs
 | 
				
			||||||
            match = re.match(r"^([^=]+)=(.*)$", line)
 | 
					            match = re.match(r"^([^=]+)=(.*)$", line)
 | 
				
			||||||
            if match:
 | 
					            if match:
 | 
				
			||||||
                key, value = match.groups()
 | 
					                key, value = match.groups()
 | 
				
			||||||
@ -67,9 +102,14 @@ def parse_properties_file(file_path):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def write_json_file(file_path, updated_properties):
 | 
					def write_json_file(file_path, updated_properties):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Writes updated properties back to the file in their original format.
 | 
				
			||||||
 | 
					    :param file_path: Path to the .properties file.
 | 
				
			||||||
 | 
					    :param updated_properties: List of updated properties to write.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    updated_lines = {entry["line_number"]: entry for entry in updated_properties}
 | 
					    updated_lines = {entry["line_number"]: entry for entry in updated_properties}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Sort by line numbers and retain comments and empty lines
 | 
					    # Sort lines by their numbers and retain comments and empty lines
 | 
				
			||||||
    all_lines = sorted(set(updated_lines.keys()))
 | 
					    all_lines = sorted(set(updated_lines.keys()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    original_format = []
 | 
					    original_format = []
 | 
				
			||||||
@ -88,8 +128,8 @@ def write_json_file(file_path, updated_properties):
 | 
				
			|||||||
            # Replace entries with those from the current JSON
 | 
					            # Replace entries with those from the current JSON
 | 
				
			||||||
            original_format.append(entry)
 | 
					            original_format.append(entry)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Write back in the original format
 | 
					    # Write the updated content back to the file
 | 
				
			||||||
    with open(file_path, "w", encoding="utf-8") as file:
 | 
					    with open(file_path, "w", encoding="utf-8", newline="\n") as file:
 | 
				
			||||||
        for entry in original_format:
 | 
					        for entry in original_format:
 | 
				
			||||||
            if entry["type"] == "comment":
 | 
					            if entry["type"] == "comment":
 | 
				
			||||||
                file.write(f"{entry['content']}\n")
 | 
					                file.write(f"{entry['content']}\n")
 | 
				
			||||||
@ -100,6 +140,12 @@ def write_json_file(file_path, updated_properties):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def update_missing_keys(reference_file, file_list, branch=""):
 | 
					def update_missing_keys(reference_file, file_list, branch=""):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Updates missing keys in the translation files based on the reference file.
 | 
				
			||||||
 | 
					    :param reference_file: Path to the reference .properties file.
 | 
				
			||||||
 | 
					    :param file_list: List of translation files to update.
 | 
				
			||||||
 | 
					    :param branch: Branch where the files are located.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    reference_properties = parse_properties_file(reference_file)
 | 
					    reference_properties = parse_properties_file(reference_file)
 | 
				
			||||||
    for file_path in file_list:
 | 
					    for file_path in file_list:
 | 
				
			||||||
        basename_current_file = os.path.basename(os.path.join(branch, file_path))
 | 
					        basename_current_file = os.path.basename(os.path.join(branch, file_path))
 | 
				
			||||||
@ -245,6 +291,24 @@ def check_for_differences(reference_file, file_list, branch, actor):
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            report.append("2. **Test Status:** ✅ **_Passed_**")
 | 
					            report.append("2. **Test Status:** ✅ **_Passed_**")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if find_duplicate_keys(os.path.join(branch, file_path)):
 | 
				
			||||||
 | 
					            has_differences = True
 | 
				
			||||||
 | 
					            output = "\n".join(
 | 
				
			||||||
 | 
					                [
 | 
				
			||||||
 | 
					                    f"      - `{key}`: first at line {first}, duplicate at `line {duplicate}`"
 | 
				
			||||||
 | 
					                    for key, first, duplicate in find_duplicate_keys(
 | 
				
			||||||
 | 
					                        os.path.join(branch, file_path)
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            report.append("3. **Test Status:** ❌ **_Failed_**")
 | 
				
			||||||
 | 
					            report.append("  - **Issue:**")
 | 
				
			||||||
 | 
					            report.append("    - duplicate entries were found:")
 | 
				
			||||||
 | 
					            report.append(output)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            report.append("3. **Test Status:** ✅ **_Passed_**")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        report.append("")
 | 
					        report.append("")
 | 
				
			||||||
        report.append("---")
 | 
					        report.append("---")
 | 
				
			||||||
        report.append("")
 | 
					        report.append("")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user