Update Kapitanbooru Uploader to version 0.9.0 with significant changes
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Gitea/kapitanbooru-uploader/pipeline/head This commit looks good
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Gitea/kapitanbooru-uploader/pipeline/head This commit looks good
				
			- Updated version number in pyproject.toml and messages.po files. - Added new translations and updated existing ones in messages.po for better localization. - Implemented core functionality in Core.py, including image processing, tagging, and upload logic. - Enhanced the autotagging feature to support multiple image formats (PNG, JPEG, WebP, AVIF, GIF). - Improved error handling and logging for file operations and network requests. - Added functionality to check for uploaded files and manage tag updates for existing posts. - Introduced threading for background processing to improve application responsiveness.
This commit is contained in:
		
							
								
								
									
										744
									
								
								kapitanbooru_uploader/Core.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										744
									
								
								kapitanbooru_uploader/Core.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,744 @@ | |||||||
|  | import glob | ||||||
|  | import hashlib | ||||||
|  | import os | ||||||
|  | import threading | ||||||
|  | from typing import Any, Callable, Tuple | ||||||
|  | import concurrent.futures | ||||||
|  | from packaging.version import parse as parse_version | ||||||
|  | import queue | ||||||
|  | import time | ||||||
|  |  | ||||||
|  | import networkx as nx | ||||||
|  | import requests | ||||||
|  | from PIL import Image | ||||||
|  | import wdtagger as wdt | ||||||
|  |  | ||||||
|  | from .I18N import _ | ||||||
|  | from .TagsRepo import TagsRepo | ||||||
|  | from .settings import Settings | ||||||
|  | from .common import login, get_auth_token | ||||||
|  | from .ProgressFile import ProgressFile | ||||||
|  | from .tag_processing import ( | ||||||
|  |     TAG_FIXES, | ||||||
|  |     extract_parameters, | ||||||
|  |     parse_parameters, | ||||||
|  |     process_tag, | ||||||
|  |     extract_artist_from_filename, | ||||||
|  | ) | ||||||
|  | from .tagger_cache import TaggerCache | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Core: | ||||||
|  |     """ | ||||||
|  |     Core functionality for Kapitanbooru Uploader. | ||||||
|  |     Handles image processing, tagging, and upload logic. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     def __init__(self, settings: Settings, gui_mode: bool = True): | ||||||
|  |         self.version = "0.9.0" | ||||||
|  |         self.acknowledged_version = parse_version(self.version) | ||||||
|  |         self.settings = settings | ||||||
|  |         self.tags_repo = TagsRepo(settings) | ||||||
|  |         # Dodatkowe ustawienia dla Taggera | ||||||
|  |         self.tagger_name = "wdtagger" | ||||||
|  |         self.tagger_version = ( | ||||||
|  |             "1.0"  # możesz ustawić wersję dynamicznie, jeśli to możliwe | ||||||
|  |         ) | ||||||
|  |         self.tagger_cache = TaggerCache( | ||||||
|  |             self.settings, self.tagger_name, self.tagger_version | ||||||
|  |         ) | ||||||
|  |         self.gui_mode = gui_mode | ||||||
|  |         self.main_thread_queue = queue.Queue() | ||||||
|  |         self.after_events = [] | ||||||
|  |  | ||||||
|  |         self.implication_graph = self.load_implication_graph() | ||||||
|  |         self.missing_tags = set()  # Track tags not in the graph | ||||||
|  |  | ||||||
|  |         self.check_uploaded_files_stop_event = threading.Event() | ||||||
|  |         self.check_uploaded_files_thread: threading.Thread | None = None | ||||||
|  |         self.process_tagger_queue_stop_event = threading.Event() | ||||||
|  |         self.process_tagger_queue_thread: threading.Thread | None = None | ||||||
|  |  | ||||||
|  |         self.check_uploaded_files_callback = None | ||||||
|  |         self.update_status_bar_callback = None | ||||||
|  |         self.process_tagger_for_image_callback = None | ||||||
|  |         self.upload_file_success_callback: Callable[[str], Any] | None = None | ||||||
|  |         self.upload_file_completed_callback: Callable | None = None | ||||||
|  |  | ||||||
|  |         self.folder_path = "" | ||||||
|  |         self.image_files = [] | ||||||
|  |         self.image_files_md5 = [] | ||||||
|  |         self.current_index = None | ||||||
|  |         self.image_cache = None | ||||||
|  |         self.tagger_thread_idx = 0 | ||||||
|  |         self.tagger = wdt.Tagger() | ||||||
|  |  | ||||||
|  |         # Liczniki statusu | ||||||
|  |         self.total_files = 0 | ||||||
|  |         self.tagger_processed = set() | ||||||
|  |         self.upload_verified = 0 | ||||||
|  |         self.uploaded_count = 0 | ||||||
|  |  | ||||||
|  |         # Oryginalny obraz (do skalowania) | ||||||
|  |         self.current_image_original = None | ||||||
|  |         self.current_parameters = "" | ||||||
|  |  | ||||||
|  |         # Mapa ratingów: wyświetlana nazwa -> wartość wysyłana | ||||||
|  |         self.rating_map = { | ||||||
|  |             "General": "g", | ||||||
|  |             "Sensitive": "s", | ||||||
|  |             "Questionable": "q", | ||||||
|  |             "Explicit": "e", | ||||||
|  |             "Unrated": "", | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         # Słowniki przechowujące stany tagów (dla PNG i Taggera) | ||||||
|  |         self.png_tags_states = {} | ||||||
|  |         self.tagger_tags_states = {} | ||||||
|  |  | ||||||
|  |         # Nowy słownik przechowujący informację, czy dany plik (ścieżka) został już uploadowany | ||||||
|  |         self.uploaded = {}  # key: file path, value: True/False | ||||||
|  |  | ||||||
|  |     def schedule_in_main_thread(self, func, delay_ms=0): | ||||||
|  |         """Schedule a function to run in the main thread""" | ||||||
|  |         if self.gui_mode: | ||||||
|  |             # In GUI mode, use the after mechanism | ||||||
|  |             self.after_events.append((time.time() + delay_ms / 1000, func)) | ||||||
|  |         else: | ||||||
|  |             # In non-GUI mode, add to queue for immediate execution | ||||||
|  |             self.main_thread_queue.put(func) | ||||||
|  |  | ||||||
|  |     def process_main_thread_queue(self): | ||||||
|  |         """Process pending main thread tasks""" | ||||||
|  |         if self.gui_mode: | ||||||
|  |             # Process scheduled events | ||||||
|  |             now = time.time() | ||||||
|  |             new_events = [] | ||||||
|  |             for schedule_time, func in self.after_events: | ||||||
|  |                 if now >= schedule_time: | ||||||
|  |                     try: | ||||||
|  |                         func() | ||||||
|  |                     except Exception as e: | ||||||
|  |                         print(f"Error in scheduled task: {e}") | ||||||
|  |                 else: | ||||||
|  |                     new_events.append((schedule_time, func)) | ||||||
|  |             self.after_events = new_events | ||||||
|  |         else: | ||||||
|  |             # Process all queued tasks in non-GUI mode | ||||||
|  |             while not self.main_thread_queue.empty(): | ||||||
|  |                 try: | ||||||
|  |                     func = self.main_thread_queue.get_nowait() | ||||||
|  |                     func() | ||||||
|  |                 except queue.Empty: | ||||||
|  |                     break | ||||||
|  |                 except Exception as e: | ||||||
|  |                     print(f"Error in main thread task: {e}") | ||||||
|  |  | ||||||
|  |     def load_implication_graph(self) -> nx.DiGraph: | ||||||
|  |         G = nx.DiGraph() | ||||||
|  |         conn = self.tags_repo.get_conn() | ||||||
|  |         cursor = conn.cursor() | ||||||
|  |  | ||||||
|  |         # Step 1: Add all tags from the 'tags' table | ||||||
|  |         cursor.execute( | ||||||
|  |             """ | ||||||
|  |             SELECT | ||||||
|  |             CASE category | ||||||
|  |             WHEN 1 THEN 'artist:' || name | ||||||
|  |             WHEN 3 THEN 'copyright:' || name | ||||||
|  |             WHEN 4 THEN 'character:' || name | ||||||
|  |             WHEN 5 THEN 'meta:' || name | ||||||
|  |             ELSE name | ||||||
|  |             END AS prefixed_name | ||||||
|  |             FROM tags | ||||||
|  |             """ | ||||||
|  |         ) | ||||||
|  |         db_tags = {row[0] for row in cursor.fetchall()} | ||||||
|  |         G.add_nodes_from(db_tags) | ||||||
|  |  | ||||||
|  |         # Step 2: Add nodes from implications (antecedents/consequents not in 'tags' table) | ||||||
|  |         cursor.execute("SELECT antecedent, consequent FROM tag_closure") | ||||||
|  |         edge_tags = set() | ||||||
|  |         for ant, cons in cursor.fetchall(): | ||||||
|  |             edge_tags.add(ant) | ||||||
|  |             edge_tags.add(cons) | ||||||
|  |         G.add_nodes_from(edge_tags - db_tags)  # Add tags only in implications | ||||||
|  |  | ||||||
|  |         # Step 3: Add edges | ||||||
|  |         cursor.execute("SELECT antecedent, consequent FROM tag_closure") | ||||||
|  |         G.add_edges_from(cursor.fetchall()) | ||||||
|  |  | ||||||
|  |         conn.close() | ||||||
|  |         return G | ||||||
|  |  | ||||||
|  |     def compute_final_tags_and_rating_for_file( | ||||||
|  |         self, file_path, update_status_callback, manual_tags=set() | ||||||
|  |     ) -> Tuple[str, str]: | ||||||
|  |         """ | ||||||
|  |         Oblicza finalną listę tagów dla danego pliku oraz rating. | ||||||
|  |         Łączy tagi z: | ||||||
|  |         - pliku (PNG): parsowane przez parse_parameters, | ||||||
|  |         - Taggera (wynik z cache lub wyliczony na bieżąco), | ||||||
|  |         - ustawień (default tags), | ||||||
|  |         - manualnych tagów (z pola manual_tags_entry), | ||||||
|  |         oraz dodaje tag "meta:auto_upload". | ||||||
|  |         Zwraca finalny ciąg tagów oraz rating. | ||||||
|  |         """ | ||||||
|  |         # Pobierz tagi z pliku | ||||||
|  |         try: | ||||||
|  |             img = Image.open(file_path) | ||||||
|  |             parameters = extract_parameters(img, file_path) | ||||||
|  |             artist_tag = extract_artist_from_filename(file_path) | ||||||
|  |             png_tags = set( | ||||||
|  |                 [ | ||||||
|  |                     x | ||||||
|  |                     for x in parse_parameters(parameters, self.tags_repo).split() | ||||||
|  |                     if process_tag(x, self.tags_repo)[1] | ||||||
|  |                     is not None  # Ignoruj nieistniejące tagi | ||||||
|  |                 ] | ||||||
|  |             ) | ||||||
|  |             if artist_tag: | ||||||
|  |                 png_tags.add("artist:" + artist_tag.replace(" ", "_").replace("\\", "")) | ||||||
|  |             img.close() | ||||||
|  |         except Exception as e: | ||||||
|  |             print(_("Błąd przy otwieraniu pliku"), file_path, ":", e) | ||||||
|  |             png_tags = set() | ||||||
|  |  | ||||||
|  |         # Pobierz tagi z Taggera – sprawdzając cache | ||||||
|  |         result = self.get_tagger_results(file_path, update_status_callback) | ||||||
|  |         tagger_tags = set() | ||||||
|  |         rating = "Unrated" | ||||||
|  |         tagger_tags.update( | ||||||
|  |             ( | ||||||
|  |                 TAG_FIXES[tag] if tag in TAG_FIXES else tag | ||||||
|  |                 for tag in result.general_tag_data.keys() | ||||||
|  |             ) | ||||||
|  |         )  # Zamień nieprawidłowe tagi na poprawne | ||||||
|  |         for t in result.character_tags: | ||||||
|  |             full_tag = "character:" + t.replace(" ", "_").replace("\\", "") | ||||||
|  |             # Zamień nieprawidłowe tagi na poprawne | ||||||
|  |             if full_tag in TAG_FIXES: | ||||||
|  |                 full_tag = TAG_FIXES[full_tag] | ||||||
|  |             tagger_tags.add(full_tag) | ||||||
|  |         rating = self.map_tagger_rating(result) | ||||||
|  |  | ||||||
|  |         # Pobierz tagi z ustawień i manualne | ||||||
|  |         default_tags = set(self.settings.default_tags.split()) | ||||||
|  |  | ||||||
|  |         # Finalna lista: suma wszystkich tagów | ||||||
|  |         final_tags = default_tags.union(png_tags).union(tagger_tags).union(manual_tags) | ||||||
|  |         final_tags.add("meta:auto_upload") | ||||||
|  |         return " ".join(sorted(final_tags)), rating | ||||||
|  |  | ||||||
|  |     def get_tagger_results(self, file_path, callback) -> wdt.Result: | ||||||
|  |         md5 = self.image_files_md5[file_path] | ||||||
|  |         cached = self.tagger_cache[md5] | ||||||
|  |         if cached: | ||||||
|  |             self.tagger_processed.add(md5) | ||||||
|  |             return cached["result"] | ||||||
|  |         try: | ||||||
|  |             with Image.open(file_path) as img: | ||||||
|  |                 result = self.tagger.tag(img) | ||||||
|  |             self.tagger_cache[md5] = result | ||||||
|  |             self.tagger_processed.add(md5) | ||||||
|  |             callback() | ||||||
|  |             print(_("Tagger przetworzył:"), f"{file_path}") | ||||||
|  |             return result | ||||||
|  |         except Exception as e: | ||||||
|  |             print(_("Błąd Taggera dla"), file_path, ":", e) | ||||||
|  |  | ||||||
|  |     def map_tagger_rating(self, result: wdt.Result) -> str: | ||||||
|  |         """ | ||||||
|  |         Mapuje rating z Taggera na wartość używaną w Kapitanbooru. | ||||||
|  |         """ | ||||||
|  |         if result.rating == "general": | ||||||
|  |             new_rating = "General" | ||||||
|  |         elif result.rating == "sensitive": | ||||||
|  |             new_rating = "Sensitive" | ||||||
|  |         elif result.rating == "questionable": | ||||||
|  |             new_rating = "Questionable" | ||||||
|  |         elif result.rating == "explicit": | ||||||
|  |             new_rating = "Explicit" | ||||||
|  |         else: | ||||||
|  |             new_rating = "Unrated" | ||||||
|  |         return new_rating | ||||||
|  |  | ||||||
|  |     def load_images(self): | ||||||
|  |         """ | ||||||
|  |         Ładuje pliki PNG, JPEG, WebP, AVIF i GIF z wybranego folderu. | ||||||
|  |         """ | ||||||
|  |         extensions = ("*.png", "*.jpg", "*.jpeg", "*.webp", "*.avif", "*.gif") | ||||||
|  |         self.image_files = sorted( | ||||||
|  |             file | ||||||
|  |             for ext in extensions | ||||||
|  |             for file in glob.glob(os.path.join(self.folder_path, ext), recursive=True) | ||||||
|  |         ) | ||||||
|  |         self.total_files = len(self.image_files) | ||||||
|  |         self.image_files_md5 = { | ||||||
|  |             file: md5 | ||||||
|  |             for file, md5 in zip( | ||||||
|  |                 self.image_files, self.compute_md5_parallel(self.image_files) | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |         self.tagger_processed.clear() | ||||||
|  |         for md5 in self.image_files_md5.values(): | ||||||
|  |             if self.tagger_cache[md5]: | ||||||
|  |                 self.tagger_processed.add(md5) | ||||||
|  |         self.uploaded.clear() | ||||||
|  |         self.upload_verified = 0 | ||||||
|  |         self.uploaded_count = 0 | ||||||
|  |         for file in self.image_files: | ||||||
|  |             self.uploaded[file] = False | ||||||
|  |         if self.image_files: | ||||||
|  |             self.post_load_processing() | ||||||
|  |  | ||||||
|  |     def compute_md5(self, file_path, chunk_size=8192): | ||||||
|  |         """Compute MD5 for a single file.""" | ||||||
|  |         hash_md5 = hashlib.md5() | ||||||
|  |         try: | ||||||
|  |             with open(file_path, "rb") as f: | ||||||
|  |                 for chunk in iter(lambda: f.read(chunk_size), b""): | ||||||
|  |                     hash_md5.update(chunk) | ||||||
|  |         except Exception as e: | ||||||
|  |             print(_("Error computing MD5:"), e) | ||||||
|  |             return "" | ||||||
|  |         return hash_md5.hexdigest() | ||||||
|  |  | ||||||
|  |     def compute_md5_parallel(self, file_paths): | ||||||
|  |         """Compute MD5 for multiple files in parallel.""" | ||||||
|  |         with concurrent.futures.ThreadPoolExecutor() as executor: | ||||||
|  |             return list(executor.map(self.compute_md5, file_paths)) | ||||||
|  |  | ||||||
|  |     def post_load_processing(self): | ||||||
|  |         """ | ||||||
|  |         Po załadowaniu plików, sprawdza czy są jakieś pliki do uploadu oraz przetwarza Taggerem pliki. | ||||||
|  |         """ | ||||||
|  |         self.join_check_uploaded_files_thread() | ||||||
|  |         self.check_uploaded_files_thread = threading.Thread( | ||||||
|  |             target=self.check_uploaded_files | ||||||
|  |         ) | ||||||
|  |         self.check_uploaded_files_thread.start() | ||||||
|  |         self.join_process_tagger_queue_thread() | ||||||
|  |         self.process_tagger_queue_thread = threading.Thread( | ||||||
|  |             target=self.process_tagger_queue | ||||||
|  |         ) | ||||||
|  |         self.process_tagger_queue_thread.start() | ||||||
|  |  | ||||||
|  |     def wait_for_completion(self): | ||||||
|  |         """Wait for background threads to finish (non-GUI mode)""" | ||||||
|  |         # Join the checking thread if running | ||||||
|  |         if ( | ||||||
|  |             self.check_uploaded_files_thread | ||||||
|  |             and self.check_uploaded_files_thread.is_alive() | ||||||
|  |         ): | ||||||
|  |             self.check_uploaded_files_stop_event.set() | ||||||
|  |             self.check_uploaded_files_thread.join() | ||||||
|  |  | ||||||
|  |         # Join the tagger processing thread if running | ||||||
|  |         if ( | ||||||
|  |             self.process_tagger_queue_thread | ||||||
|  |             and self.process_tagger_queue_thread.is_alive() | ||||||
|  |         ): | ||||||
|  |             self.process_tagger_queue_stop_event.set() | ||||||
|  |             self.process_tagger_queue_thread.join() | ||||||
|  |  | ||||||
|  |         # Process any remaining main thread tasks | ||||||
|  |         self.process_main_thread_queue() | ||||||
|  |  | ||||||
|  |     def join_check_uploaded_files_thread(self): | ||||||
|  |         if self.check_uploaded_files_thread is not None: | ||||||
|  |             self.check_uploaded_files_stop_event.set() | ||||||
|  |             self.check_uploaded_files_thread.join() | ||||||
|  |             self.check_uploaded_files_thread = None | ||||||
|  |             self.check_uploaded_files_stop_event = threading.Event() | ||||||
|  |  | ||||||
|  |     def join_process_tagger_queue_thread(self): | ||||||
|  |         if self.process_tagger_queue_thread is not None: | ||||||
|  |             self.process_tagger_queue_stop_event.set() | ||||||
|  |             self.process_tagger_queue_thread.join() | ||||||
|  |             self.process_tagger_queue_thread = None | ||||||
|  |             self.process_tagger_queue_stop_event = threading.Event() | ||||||
|  |  | ||||||
|  |     def process_tagger_for_image(self, file_path): | ||||||
|  |         """Przetwarza obrazek przy użyciu Taggera i zapisuje wynik do cache.""" | ||||||
|  |         result = self.get_tagger_results(file_path) | ||||||
|  |         if self.process_tagger_for_image_callback: | ||||||
|  |             self.process_tagger_for_image_callback(file_path, result.rating) | ||||||
|  |  | ||||||
|  |     def process_tagger_queue(self): | ||||||
|  |         """Przetwarza wszystkie obrazki w tle (pomijając aktualnie wybrany).""" | ||||||
|  |         for file_path in self.image_files: | ||||||
|  |             if self.process_tagger_queue_stop_event.is_set(): | ||||||
|  |                 break | ||||||
|  |             # Jeśli obrazek jest aktualnie wybrany, pomijamy – on będzie przetwarzany w foreground | ||||||
|  |             if ( | ||||||
|  |                 self.current_index is not None | ||||||
|  |                 and file_path == self.image_files[self.current_index] | ||||||
|  |             ): | ||||||
|  |                 continue | ||||||
|  |             self.process_tagger_for_image(file_path) | ||||||
|  |         self.schedule_in_main_thread(self.join_process_tagger_queue_thread, 100) | ||||||
|  |  | ||||||
|  |     def check_uploaded_files(self): | ||||||
|  |         """ | ||||||
|  |         Dla każdego obrazu oblicza MD5, grupuje je w paczki (do 100 skrótów), | ||||||
|  |         wysyła zapytanie do endpointa 'posts.json' dla każdej paczki, | ||||||
|  |         a następnie na podstawie odpowiedzi ustawia w self.uploaded post id dla uploadowanych plików. | ||||||
|  |         """ | ||||||
|  |         file_md5_list = [ | ||||||
|  |             (idx, file, self.image_files_md5[file]) | ||||||
|  |             for idx, file in enumerate(self.image_files) | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |         batch_size = 100 | ||||||
|  |         for i in range(0, len(file_md5_list), batch_size): | ||||||
|  |             if self.check_uploaded_files_stop_event.is_set(): | ||||||
|  |                 break | ||||||
|  |             batch = file_md5_list[i : i + batch_size] | ||||||
|  |             batch_md5 = [item[2] for item in batch] | ||||||
|  |             md5_param = ",".join(batch_md5) | ||||||
|  |             url = self.settings.base_url.rstrip("/") + "/posts.json" | ||||||
|  |             try: | ||||||
|  |                 response = requests.get(url, params={"md5": md5_param}) | ||||||
|  |  | ||||||
|  |                 root = response.json() | ||||||
|  |                 found = {} | ||||||
|  |                 for elem in root: | ||||||
|  |                     if self.check_uploaded_files_stop_event.is_set(): | ||||||
|  |                         break | ||||||
|  |                     post_md5 = elem.get("md5", "").lower() | ||||||
|  |                     post_id = elem.get("id") | ||||||
|  |                     if post_md5 and post_id: | ||||||
|  |                         found[post_md5] = post_id | ||||||
|  |                 for idx, file_path, md5 in batch: | ||||||
|  |                     if self.check_uploaded_files_stop_event.is_set(): | ||||||
|  |                         break | ||||||
|  |                     self.upload_verified += 1  # Każdy plik w batchu jest zweryfikowany | ||||||
|  |                     if md5.lower() in found: | ||||||
|  |                         self.uploaded[file_path] = found[md5.lower()] | ||||||
|  |                         self.uploaded_count += 1 | ||||||
|  |                         if self.check_uploaded_files_callback: | ||||||
|  |                             self.check_uploaded_files_callback(idx) | ||||||
|  |                     else: | ||||||
|  |                         self.uploaded[file_path] = False | ||||||
|  |                     if self.update_status_bar_callback: | ||||||
|  |                         self.update_status_bar_callback() | ||||||
|  |  | ||||||
|  |             except Exception as e: | ||||||
|  |                 print(_("Błąd podczas sprawdzania paczki uploadu:"), e) | ||||||
|  |         self.schedule_in_main_thread(self.join_check_uploaded_files_thread, 100) | ||||||
|  |  | ||||||
|  |     def autotag_files(self, file_paths): | ||||||
|  |         """ | ||||||
|  |         Autotaguje pliki przy użyciu Taggera i wysyła je na serwer. | ||||||
|  |         """ | ||||||
|  |         for file_path in file_paths: | ||||||
|  |             if not os.path.isfile(file_path): | ||||||
|  |                 print(_("Plik nie istnieje:"), file_path) | ||||||
|  |                 continue | ||||||
|  |             try: | ||||||
|  |                 tags, rating = self.compute_final_tags_and_rating_for_file( | ||||||
|  |                     file_path, lambda: None | ||||||
|  |                 ) | ||||||
|  |                 print(_("Tagi dla pliku"), file_path, ":", tags, "Rating:", rating) | ||||||
|  |                 self.upload_file( | ||||||
|  |                     file_path, | ||||||
|  |                     final_tags=tags, | ||||||
|  |                     final_rating=rating, | ||||||
|  |                     progress_queue=None, | ||||||
|  |                     cancel_event=None, | ||||||
|  |                 ) | ||||||
|  |             except Exception as e: | ||||||
|  |                 print(_("Błąd podczas autotagowania pliku"), file_path, ":", e) | ||||||
|  |  | ||||||
|  |     def autotag_dir(self, dir): | ||||||
|  |         """ | ||||||
|  |         Autotaguje wszystkie pliki w katalogu przy użyciu Taggera i wysyła je na serwer. | ||||||
|  |         """ | ||||||
|  |         if not os.path.isdir(dir): | ||||||
|  |             print(_("Podana ścieżka nie jest katalogiem:"), dir) | ||||||
|  |             return | ||||||
|  |         self.folder_path = dir | ||||||
|  |         self.load_images() | ||||||
|  |         self.check_uploaded_files_thread.join() | ||||||
|  |         self.process_tagger_queue_thread.join() | ||||||
|  |         files_to_upload = [x for x in self.image_files if not self.uploaded[x]] | ||||||
|  |         if not files_to_upload: | ||||||
|  |             print(_("Brak obrazów do przetworzenia w katalogu:"), dir) | ||||||
|  |             return | ||||||
|  |  | ||||||
|  |         self.autotag_files(files_to_upload) | ||||||
|  |  | ||||||
|  |     def upload_file( | ||||||
|  |         self, | ||||||
|  |         file_path, | ||||||
|  |         final_tags=None, | ||||||
|  |         final_rating=None, | ||||||
|  |         progress_queue: queue.Queue | None = None, | ||||||
|  |         cancel_event: threading.Event | None = None, | ||||||
|  |         info_callback: Callable[[str], Any] | None = None, | ||||||
|  |         warning_callback: Callable[[str], Any] | None = None, | ||||||
|  |         error_callback: Callable[[str], Any] | None = None, | ||||||
|  |     ): | ||||||
|  |         base_file_name = os.path.basename(file_path) | ||||||
|  |         if progress_queue: | ||||||
|  |             progress_queue.put(("mode", "determinate")) | ||||||
|  |             progress_queue.put(("max", 100)) | ||||||
|  |             progress_queue.put( | ||||||
|  |                 ( | ||||||
|  |                     "label", | ||||||
|  |                     _("Wysyłam plik {base_file_name}...").format( | ||||||
|  |                         base_file_name=base_file_name | ||||||
|  |                     ), | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         url = self.settings.base_url.rstrip("/") + "/api/danbooru/add_post" | ||||||
|  |         tags = final_tags | ||||||
|  |         fields = { | ||||||
|  |             "login": self.settings.username, | ||||||
|  |             "password": self.settings.password, | ||||||
|  |             "tags": tags, | ||||||
|  |             "source": "", | ||||||
|  |         } | ||||||
|  |         rating_value = self.rating_map.get(final_rating, "") | ||||||
|  |         if rating_value: | ||||||
|  |             fields["rating"] = rating_value | ||||||
|  |         try: | ||||||
|  |             total_size = os.path.getsize(file_path) | ||||||
|  |  | ||||||
|  |             def progress_callback(bytes_read, total_size): | ||||||
|  |                 if progress_queue: | ||||||
|  |                     percentage = int(bytes_read / total_size * 100) | ||||||
|  |                     progress_queue.put(("progress", percentage)) | ||||||
|  |  | ||||||
|  |             with open(file_path, "rb") as f: | ||||||
|  |                 wrapped_file = ProgressFile( | ||||||
|  |                     f, progress_callback, total_size, cancel_event | ||||||
|  |                 ) | ||||||
|  |                 files = {"file": (base_file_name, wrapped_file, "image/png")} | ||||||
|  |                 response = requests.post(url, data=fields, files=files) | ||||||
|  |             if progress_queue: | ||||||
|  |                 progress_queue.put(("progress", 100)) | ||||||
|  |             show_warn = False | ||||||
|  |             post_url = None | ||||||
|  |             if response.status_code in (200, 201): | ||||||
|  |                 message = _("Wysyłanie zakończone powodzeniem!") | ||||||
|  |                 post_url = response.headers.get("X-Danbooru-Location", None) | ||||||
|  |             elif response.status_code == 409: | ||||||
|  |                 message = _( | ||||||
|  |                     "Wysyłanie zakończone błędem.\nStatus: {status_code}\nTreść: {text}" | ||||||
|  |                 ).format( | ||||||
|  |                     status_code=response.status_code, | ||||||
|  |                     text=response.headers.get("X-Danbooru-Errors", ""), | ||||||
|  |                 ) | ||||||
|  |                 post_url = response.headers.get("X-Danbooru-Location", None) | ||||||
|  |                 show_warn = True | ||||||
|  |             else: | ||||||
|  |                 message = _( | ||||||
|  |                     "Wysyłanie zakończone błędem.\nStatus: {status_code}\nTreść: {text}" | ||||||
|  |                 ).format(status_code=response.status_code, text=response.text) | ||||||
|  |                 show_warn = True | ||||||
|  |             # Aktualizacja wyglądu listy – musimy użyć domyślnych argumentów w lambdzie, aby zachować bieżący indeks | ||||||
|  |             if show_warn: | ||||||
|  |                 if not final_tags: | ||||||
|  |                     if warning_callback: | ||||||
|  |                         warning_callback(message) | ||||||
|  |                     else: | ||||||
|  |                         print("[WARN]", _("Wysyłanie"), message) | ||||||
|  |             else: | ||||||
|  |                 if not final_tags: | ||||||
|  |                     if info_callback: | ||||||
|  |                         info_callback(message) | ||||||
|  |                     else: | ||||||
|  |                         print("[INFO]", _("Wysyłanie"), message) | ||||||
|  |                 if self.upload_file_success_callback: | ||||||
|  |                     self.upload_file_success_callback(file_path) | ||||||
|  |             if post_url: | ||||||
|  |                 post_id = post_url.split("/")[-1] | ||||||
|  |                 self.uploaded[file_path] = post_id | ||||||
|  |                 self.uploaded_count += 1 | ||||||
|  |                 self.after(0, self.update_status_bar) | ||||||
|  |         except Exception as e: | ||||||
|  |             if error_callback: | ||||||
|  |                 error_callback(str(e)) | ||||||
|  |             else: | ||||||
|  |                 print("[ERROR]", _("Błąd wysyłania pliku"), file_path, ":", e) | ||||||
|  |         finally: | ||||||
|  |             if self.upload_file_completed_callback: | ||||||
|  |                 self.upload_file_completed_callback() | ||||||
|  |  | ||||||
|  |     def upload_all_files( | ||||||
|  |         self, | ||||||
|  |         progress_queue: queue.Queue = None, | ||||||
|  |         cancel_event: threading.Event = None, | ||||||
|  |         secondary_progress_queue: queue.Queue = None, | ||||||
|  |         update_status_callback=None, | ||||||
|  |         manual_tags: set = set(), | ||||||
|  |         info_callback: Callable[[str], Any] | None = None, | ||||||
|  |         warning_callback: Callable[[str], Any] | None = None, | ||||||
|  |         error_callback: Callable[[str], Any] | None = None, | ||||||
|  |     ): | ||||||
|  |         files_to_upload = [x for x in self.image_files if not self.uploaded[x]] | ||||||
|  |         files_count = len(files_to_upload) | ||||||
|  |         if progress_queue: | ||||||
|  |             progress_queue.put(("mode", "determinate")) | ||||||
|  |             progress_queue.put(("max", 100)) | ||||||
|  |         file_idx = 0 | ||||||
|  |         for file_path in files_to_upload: | ||||||
|  |             if progress_queue: | ||||||
|  |                 progress_queue.put(("progress", file_idx * 100 / files_count)) | ||||||
|  |                 progress_queue.put( | ||||||
|  |                     ("label", f"Wysyłam plik {file_idx+1}/{files_count}...") | ||||||
|  |                 ) | ||||||
|  |             if cancel_event is not None and cancel_event.is_set(): | ||||||
|  |                 if progress_queue: | ||||||
|  |                     progress_queue.put(("label", _("Anulowano operację!"))) | ||||||
|  |                 return | ||||||
|  |             if not self.uploaded.get(file_path, False): | ||||||
|  |                 final_tags, final_rating = self.compute_final_tags_and_rating_for_file( | ||||||
|  |                     file_path, | ||||||
|  |                     update_status_callback,  # lambda: self.after(0, self.update_status_bar) | ||||||
|  |                     manual_tags,  # set(self.manual_tags_manager.manual_tags) | ||||||
|  |                 ) | ||||||
|  |                 print( | ||||||
|  |                     _( | ||||||
|  |                         "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" | ||||||
|  |                     ).format( | ||||||
|  |                         file_path=file_path, | ||||||
|  |                         final_tags=final_tags, | ||||||
|  |                         final_rating=final_rating, | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |                 self.upload_file( | ||||||
|  |                     file_path, | ||||||
|  |                     final_tags=final_tags, | ||||||
|  |                     final_rating=final_rating, | ||||||
|  |                     progress_queue=secondary_progress_queue, | ||||||
|  |                     cancel_event=cancel_event, | ||||||
|  |                     info_callback=info_callback, | ||||||
|  |                     warning_callback=warning_callback, | ||||||
|  |                     error_callback=error_callback, | ||||||
|  |                 ) | ||||||
|  |             file_idx += 1 | ||||||
|  |         if progress_queue: | ||||||
|  |             progress_queue.put(("label", _("Przesłano pliki!"))) | ||||||
|  |             progress_queue.put(("progress", 100)) | ||||||
|  |  | ||||||
|  |     def edit_file( | ||||||
|  |         self, | ||||||
|  |         file_path, | ||||||
|  |         final_tags=None, | ||||||
|  |         final_rating=None, | ||||||
|  |         progress_queue=None, | ||||||
|  |         cancel_event=None, | ||||||
|  |         info_callback: Callable[[str], Any] | None = None, | ||||||
|  |         error_callback: Callable[[str], Any] | None = None, | ||||||
|  |     ): | ||||||
|  |         """ | ||||||
|  |         Update tags and rating for an existing post without uploading the file. | ||||||
|  |         """ | ||||||
|  |         base_file_name = os.path.basename(file_path) | ||||||
|  |         post_id = self.uploaded.get(file_path) | ||||||
|  |  | ||||||
|  |         if not post_id: | ||||||
|  |             if error_callback: | ||||||
|  |                 error_callback(_("Post nie został znaleziony dla tego pliku")) | ||||||
|  |             else: | ||||||
|  |                 print( | ||||||
|  |                     "[ERROR]", | ||||||
|  |                     _("Post nie został znaleziony dla tego pliku"), | ||||||
|  |                     file_path, | ||||||
|  |                 ) | ||||||
|  |             return | ||||||
|  |  | ||||||
|  |         if progress_queue: | ||||||
|  |             progress_queue.put(("mode", "determinate")) | ||||||
|  |             progress_queue.put(("max", 100)) | ||||||
|  |             progress_queue.put( | ||||||
|  |                 ( | ||||||
|  |                     "label", | ||||||
|  |                     _("Aktualizuję tagi dla {base_file_name}...").format( | ||||||
|  |                         base_file_name=base_file_name | ||||||
|  |                     ), | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             # Check for cancellation before starting the operation. | ||||||
|  |             if cancel_event is not None and cancel_event.is_set(): | ||||||
|  |                 if progress_queue: | ||||||
|  |                     progress_queue.put(("label", _("Operacja anulowana"))) | ||||||
|  |                 return | ||||||
|  |  | ||||||
|  |             # Get authentication session and token | ||||||
|  |             session = login(self.settings) | ||||||
|  |             auth_token = get_auth_token(session, self.settings) | ||||||
|  |  | ||||||
|  |             # Check cancellation after login if needed. | ||||||
|  |             if cancel_event is not None and cancel_event.is_set(): | ||||||
|  |                 if progress_queue: | ||||||
|  |                     progress_queue.put(("label", _("Operacja anulowana"))) | ||||||
|  |                 return | ||||||
|  |  | ||||||
|  |             # Prepare tags and rating | ||||||
|  |             tags = final_tags | ||||||
|  |             rating_value = self.rating_map.get(final_rating, "?") | ||||||
|  |  | ||||||
|  |             # Prepare API request | ||||||
|  |             url = self.settings.base_url.rstrip("/") + "/post/set" | ||||||
|  |             payload = { | ||||||
|  |                 "auth_token": auth_token, | ||||||
|  |                 "image_id": post_id, | ||||||
|  |                 "title": base_file_name, | ||||||
|  |                 "owner": self.settings.username, | ||||||
|  |                 "tags": tags, | ||||||
|  |                 "source": "", | ||||||
|  |                 "rating": rating_value, | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if progress_queue: | ||||||
|  |                 progress_queue.put(("progress", 50)) | ||||||
|  |  | ||||||
|  |             # Check for cancellation before sending the update request. | ||||||
|  |             if cancel_event is not None and cancel_event.is_set(): | ||||||
|  |                 if progress_queue: | ||||||
|  |                     progress_queue.put(("label", _("Operacja anulowana"))) | ||||||
|  |                 return | ||||||
|  |  | ||||||
|  |             # Send update request | ||||||
|  |             response = session.post(url, data=payload, allow_redirects=False) | ||||||
|  |  | ||||||
|  |             # Handle 302 redirect as success case | ||||||
|  |             if response.status_code == 302: | ||||||
|  |                 if progress_queue: | ||||||
|  |                     progress_queue.put(("progress", 100)) | ||||||
|  |                 message = _("Tagi zostały zaktualizowane!") | ||||||
|  |                 if not final_tags:  # Only show success if not bulk operation | ||||||
|  |                     if info_callback: | ||||||
|  |                         info_callback(message) | ||||||
|  |                     else: | ||||||
|  |                         print("[INFO]", _("Sukces edycji"), message) | ||||||
|  |                 # Update UI state | ||||||
|  |                 if self.upload_file_completed_callback: | ||||||
|  |                     self.upload_file_completed_callback() | ||||||
|  |                 return | ||||||
|  |  | ||||||
|  |             # Handle other status codes | ||||||
|  |             error_msg = _("Błąd podczas aktualizacji tagów\nStatus: {code}").format( | ||||||
|  |                 code=response.status_code | ||||||
|  |             ) | ||||||
|  |             if response.text: | ||||||
|  |                 error_msg += f"\n{_('Treść:')} {response.text}" | ||||||
|  |             if error_callback: | ||||||
|  |                 error_callback(error_msg) | ||||||
|  |             else: | ||||||
|  |                 print("[ERROR]", _("Błąd edycji"), error_msg) | ||||||
|  |  | ||||||
|  |         except Exception as e: | ||||||
|  |             if error_callback: | ||||||
|  |                 error_callback(str(e)) | ||||||
|  |             else: | ||||||
|  |                 print("[ERROR]", _("Krytyczny błąd edycji"), file_path, ":", e) | ||||||
|  |         finally: | ||||||
|  |             if progress_queue: | ||||||
|  |                 progress_queue.put(("progress", 100)) | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,11 +1,43 @@ | |||||||
| """kapitanbooru_uploader.__main__: executed | """kapitanbooru_uploader.__main__: executed | ||||||
| when kapitanbooru_uploader directory is called as script.""" | when kapitanbooru_uploader directory is called as script.""" | ||||||
|  |  | ||||||
|  | from .Core import Core | ||||||
|  | from .settings import Settings | ||||||
| from .ImageBrowser import ImageBrowser | from .ImageBrowser import ImageBrowser | ||||||
|  | import argparse | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(): | def main(): | ||||||
|     app = ImageBrowser() |     parser = argparse.ArgumentParser( | ||||||
|     app.mainloop() |         prog="kapitanbooru-uploader", description="KapitanBooru Uploader" | ||||||
|  |     ) | ||||||
|  |     group = parser.add_mutually_exclusive_group() | ||||||
|  |  | ||||||
|  |     # Add arguments to the group | ||||||
|  |     group.add_argument( | ||||||
|  |         "--autotag-files", | ||||||
|  |         nargs="+", | ||||||
|  |         metavar="PATH", | ||||||
|  |         help="Specify one or more files to process", | ||||||
|  |     ) | ||||||
|  |     group.add_argument( | ||||||
|  |         "--autotag-dir", metavar="PATH", help="Specify a directory to process" | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     args = parser.parse_args() | ||||||
|  |  | ||||||
|  |     # Determine which function to call | ||||||
|  |     if args.autotag_files: | ||||||
|  |         core = Core(Settings(), gui_mode=False) | ||||||
|  |         core.autotag_files(args.autotag_files) | ||||||
|  |         core.wait_for_completion()  # Wait for threads to finish | ||||||
|  |     elif args.autotag_dir: | ||||||
|  |         core = Core(Settings(), gui_mode=False) | ||||||
|  |         core.autotag_dir(args.autotag_dir) | ||||||
|  |         core.wait_for_completion()  # Wait for threads to finish | ||||||
|  |     else: | ||||||
|  |         app = ImageBrowser() | ||||||
|  |         app.mainloop() | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: Kapitanbooru Uploader 0.8.3\n" | "Project-Id-Version: Kapitanbooru Uploader 0.9.0\n" | ||||||
| "Report-Msgid-Bugs-To: kapitan@mlesniak.pl\n" | "Report-Msgid-Bugs-To: kapitan@mlesniak.pl\n" | ||||||
| "POT-Creation-Date: 2025-06-25 23:49+0200\n" | "POT-Creation-Date: 2025-06-26 17:07+0200\n" | ||||||
| "Content-Type: text/plain; charset=UTF-8\n" | "Content-Type: text/plain; charset=UTF-8\n" | ||||||
| "Content-Transfer-Encoding: 8bit\n" | "Content-Transfer-Encoding: 8bit\n" | ||||||
|  |  | ||||||
| @@ -43,273 +43,56 @@ msgstr "Found auth_token:" | |||||||
| msgid "auth_token not found in the HTML page." | msgid "auth_token not found in the HTML page." | ||||||
| msgstr "auth_token not found in the HTML page." | msgstr "auth_token not found in the HTML page." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:138 | #: Core.py:204 | ||||||
| #, python-brace-format |  | ||||||
| msgid "Update check failed: {error}" |  | ||||||
| msgstr "Update check failed: {error}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:140 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "Malformed pyproject.toml: {error}" |  | ||||||
| msgstr "Malformed pyproject.toml: {error}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:143 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "Unexpected error during update check: {error}" |  | ||||||
| msgstr "Unexpected error during update check: {error}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:150 |  | ||||||
| msgid "Update Available" |  | ||||||
| msgstr "Update Available" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:152 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "" |  | ||||||
| "A new version {new_version} is available!\n" |  | ||||||
| "You have version {current_version}.\n" |  | ||||||
| "\n" |  | ||||||
| "Update using: {update_command}" |  | ||||||
| msgstr "" |  | ||||||
| "A new version {new_version} is available!\n" |  | ||||||
| "You have version {current_version}.\n" |  | ||||||
| "\n" |  | ||||||
| "Update using: {update_command}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:266 |  | ||||||
| msgid "Błąd przy otwieraniu pliku" | msgid "Błąd przy otwieraniu pliku" | ||||||
| msgstr "Error opening file" | msgstr "Error opening file" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:308 | #: Core.py:245 | ||||||
| msgid "Tagger przetworzył:" | msgid "Tagger przetworzył:" | ||||||
| msgstr "Tagger processed:" | msgstr "Tagger processed:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:311 | #: Core.py:248 | ||||||
| msgid "Błąd Taggera dla" | msgid "Błąd Taggera dla" | ||||||
| msgstr "Tagger error for" | msgstr "Tagger error for" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:337 | #: Core.py:303 | ||||||
| msgid "Otwórz folder" |  | ||||||
| msgstr "Open folder" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:340 ImageBrowser.py:629 ImageBrowser.py:856 |  | ||||||
| #: ImageBrowser.py:864 |  | ||||||
| msgid "Wyślij" |  | ||||||
| msgstr "Send" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:343 ImageBrowser.py:849 |  | ||||||
| msgid "Wyślij wszystko" |  | ||||||
| msgstr "Send all" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:347 ImageBrowser.py:850 ImageBrowser.py:856 |  | ||||||
| msgid "Podmień tagi" |  | ||||||
| msgstr "Replace tags" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:350 ImageBrowser.py:851 |  | ||||||
| msgid "Otwórz post" |  | ||||||
| msgstr "Open post" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:353 |  | ||||||
| msgid "Zakończ" |  | ||||||
| msgstr "Finish" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:355 |  | ||||||
| msgid "Plik" |  | ||||||
| msgstr "File" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:359 ImageBrowser.py:458 |  | ||||||
| msgid "Ustawienia" |  | ||||||
| msgstr "Settings" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:362 |  | ||||||
| msgid "Wyczyść cache Taggera" |  | ||||||
| msgstr "Clear Tagger cache" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:365 |  | ||||||
| msgid "Zregeneruj bazę tagów" |  | ||||||
| msgstr "Regenerate tag database" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:367 |  | ||||||
| msgid "Opcje" |  | ||||||
| msgstr "Options" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:370 |  | ||||||
| msgid "About" |  | ||||||
| msgstr "About" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:371 |  | ||||||
| msgid "Help" |  | ||||||
| msgstr "Help" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:376 |  | ||||||
| msgid "About Kapitanbooru Uploader" |  | ||||||
| msgstr "About Kapitanbooru Uploader" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:393 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "A new version {new_version} is available!" |  | ||||||
| msgstr "A new version {new_version} is available!" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:400 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "Current version: {version}" |  | ||||||
| msgstr "Current version: {version}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:402 |  | ||||||
| msgid "A GUI application for uploading images to KapitanBooru." |  | ||||||
| msgstr "A GUI application for uploading images to KapitanBooru." |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:403 |  | ||||||
| msgid "Features include image upload, tag management, automatic" |  | ||||||
| msgstr "Features include image upload, tag management, automatic" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:404 |  | ||||||
| msgid "tagging with wdtagger, and cache management." |  | ||||||
| msgstr "tagging with wdtagger, and cache management." |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:406 |  | ||||||
| msgid "Authors:" |  | ||||||
| msgstr "Authors:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:409 |  | ||||||
| msgid "License: MIT License" |  | ||||||
| msgstr "License: MIT License" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:422 |  | ||||||
| msgid "Repository:" |  | ||||||
| msgstr "Repository:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:431 |  | ||||||
| msgid "Website:" |  | ||||||
| msgstr "Website:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:442 |  | ||||||
| msgid "Close" |  | ||||||
| msgstr "Close" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:450 ImageBrowser.py:453 |  | ||||||
| msgid "Cache" |  | ||||||
| msgstr "Cache" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:450 |  | ||||||
| msgid "Cache Taggera zostało wyczyszczone." |  | ||||||
| msgstr "Tagger cache has been cleared." |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:453 |  | ||||||
| msgid "Błąd przy czyszczeniu cache:" |  | ||||||
| msgstr "Error clearing cache:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:463 |  | ||||||
| msgid "Login:" |  | ||||||
| msgstr "Login:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:469 |  | ||||||
| msgid "Hasło:" |  | ||||||
| msgstr "Password:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:475 |  | ||||||
| msgid "Base URL:" |  | ||||||
| msgstr "Base URL:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:481 |  | ||||||
| msgid "Default Tags:" |  | ||||||
| msgstr "Default Tags:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:487 |  | ||||||
| msgid "Browser:" |  | ||||||
| msgstr "Browser:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:501 |  | ||||||
| msgid "Language:" |  | ||||||
| msgstr "Language:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:533 |  | ||||||
| msgid "Zapisz" |  | ||||||
| msgstr "Save" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:575 |  | ||||||
| msgid "PNG Tags" |  | ||||||
| msgstr "PNG Tags" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:587 |  | ||||||
| msgid "Tagger Tags" |  | ||||||
| msgstr "Tagger Tags" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:601 |  | ||||||
| msgid "Manual Tags" |  | ||||||
| msgstr "Manual Tags" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:609 |  | ||||||
| msgid "Final Tags" |  | ||||||
| msgstr "Final Tags" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:634 |  | ||||||
| msgid "Wyświetl" |  | ||||||
| msgstr "Display" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:651 |  | ||||||
| msgid "Przetworzono tagi:" |  | ||||||
| msgstr "Processed tags:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:651 ImageBrowser.py:652 ImageBrowser.py:653 |  | ||||||
| msgid "plików" |  | ||||||
| msgstr "files" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:652 |  | ||||||
| msgid "Zweryfikowano status uploadu:" |  | ||||||
| msgstr "Upload status verified:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:653 |  | ||||||
| msgid "Zuploadowano:" |  | ||||||
| msgstr "Uploaded:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:682 |  | ||||||
| msgid "Wybierz folder z obrazkami PNG, JPEG, WebP, AVIF i GIF" |  | ||||||
| msgstr "Select folder with PNG, JPEG, WebP, AVIF, and GIF images" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:724 |  | ||||||
| msgid "Informacja" |  | ||||||
| msgstr "Information" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:725 |  | ||||||
| #, fuzzy |  | ||||||
| msgid "Brak plików PNG, JPEG, WebP, AVIF lub GIF w wybranym folderze." |  | ||||||
| msgstr "No PNG files in the selected folder." |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:808 |  | ||||||
| msgid "Błąd podczas sprawdzania paczki uploadu:" |  | ||||||
| msgstr "Error while checking upload package:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:884 |  | ||||||
| msgid "Error computing MD5:" | msgid "Error computing MD5:" | ||||||
| msgstr "Error computing MD5:" | msgstr "Error computing MD5:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:946 | #: Core.py:428 | ||||||
| msgid "Błąd" | msgid "Błąd podczas sprawdzania paczki uploadu:" | ||||||
| msgstr "Error" | msgstr "Error while checking upload package:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:946 | #: Core.py:437 | ||||||
| msgid "Nie można załadować obrazka:" | msgid "Plik nie istnieje:" | ||||||
| msgstr "Unable to load image:" | msgstr "File does not exist:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1156 ImageBrowser.py:1166 | #: Core.py:443 | ||||||
| #, python-brace-format | msgid "Tagi dla pliku" | ||||||
| msgid "Warning: Tag '{tag}' not found in implication graph" | msgstr "Tags for file" | ||||||
| msgstr "Warning: Tag '{tag}' not found in implication graph" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1396 | #: Core.py:452 | ||||||
| msgid "Tagger przetwarza..." | msgid "Błąd podczas autotagowania pliku" | ||||||
| msgstr "Tagger processing..." | msgstr "Error during file autotagowania" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1421 | #: Core.py:459 | ||||||
|  | msgid "Podana ścieżka nie jest katalogiem:" | ||||||
|  | msgstr "Given path is not a directory:" | ||||||
|  |  | ||||||
|  | #: Core.py:467 | ||||||
|  | msgid "Brak obrazów do przetworzenia w katalogu:" | ||||||
|  | msgstr "No images to process in directory:" | ||||||
|  |  | ||||||
|  | #: Core.py:490 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Wysyłam plik {base_file_name}..." | msgid "Wysyłam plik {base_file_name}..." | ||||||
| msgstr "Sending file {base_file_name}..." | msgstr "Uploading file {base_file_name}..." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1462 | #: Core.py:525 | ||||||
| msgid "Wysyłanie zakończone powodzeniem!" | msgid "Wysyłanie zakończone powodzeniem!" | ||||||
| msgstr "Upload completed successfully!" | msgstr "Upload completed successfully!" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1466 ImageBrowser.py:1475 | #: Core.py:529 Core.py:538 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "" | msgid "" | ||||||
| "Wysyłanie zakończone błędem.\n" | "Wysyłanie zakończone błędem.\n" | ||||||
| @@ -320,40 +103,52 @@ msgstr "" | |||||||
| "Status: {status_code}\n" | "Status: {status_code}\n" | ||||||
| "Content: {text}" | "Content: {text}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1481 ImageBrowser.py:1484 | #: Core.py:547 Core.py:553 ImageBrowser.py:654 ImageBrowser.py:657 | ||||||
|  | #: ImageBrowser.py:1177 ImageBrowser.py:1180 | ||||||
| msgid "Wysyłanie" | msgid "Wysyłanie" | ||||||
| msgstr "Uploading" | msgstr "Uploading" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1497 | #: Core.py:565 | ||||||
| msgid "Błąd wysyłania" | msgid "Błąd wysyłania pliku" | ||||||
| msgstr "Upload error" | msgstr "Upload error" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1517 | #: Core.py:595 | ||||||
| msgid "Błąd edycji" | msgid "Anulowano operację!" | ||||||
| msgstr "Edit error" | msgstr "Operation cancelled!" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1517 | #: Core.py:605 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "" | ||||||
|  | "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" | ||||||
|  | msgstr "" | ||||||
|  | "Uploading {file_path} with tags: {final_tags} and rating: {final_rating}" | ||||||
|  |  | ||||||
|  | #: Core.py:624 | ||||||
|  | msgid "Przesłano pliki!" | ||||||
|  | msgstr "Files have been uploaded!" | ||||||
|  |  | ||||||
|  | #: Core.py:645 Core.py:649 | ||||||
| msgid "Post nie został znaleziony dla tego pliku" | msgid "Post nie został znaleziony dla tego pliku" | ||||||
| msgstr "Post not found for this file" | msgstr "Post not found for this file" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1527 | #: Core.py:660 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Aktualizuję tagi dla {base_file_name}..." | msgid "Aktualizuję tagi dla {base_file_name}..." | ||||||
| msgstr "Updating tags for {base_file_name}..." | msgstr "Updating tags for {base_file_name}..." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1537 ImageBrowser.py:1547 ImageBrowser.py:1578 | #: Core.py:670 Core.py:680 Core.py:705 | ||||||
| msgid "Operacja anulowana" | msgid "Operacja anulowana" | ||||||
| msgstr "Operation cancelled" | msgstr "Operation cancelled" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1588 | #: Core.py:715 | ||||||
| msgid "Tagi zostały zaktualizowane!" | msgid "Tagi zostały zaktualizowane!" | ||||||
| msgstr "Tags have been updated!" | msgstr "Tags have been updated!" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1590 | #: Core.py:720 ImageBrowser.py:719 | ||||||
| msgid "Sukces edycji" | msgid "Sukces edycji" | ||||||
| msgstr "Edit successful" | msgstr "Edit successful" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1596 | #: Core.py:727 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "" | msgid "" | ||||||
| "Błąd podczas aktualizacji tagów\n" | "Błąd podczas aktualizacji tagów\n" | ||||||
| @@ -362,19 +157,263 @@ msgstr "" | |||||||
| "Error updating tags\n" | "Error updating tags\n" | ||||||
| "Status: {code}" | "Status: {code}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1600 | #: Core.py:731 | ||||||
| msgid "Treść:" | msgid "Treść:" | ||||||
| msgstr "Content:" | msgstr "Content:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1604 | #: Core.py:735 ImageBrowser.py:716 | ||||||
|  | msgid "Błąd edycji" | ||||||
|  | msgstr "Edit error" | ||||||
|  |  | ||||||
|  | #: Core.py:741 | ||||||
| msgid "Krytyczny błąd edycji" | msgid "Krytyczny błąd edycji" | ||||||
| msgstr "Critical edit error" | msgstr "Critical edit error" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1616 | #: ImageBrowser.py:112 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Update check failed: {error}" | ||||||
|  | msgstr "Update check failed: {error}" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:114 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Malformed pyproject.toml: {error}" | ||||||
|  | msgstr "Malformed pyproject.toml: {error}" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:117 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Unexpected error during update check: {error}" | ||||||
|  | msgstr "Unexpected error during update check: {error}" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:124 | ||||||
|  | msgid "Update Available" | ||||||
|  | msgstr "Update Available" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:126 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "" | ||||||
|  | "A new version {new_version} is available!\n" | ||||||
|  | "You have version {current_version}.\n" | ||||||
|  | "\n" | ||||||
|  | "Update using: {update_command}" | ||||||
|  | msgstr "" | ||||||
|  | "A new version {new_version} is available!\n" | ||||||
|  | "You have version {current_version}.\n" | ||||||
|  | "\n" | ||||||
|  | "Update using: {update_command}" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:183 | ||||||
|  | msgid "Otwórz folder" | ||||||
|  | msgstr "Open folder" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:186 ImageBrowser.py:484 ImageBrowser.py:601 | ||||||
|  | #: ImageBrowser.py:609 | ||||||
|  | msgid "Wyślij" | ||||||
|  | msgstr "Upload" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:189 ImageBrowser.py:594 | ||||||
|  | msgid "Wyślij wszystko" | ||||||
|  | msgstr "Upload all" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:193 ImageBrowser.py:595 ImageBrowser.py:601 | ||||||
|  | msgid "Podmień tagi" | ||||||
|  | msgstr "Replace tags" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:196 ImageBrowser.py:596 | ||||||
|  | msgid "Otwórz post" | ||||||
|  | msgstr "Open post" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:199 | ||||||
|  | msgid "Zakończ" | ||||||
|  | msgstr "Finish" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:201 | ||||||
|  | msgid "Plik" | ||||||
|  | msgstr "File" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:205 ImageBrowser.py:306 | ||||||
|  | msgid "Ustawienia" | ||||||
|  | msgstr "Settings" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:208 | ||||||
|  | msgid "Wyczyść cache Taggera" | ||||||
|  | msgstr "Clear Tagger cache" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:211 | ||||||
|  | msgid "Zregeneruj bazę tagów" | ||||||
|  | msgstr "Regenerate tag database" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:213 | ||||||
|  | msgid "Opcje" | ||||||
|  | msgstr "Options" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:216 | ||||||
|  | msgid "About" | ||||||
|  | msgstr "About" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:217 | ||||||
|  | msgid "Help" | ||||||
|  | msgstr "Help" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:222 | ||||||
|  | msgid "About Kapitanbooru Uploader" | ||||||
|  | msgstr "About Kapitanbooru Uploader" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:239 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "A new version {new_version} is available!" | ||||||
|  | msgstr "A new version {new_version} is available!" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:246 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Current version: {version}" | ||||||
|  | msgstr "Current version: {version}" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:248 | ||||||
|  | msgid "A GUI application for uploading images to KapitanBooru." | ||||||
|  | msgstr "A GUI application for uploading images to KapitanBooru." | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:249 | ||||||
|  | msgid "Features include image upload, tag management, automatic" | ||||||
|  | msgstr "Features include image upload, tag management, automatic" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:250 | ||||||
|  | msgid "tagging with wdtagger, and cache management." | ||||||
|  | msgstr "tagging with wdtagger, and cache management." | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:252 | ||||||
|  | msgid "Authors:" | ||||||
|  | msgstr "Authors:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:255 | ||||||
|  | msgid "License: MIT License" | ||||||
|  | msgstr "License: MIT License" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:268 | ||||||
|  | msgid "Repository:" | ||||||
|  | msgstr "Repository:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:277 | ||||||
|  | msgid "Website:" | ||||||
|  | msgstr "Website:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:288 | ||||||
|  | msgid "Close" | ||||||
|  | msgstr "Close" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:298 ImageBrowser.py:301 | ||||||
|  | msgid "Cache" | ||||||
|  | msgstr "Cache" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:298 | ||||||
|  | msgid "Cache Taggera zostało wyczyszczone." | ||||||
|  | msgstr "Tagger cache has been cleared." | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:301 | ||||||
|  | msgid "Błąd przy czyszczeniu cache:" | ||||||
|  | msgstr "Error clearing cache:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:311 | ||||||
|  | msgid "Login:" | ||||||
|  | msgstr "Login:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:317 | ||||||
|  | msgid "Hasło:" | ||||||
|  | msgstr "Password:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:323 | ||||||
|  | msgid "Base URL:" | ||||||
|  | msgstr "Base URL:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:329 | ||||||
|  | msgid "Default Tags:" | ||||||
|  | msgstr "Default Tags:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:335 | ||||||
|  | msgid "Browser:" | ||||||
|  | msgstr "Browser:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:349 | ||||||
|  | msgid "Language:" | ||||||
|  | msgstr "Language:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:385 | ||||||
|  | msgid "Zapisz" | ||||||
|  | msgstr "Save" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:427 | ||||||
|  | msgid "PNG Tags" | ||||||
|  | msgstr "PNG Tags" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:439 | ||||||
|  | msgid "Tagger Tags" | ||||||
|  | msgstr "Tagger Tags" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:453 | ||||||
|  | msgid "Manual Tags" | ||||||
|  | msgstr "Manual Tags" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:464 | ||||||
|  | msgid "Final Tags" | ||||||
|  | msgstr "Final Tags" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:489 | ||||||
|  | msgid "Wyświetl" | ||||||
|  | msgstr "Display" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:506 | ||||||
|  | msgid "Przetworzono tagi:" | ||||||
|  | msgstr "Processed tags:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:506 ImageBrowser.py:507 ImageBrowser.py:508 | ||||||
|  | msgid "plików" | ||||||
|  | msgstr "files" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:507 | ||||||
|  | msgid "Zweryfikowano status uploadu:" | ||||||
|  | msgstr "Upload status verified:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:508 | ||||||
|  | msgid "Zuploadowano:" | ||||||
|  | msgstr "Uploaded:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:537 | ||||||
|  | msgid "Wybierz folder z obrazkami PNG, JPEG, WebP, AVIF i GIF" | ||||||
|  | msgstr "Select folder with PNG, JPEG, WebP, AVIF, and GIF images" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:552 | ||||||
|  | msgid "Informacja" | ||||||
|  | msgstr "Information" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:553 | ||||||
|  | msgid "Brak plików PNG, JPEG, WebP, AVIF lub GIF w wybranym folderze." | ||||||
|  | msgstr "No PNG, JPEG, WebP, AVIF or GIF files in the selected folder." | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:660 ImageBrowser.py:1183 | ||||||
|  | msgid "Błąd wysyłania" | ||||||
|  | msgstr "Upload error" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:695 | ||||||
|  | msgid "Błąd" | ||||||
|  | msgstr "Error" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:695 | ||||||
|  | msgid "Nie można załadować obrazka:" | ||||||
|  | msgstr "Unable to load image:" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:923 ImageBrowser.py:935 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Warning: Tag '{tag}' not found in implication graph" | ||||||
|  | msgstr "Warning: Tag '{tag}' not found in implication graph" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:1144 | ||||||
|  | msgid "Tagger przetwarza..." | ||||||
|  | msgstr "Tagger processing..." | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:1161 | ||||||
| msgid "Potwierdzenie" | msgid "Potwierdzenie" | ||||||
| msgstr "Confirmation" | msgstr "Confirmation" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1618 | #: ImageBrowser.py:1163 | ||||||
| msgid "" | msgid "" | ||||||
| "Czy na pewno chcesz wrzucić wszystkie niewrzucone pliki?\n" | "Czy na pewno chcesz wrzucić wszystkie niewrzucone pliki?\n" | ||||||
| "Każdy z nich zostanie oznaczony tagiem 'meta:auto_upload'.\n" | "Każdy z nich zostanie oznaczony tagiem 'meta:auto_upload'.\n" | ||||||
| @@ -384,21 +423,6 @@ msgstr "" | |||||||
| "Each will be tagged with 'meta:auto_upload'.\n" | "Each will be tagged with 'meta:auto_upload'.\n" | ||||||
| "Make sure the tags are correct!" | "Make sure the tags are correct!" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1642 |  | ||||||
| msgid "Anulowano operację!" |  | ||||||
| msgstr "Operation cancelled!" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1650 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "" |  | ||||||
| "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" |  | ||||||
| msgstr "" |  | ||||||
| "Uploading {file_path} with tags: {final_tags} and rating: {final_rating}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1666 |  | ||||||
| msgid "Przesłano pliki!" |  | ||||||
| msgstr "Files have been uploaded!" |  | ||||||
|  |  | ||||||
| #: ProcessingDialog.py:15 | #: ProcessingDialog.py:15 | ||||||
| msgid "Processing..." | msgid "Processing..." | ||||||
| msgstr "Processing..." | msgstr "Processing..." | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: Kapitanbooru Uploader 0.8.3\n" | "Project-Id-Version: Kapitanbooru Uploader 0.9.0\n" | ||||||
| "Report-Msgid-Bugs-To: kapitan@mlesniak.pl\n" | "Report-Msgid-Bugs-To: kapitan@mlesniak.pl\n" | ||||||
| "POT-Creation-Date: 2025-06-25 23:49+0200\n" | "POT-Creation-Date: 2025-06-26 17:07+0200\n" | ||||||
| "Language: pl\n" | "Language: pl\n" | ||||||
| "Content-Type: text/plain; charset=UTF-8\n" | "Content-Type: text/plain; charset=UTF-8\n" | ||||||
| "Content-Transfer-Encoding: 8bit\n" | "Content-Transfer-Encoding: 8bit\n" | ||||||
| @@ -45,26 +45,152 @@ msgstr "Znaleziono auth_token:" | |||||||
| msgid "auth_token not found in the HTML page." | msgid "auth_token not found in the HTML page." | ||||||
| msgstr "Nie znaleziono auth_token w stronie HTML." | msgstr "Nie znaleziono auth_token w stronie HTML." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:138 | #: Core.py:204 | ||||||
|  | msgid "Błąd przy otwieraniu pliku" | ||||||
|  | msgstr "Błąd przy otwieraniu pliku" | ||||||
|  |  | ||||||
|  | #: Core.py:245 | ||||||
|  | msgid "Tagger przetworzył:" | ||||||
|  | msgstr "Tagger przetworzył:" | ||||||
|  |  | ||||||
|  | #: Core.py:248 | ||||||
|  | msgid "Błąd Taggera dla" | ||||||
|  | msgstr "Błąd Taggera dla" | ||||||
|  |  | ||||||
|  | #: Core.py:303 | ||||||
|  | msgid "Error computing MD5:" | ||||||
|  | msgstr "Błąd przy obliczaniu MD5:" | ||||||
|  |  | ||||||
|  | #: Core.py:428 | ||||||
|  | msgid "Błąd podczas sprawdzania paczki uploadu:" | ||||||
|  | msgstr "Błąd podczas sprawdzania paczki uploadu:" | ||||||
|  |  | ||||||
|  | #: Core.py:437 | ||||||
|  | msgid "Plik nie istnieje:" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: Core.py:443 | ||||||
|  | msgid "Tagi dla pliku" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: Core.py:452 | ||||||
|  | msgid "Błąd podczas autotagowania pliku" | ||||||
|  | msgstr "Błąd podczas autotagowania pliku" | ||||||
|  |  | ||||||
|  | #: Core.py:459 | ||||||
|  | msgid "Podana ścieżka nie jest katalogiem:" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: Core.py:467 | ||||||
|  | msgid "Brak obrazów do przetworzenia w katalogu:" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: Core.py:490 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Wysyłam plik {base_file_name}..." | ||||||
|  | msgstr "Wysyłam plik {base_file_name}..." | ||||||
|  |  | ||||||
|  | #: Core.py:525 | ||||||
|  | msgid "Wysyłanie zakończone powodzeniem!" | ||||||
|  | msgstr "Wysyłanie zakończone powodzeniem!" | ||||||
|  |  | ||||||
|  | #: Core.py:529 Core.py:538 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "" | ||||||
|  | "Wysyłanie zakończone błędem.\n" | ||||||
|  | "Status: {status_code}\n" | ||||||
|  | "Treść: {text}" | ||||||
|  | msgstr "" | ||||||
|  | "Wysyłanie zakończone błędem.\n" | ||||||
|  | "Status: {status_code}\n" | ||||||
|  | "Treść: {text}" | ||||||
|  |  | ||||||
|  | #: Core.py:547 Core.py:553 ImageBrowser.py:654 ImageBrowser.py:657 | ||||||
|  | #: ImageBrowser.py:1177 ImageBrowser.py:1180 | ||||||
|  | msgid "Wysyłanie" | ||||||
|  | msgstr "Wysyłanie" | ||||||
|  |  | ||||||
|  | #: Core.py:565 | ||||||
|  | msgid "Błąd wysyłania pliku" | ||||||
|  | msgstr "Błąd wysyłania pliku" | ||||||
|  |  | ||||||
|  | #: Core.py:595 | ||||||
|  | msgid "Anulowano operację!" | ||||||
|  | msgstr "Operacja anulowana!" | ||||||
|  |  | ||||||
|  | #: Core.py:605 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "" | ||||||
|  | "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" | ||||||
|  | msgstr "" | ||||||
|  | "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" | ||||||
|  |  | ||||||
|  | #: Core.py:624 | ||||||
|  | msgid "Przesłano pliki!" | ||||||
|  | msgstr "Pliki zostały przesłane!" | ||||||
|  |  | ||||||
|  | #: Core.py:645 Core.py:649 | ||||||
|  | msgid "Post nie został znaleziony dla tego pliku" | ||||||
|  | msgstr "Post nie został znaleziony dla tego pliku" | ||||||
|  |  | ||||||
|  | #: Core.py:660 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "Aktualizuję tagi dla {base_file_name}..." | ||||||
|  | msgstr "Aktualizuję tagi dla {base_file_name}..." | ||||||
|  |  | ||||||
|  | #: Core.py:670 Core.py:680 Core.py:705 | ||||||
|  | msgid "Operacja anulowana" | ||||||
|  | msgstr "Operacja anulowana" | ||||||
|  |  | ||||||
|  | #: Core.py:715 | ||||||
|  | msgid "Tagi zostały zaktualizowane!" | ||||||
|  | msgstr "Tagi zostały zaktualizowane!" | ||||||
|  |  | ||||||
|  | #: Core.py:720 ImageBrowser.py:719 | ||||||
|  | msgid "Sukces edycji" | ||||||
|  | msgstr "Sukces edycji" | ||||||
|  |  | ||||||
|  | #: Core.py:727 | ||||||
|  | #, python-brace-format | ||||||
|  | msgid "" | ||||||
|  | "Błąd podczas aktualizacji tagów\n" | ||||||
|  | "Status: {code}" | ||||||
|  | msgstr "" | ||||||
|  | "Błąd podczas aktualizacji tagów\n" | ||||||
|  | "Status: {code}" | ||||||
|  |  | ||||||
|  | #: Core.py:731 | ||||||
|  | msgid "Treść:" | ||||||
|  | msgstr "Treść:" | ||||||
|  |  | ||||||
|  | #: Core.py:735 ImageBrowser.py:716 | ||||||
|  | msgid "Błąd edycji" | ||||||
|  | msgstr "Błąd edycji" | ||||||
|  |  | ||||||
|  | #: Core.py:741 | ||||||
|  | msgid "Krytyczny błąd edycji" | ||||||
|  | msgstr "Krytyczny błąd edycji" | ||||||
|  |  | ||||||
|  | #: ImageBrowser.py:112 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Update check failed: {error}" | msgid "Update check failed: {error}" | ||||||
| msgstr "Sprawdzenie aktualizacji nie powiodło się: {error}" | msgstr "Sprawdzenie aktualizacji nie powiodło się: {error}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:140 | #: ImageBrowser.py:114 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Malformed pyproject.toml: {error}" | msgid "Malformed pyproject.toml: {error}" | ||||||
| msgstr "Nieprawidłowy plik pyproject.toml: {error}" | msgstr "Nieprawidłowy plik pyproject.toml: {error}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:143 | #: ImageBrowser.py:117 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Unexpected error during update check: {error}" | msgid "Unexpected error during update check: {error}" | ||||||
| msgstr "Nieoczekiwany błąd podczas sprawdzania aktualizacji: {error}" | msgstr "Nieoczekiwany błąd podczas sprawdzania aktualizacji: {error}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:150 | #: ImageBrowser.py:124 | ||||||
| msgid "Update Available" | msgid "Update Available" | ||||||
| msgstr "Aktualizacja dostępna" | msgstr "Aktualizacja dostępna" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:152 | #: ImageBrowser.py:126 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "" | msgid "" | ||||||
| "A new version {new_version} is available!\n" | "A new version {new_version} is available!\n" | ||||||
| @@ -77,307 +203,219 @@ msgstr "" | |||||||
| "\n" | "\n" | ||||||
| "Aktualizuj za pomocą: {update_command}" | "Aktualizuj za pomocą: {update_command}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:266 | #: ImageBrowser.py:183 | ||||||
| msgid "Błąd przy otwieraniu pliku" |  | ||||||
| msgstr "Błąd przy otwieraniu pliku" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:308 |  | ||||||
| msgid "Tagger przetworzył:" |  | ||||||
| msgstr "Tagger przetworzył:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:311 |  | ||||||
| msgid "Błąd Taggera dla" |  | ||||||
| msgstr "Błąd Taggera dla" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:337 |  | ||||||
| msgid "Otwórz folder" | msgid "Otwórz folder" | ||||||
| msgstr "Otwórz folder" | msgstr "Otwórz folder" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:340 ImageBrowser.py:629 ImageBrowser.py:856 | #: ImageBrowser.py:186 ImageBrowser.py:484 ImageBrowser.py:601 | ||||||
| #: ImageBrowser.py:864 | #: ImageBrowser.py:609 | ||||||
| msgid "Wyślij" | msgid "Wyślij" | ||||||
| msgstr "Wyślij" | msgstr "Wyślij" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:343 ImageBrowser.py:849 | #: ImageBrowser.py:189 ImageBrowser.py:594 | ||||||
| msgid "Wyślij wszystko" | msgid "Wyślij wszystko" | ||||||
| msgstr "Wyślij wszystko" | msgstr "Wyślij wszystko" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:347 ImageBrowser.py:850 ImageBrowser.py:856 | #: ImageBrowser.py:193 ImageBrowser.py:595 ImageBrowser.py:601 | ||||||
| msgid "Podmień tagi" | msgid "Podmień tagi" | ||||||
| msgstr "Podmień tagi" | msgstr "Podmień tagi" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:350 ImageBrowser.py:851 | #: ImageBrowser.py:196 ImageBrowser.py:596 | ||||||
| msgid "Otwórz post" | msgid "Otwórz post" | ||||||
| msgstr "Otwórz post" | msgstr "Otwórz post" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:353 | #: ImageBrowser.py:199 | ||||||
| msgid "Zakończ" | msgid "Zakończ" | ||||||
| msgstr "Zakończ" | msgstr "Zakończ" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:355 | #: ImageBrowser.py:201 | ||||||
| msgid "Plik" | msgid "Plik" | ||||||
| msgstr "Plik" | msgstr "Plik" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:359 ImageBrowser.py:458 | #: ImageBrowser.py:205 ImageBrowser.py:306 | ||||||
| msgid "Ustawienia" | msgid "Ustawienia" | ||||||
| msgstr "Ustawienia" | msgstr "Ustawienia" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:362 | #: ImageBrowser.py:208 | ||||||
| msgid "Wyczyść cache Taggera" | msgid "Wyczyść cache Taggera" | ||||||
| msgstr "Wyczyść cache Taggera" | msgstr "Wyczyść cache Taggera" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:365 | #: ImageBrowser.py:211 | ||||||
| msgid "Zregeneruj bazę tagów" | msgid "Zregeneruj bazę tagów" | ||||||
| msgstr "Zregeneruj bazę tagów" | msgstr "Zregeneruj bazę tagów" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:367 | #: ImageBrowser.py:213 | ||||||
| msgid "Opcje" | msgid "Opcje" | ||||||
| msgstr "Opcje" | msgstr "Opcje" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:370 | #: ImageBrowser.py:216 | ||||||
| msgid "About" | msgid "About" | ||||||
| msgstr "O programie" | msgstr "O programie" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:371 | #: ImageBrowser.py:217 | ||||||
| msgid "Help" | msgid "Help" | ||||||
| msgstr "Pomoc" | msgstr "Pomoc" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:376 | #: ImageBrowser.py:222 | ||||||
| msgid "About Kapitanbooru Uploader" | msgid "About Kapitanbooru Uploader" | ||||||
| msgstr "O programie Kapitanbooru Uploader" | msgstr "O programie Kapitanbooru Uploader" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:393 | #: ImageBrowser.py:239 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "A new version {new_version} is available!" | msgid "A new version {new_version} is available!" | ||||||
| msgstr "Dostępna jest nowa wersja {new_version}!" | msgstr "Dostępna jest nowa wersja {new_version}!" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:400 | #: ImageBrowser.py:246 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Current version: {version}" | msgid "Current version: {version}" | ||||||
| msgstr "Obecna wersja: {version}" | msgstr "Obecna wersja: {version}" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:402 | #: ImageBrowser.py:248 | ||||||
| msgid "A GUI application for uploading images to KapitanBooru." | msgid "A GUI application for uploading images to KapitanBooru." | ||||||
| msgstr "Aplikacja GUI do przesyłania obrazów do KapitanBooru." | msgstr "Aplikacja GUI do przesyłania obrazów do KapitanBooru." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:403 | #: ImageBrowser.py:249 | ||||||
| msgid "Features include image upload, tag management, automatic" | msgid "Features include image upload, tag management, automatic" | ||||||
| msgstr "Funkcje obejmują przesyłanie obrazów, zarządzanie tagami, automatyczne" | msgstr "Funkcje obejmują przesyłanie obrazów, zarządzanie tagami, automatyczne" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:404 | #: ImageBrowser.py:250 | ||||||
| msgid "tagging with wdtagger, and cache management." | msgid "tagging with wdtagger, and cache management." | ||||||
| msgstr "tagowanie za pomocą wdtagger oraz zarządzanie cache." | msgstr "tagowanie za pomocą wdtagger oraz zarządzanie cache." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:406 | #: ImageBrowser.py:252 | ||||||
| msgid "Authors:" | msgid "Authors:" | ||||||
| msgstr "Autorzy:" | msgstr "Autorzy:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:409 | #: ImageBrowser.py:255 | ||||||
| msgid "License: MIT License" | msgid "License: MIT License" | ||||||
| msgstr "Licencja: MIT License" | msgstr "Licencja: MIT License" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:422 | #: ImageBrowser.py:268 | ||||||
| msgid "Repository:" | msgid "Repository:" | ||||||
| msgstr "Repozytorium:" | msgstr "Repozytorium:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:431 | #: ImageBrowser.py:277 | ||||||
| msgid "Website:" | msgid "Website:" | ||||||
| msgstr "Strona internetowa:" | msgstr "Strona internetowa:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:442 | #: ImageBrowser.py:288 | ||||||
| msgid "Close" | msgid "Close" | ||||||
| msgstr "Zamknij" | msgstr "Zamknij" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:450 ImageBrowser.py:453 | #: ImageBrowser.py:298 ImageBrowser.py:301 | ||||||
| msgid "Cache" | msgid "Cache" | ||||||
| msgstr "Cache" | msgstr "Cache" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:450 | #: ImageBrowser.py:298 | ||||||
| msgid "Cache Taggera zostało wyczyszczone." | msgid "Cache Taggera zostało wyczyszczone." | ||||||
| msgstr "Cache Taggera zostało wyczyszczone." | msgstr "Cache Taggera zostało wyczyszczone." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:453 | #: ImageBrowser.py:301 | ||||||
| msgid "Błąd przy czyszczeniu cache:" | msgid "Błąd przy czyszczeniu cache:" | ||||||
| msgstr "Błąd przy czyszczeniu cache:" | msgstr "Błąd przy czyszczeniu cache:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:463 | #: ImageBrowser.py:311 | ||||||
| msgid "Login:" | msgid "Login:" | ||||||
| msgstr "Login:" | msgstr "Login:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:469 | #: ImageBrowser.py:317 | ||||||
| msgid "Hasło:" | msgid "Hasło:" | ||||||
| msgstr "Hasło:" | msgstr "Hasło:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:475 | #: ImageBrowser.py:323 | ||||||
| msgid "Base URL:" | msgid "Base URL:" | ||||||
| msgstr "Base URL:" | msgstr "Base URL:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:481 | #: ImageBrowser.py:329 | ||||||
| msgid "Default Tags:" | msgid "Default Tags:" | ||||||
| msgstr "Domyślne tagi:" | msgstr "Domyślne tagi:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:487 | #: ImageBrowser.py:335 | ||||||
| msgid "Browser:" | msgid "Browser:" | ||||||
| msgstr "Przeglądarka:" | msgstr "Przeglądarka:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:501 | #: ImageBrowser.py:349 | ||||||
| msgid "Language:" | msgid "Language:" | ||||||
| msgstr "Język:" | msgstr "Język:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:533 | #: ImageBrowser.py:385 | ||||||
| msgid "Zapisz" | msgid "Zapisz" | ||||||
| msgstr "Zapisz" | msgstr "Zapisz" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:575 | #: ImageBrowser.py:427 | ||||||
| msgid "PNG Tags" | msgid "PNG Tags" | ||||||
| msgstr "Tagi PNG" | msgstr "Tagi PNG" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:587 | #: ImageBrowser.py:439 | ||||||
| msgid "Tagger Tags" | msgid "Tagger Tags" | ||||||
| msgstr "Tagi Taggera" | msgstr "Tagi Taggera" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:601 | #: ImageBrowser.py:453 | ||||||
| msgid "Manual Tags" | msgid "Manual Tags" | ||||||
| msgstr "Tagi ręczne" | msgstr "Tagi ręczne" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:609 | #: ImageBrowser.py:464 | ||||||
| msgid "Final Tags" | msgid "Final Tags" | ||||||
| msgstr "Ostateczne tagi" | msgstr "Ostateczne tagi" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:634 | #: ImageBrowser.py:489 | ||||||
| msgid "Wyświetl" | msgid "Wyświetl" | ||||||
| msgstr "Wyświetl" | msgstr "Wyświetl" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:651 | #: ImageBrowser.py:506 | ||||||
| msgid "Przetworzono tagi:" | msgid "Przetworzono tagi:" | ||||||
| msgstr "Przetworzono tagi:" | msgstr "Przetworzono tagi:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:651 ImageBrowser.py:652 ImageBrowser.py:653 | #: ImageBrowser.py:506 ImageBrowser.py:507 ImageBrowser.py:508 | ||||||
| msgid "plików" | msgid "plików" | ||||||
| msgstr "plików" | msgstr "plików" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:652 | #: ImageBrowser.py:507 | ||||||
| msgid "Zweryfikowano status uploadu:" | msgid "Zweryfikowano status uploadu:" | ||||||
| msgstr "Zweryfikowano status uploadu:" | msgstr "Zweryfikowano status uploadu:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:653 | #: ImageBrowser.py:508 | ||||||
| msgid "Zuploadowano:" | msgid "Zuploadowano:" | ||||||
| msgstr "Zuploadowano:" | msgstr "Zuploadowano:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:682 | #: ImageBrowser.py:537 | ||||||
| #, fuzzy |  | ||||||
| msgid "Wybierz folder z obrazkami PNG, JPEG, WebP, AVIF i GIF" | msgid "Wybierz folder z obrazkami PNG, JPEG, WebP, AVIF i GIF" | ||||||
| msgstr "Wybierz folder z obrazami PNG" | msgstr "Wybierz folder z obrazkami PNG, JPEG, WebP, AVIF i GIF" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:724 | #: ImageBrowser.py:552 | ||||||
| msgid "Informacja" | msgid "Informacja" | ||||||
| msgstr "Informacja" | msgstr "Informacja" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:725 | #: ImageBrowser.py:553 | ||||||
| #, fuzzy |  | ||||||
| msgid "Brak plików PNG, JPEG, WebP, AVIF lub GIF w wybranym folderze." | msgid "Brak plików PNG, JPEG, WebP, AVIF lub GIF w wybranym folderze." | ||||||
| msgstr "Brak plików PNG w wybranym folderze." | msgstr "Brak plików PNG, JPEG, WebP, AVIF lub GIF w wybranym folderze." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:808 | #: ImageBrowser.py:660 ImageBrowser.py:1183 | ||||||
| msgid "Błąd podczas sprawdzania paczki uploadu:" | msgid "Błąd wysyłania" | ||||||
| msgstr "Błąd podczas sprawdzania paczki uploadu:" | msgstr "Błąd wysyłania" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:884 | #: ImageBrowser.py:695 | ||||||
| msgid "Error computing MD5:" |  | ||||||
| msgstr "Błąd przy obliczaniu MD5:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:946 |  | ||||||
| msgid "Błąd" | msgid "Błąd" | ||||||
| msgstr "Błąd" | msgstr "Błąd" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:946 | #: ImageBrowser.py:695 | ||||||
| msgid "Nie można załadować obrazka:" | msgid "Nie można załadować obrazka:" | ||||||
| msgstr "Nie można załadować obrazka:" | msgstr "Nie można załadować obrazka:" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1156 ImageBrowser.py:1166 | #: ImageBrowser.py:923 ImageBrowser.py:935 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Warning: Tag '{tag}' not found in implication graph" | msgid "Warning: Tag '{tag}' not found in implication graph" | ||||||
| msgstr "Ostrzeżenie: Tag '{tag}' nie został znaleziony w grafie implikacji" | msgstr "Ostrzeżenie: Tag '{tag}' nie został znaleziony w grafie implikacji" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1396 | #: ImageBrowser.py:1144 | ||||||
| msgid "Tagger przetwarza..." | msgid "Tagger przetwarza..." | ||||||
| msgstr "Tagger przetwarza..." | msgstr "Tagger przetwarza..." | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1421 | #: ImageBrowser.py:1161 | ||||||
| #, python-brace-format |  | ||||||
| msgid "Wysyłam plik {base_file_name}..." |  | ||||||
| msgstr "Wysyłam plik {base_file_name}..." |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1462 |  | ||||||
| msgid "Wysyłanie zakończone powodzeniem!" |  | ||||||
| msgstr "Wysyłanie zakończone powodzeniem!" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1466 ImageBrowser.py:1475 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "" |  | ||||||
| "Wysyłanie zakończone błędem.\n" |  | ||||||
| "Status: {status_code}\n" |  | ||||||
| "Treść: {text}" |  | ||||||
| msgstr "" |  | ||||||
| "Wysyłanie zakończone błędem.\n" |  | ||||||
| "Status: {status_code}\n" |  | ||||||
| "Treść: {text}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1481 ImageBrowser.py:1484 |  | ||||||
| msgid "Wysyłanie" |  | ||||||
| msgstr "Wysyłanie" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1497 |  | ||||||
| msgid "Błąd wysyłania" |  | ||||||
| msgstr "Błąd wysyłania" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1517 |  | ||||||
| msgid "Błąd edycji" |  | ||||||
| msgstr "Błąd edycji" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1517 |  | ||||||
| msgid "Post nie został znaleziony dla tego pliku" |  | ||||||
| msgstr "Post nie został znaleziony dla tego pliku" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1527 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "Aktualizuję tagi dla {base_file_name}..." |  | ||||||
| msgstr "Aktualizuję tagi dla {base_file_name}..." |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1537 ImageBrowser.py:1547 ImageBrowser.py:1578 |  | ||||||
| msgid "Operacja anulowana" |  | ||||||
| msgstr "Operacja anulowana" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1588 |  | ||||||
| msgid "Tagi zostały zaktualizowane!" |  | ||||||
| msgstr "Tagi zostały zaktualizowane!" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1590 |  | ||||||
| msgid "Sukces edycji" |  | ||||||
| msgstr "Sukces edycji" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1596 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "" |  | ||||||
| "Błąd podczas aktualizacji tagów\n" |  | ||||||
| "Status: {code}" |  | ||||||
| msgstr "" |  | ||||||
| "Błąd podczas aktualizacji tagów\n" |  | ||||||
| "Status: {code}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1600 |  | ||||||
| msgid "Treść:" |  | ||||||
| msgstr "Treść:" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1604 |  | ||||||
| msgid "Krytyczny błąd edycji" |  | ||||||
| msgstr "Krytyczny błąd edycji" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1616 |  | ||||||
| msgid "Potwierdzenie" | msgid "Potwierdzenie" | ||||||
| msgstr "Potwierdzenie" | msgstr "Potwierdzenie" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1618 | #: ImageBrowser.py:1163 | ||||||
| msgid "" | msgid "" | ||||||
| "Czy na pewno chcesz wrzucić wszystkie niewrzucone pliki?\n" | "Czy na pewno chcesz wrzucić wszystkie niewrzucone pliki?\n" | ||||||
| "Każdy z nich zostanie oznaczony tagiem 'meta:auto_upload'.\n" | "Każdy z nich zostanie oznaczony tagiem 'meta:auto_upload'.\n" | ||||||
| @@ -387,21 +425,6 @@ msgstr "" | |||||||
| "Każdy z nich zostanie oznaczony tagiem 'meta:auto_upload'.\n" | "Każdy z nich zostanie oznaczony tagiem 'meta:auto_upload'.\n" | ||||||
| "Upewnij się, że tagi są poprawne!" | "Upewnij się, że tagi są poprawne!" | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1642 |  | ||||||
| msgid "Anulowano operację!" |  | ||||||
| msgstr "Operacja anulowana!" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1650 |  | ||||||
| #, python-brace-format |  | ||||||
| msgid "" |  | ||||||
| "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" |  | ||||||
| msgstr "" |  | ||||||
| "Wysyłanie {file_path} z tagami: {final_tags} i ratingiem: {final_rating}" |  | ||||||
|  |  | ||||||
| #: ImageBrowser.py:1666 |  | ||||||
| msgid "Przesłano pliki!" |  | ||||||
| msgstr "Pliki zostały przesłane!" |  | ||||||
|  |  | ||||||
| #: ProcessingDialog.py:15 | #: ProcessingDialog.py:15 | ||||||
| msgid "Processing..." | msgid "Processing..." | ||||||
| msgstr "Przetwarzanie..." | msgstr "Przetwarzanie..." | ||||||
| @@ -435,9 +458,8 @@ msgid "Błąd przy pobieraniu tagów artystów:" | |||||||
| msgstr "Błąd przy pobieraniu tagów artystów:" | msgstr "Błąd przy pobieraniu tagów artystów:" | ||||||
|  |  | ||||||
| #: tag_processing.py:208 | #: tag_processing.py:208 | ||||||
| #, fuzzy |  | ||||||
| msgid "Nie można sparsować parametrów." | msgid "Nie można sparsować parametrów." | ||||||
| msgstr "Nie można załadować obrazka:" | msgstr "Nie można sparsować parametrów." | ||||||
|  |  | ||||||
| #: tag_processing.py:295 | #: tag_processing.py:295 | ||||||
| msgid "Błąd podczas odczytu tag_aliases:" | msgid "Błąd podczas odczytu tag_aliases:" | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" | |||||||
|  |  | ||||||
| [project] | [project] | ||||||
| name = "kapitanbooru-uploader" | name = "kapitanbooru-uploader" | ||||||
| version = "0.8.3" | version = "0.9.0" | ||||||
| description = "A GUI application for uploading images to KapitanBooru" | description = "A GUI application for uploading images to KapitanBooru" | ||||||
| authors = [{ name = "Michał Leśniak", email = "kapitan@mlesniak.pl" }] | authors = [{ name = "Michał Leśniak", email = "kapitan@mlesniak.pl" }] | ||||||
| dependencies = [ | dependencies = [ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user