transpaste 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: transpaste
3
+ Version: 0.1.0
4
+ Summary: A local LLM-based clipboard translator
5
+ Author-email: CodeOfMe <wedonotuse@outlook.com>
6
+ License: GPL-3.0
7
+ Project-URL: Homepage, https://github.com/CodeOfMe/TransPaste
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: PySide6
11
+ Requires-Dist: requests
12
+
13
+ # TransPaste
14
+
15
+ TransPaste is a powerful and lightweight clipboard translation tool powered by local Large Language Models (LLMs) via Ollama. Designed to seamlessly integrate into daily workflows, TransPaste automatically detects text copied to the clipboard and replaces it with a high-quality translation in the target language.
16
+
17
+ ## Project Background
18
+
19
+ In the contemporary globalized digital environment, the necessity for rapid and accurate translation is ubiquitous. Traditional translation workflows frequently involve a tedious process of copying text, navigating to a translation website or application, pasting the text, awaiting the result, copying the translation, and finally returning to the original application to paste it. This persistent context switching disrupts focus and diminishes productivity. Furthermore, numerous online translation services necessitate transmitting sensitive data to cloud servers, precipitating significant privacy concerns for professionals handling confidential documents or personal communications.
20
+
21
+ TransPaste was conceived to address these two critical issues: workflow friction and data privacy. By leveraging the capabilities of local LLMs such as `gemma3:1b` and `qwen3:0.6b` through Ollama, TransPaste ensures that data never leaves the local machine. The translation process occurs entirely on local hardware, providing assurance regarding data security. Additionally, by automating the "translate-and-replace" mechanism directly within the clipboard, TransPaste eliminates the necessity for manual context switching. Users can simply copy text in one language and immediately paste it in another, rendering cross-lingual communication as natural as native typing. This project represents a progression towards more integrated, private, and efficient AI-assisted productivity tools.
22
+
23
+ ## Application Scenarios
24
+
25
+ TransPaste is versatile and applicable in numerous scenarios characterized by language barriers.
26
+
27
+ 1. **Cross-Border E-Commerce & Customer Support**: Support agents frequently need to communicate with customers in multiple languages. TransPaste facilitates the copying of a customer's query for instant comprehension, or the drafting of a response in a native language followed by the pasting of a translated version directly into the chat window, significantly accelerating response times.
28
+ 2. **Software Development**: Developers often encounter documentation, error messages, or code comments in languages not fluently spoken. With TransPaste, error logs in languages such as Japanese or Chinese can be copied and the English explanation pasted into notes or search engines, streamlining the debugging process. It also assists in variable naming by translating concepts into English identifiers.
29
+ 3. **Academic Research & Reading**: Researchers reviewing international papers can copy paragraphs of foreign text and paste the translation into summary notes. This fluid workflow encourages deeper engagement with international sources without the distraction of constant tab-switching.
30
+ 4. **Language Learning**: Language learners can utilize TransPaste to verify understanding. By copying a written sentence and pasting it back, the AI translation can be observed, or conversely, a foreign sentence can be copied to obtain an instant translation, reinforcing vocabulary and grammar knowledge in real-time.
31
+
32
+ ## Compatible Hardware
33
+
34
+ Since TransPaste relies on local LLM inference provided by Ollama, hardware requirements are primarily dictated by the chosen model.
35
+
36
+ * **Processor (CPU)**: A modern multi-core processor (Intel Core i5/i7/i9 or AMD Ryzen 5/7/9) is recommended. While Ollama can operate on CPU only, performance scales significantly with superior CPU clock speeds and core counts, particularly for quantized models.
37
+ * **Graphics Card (GPU)**: For the optimal experience, a dedicated NVIDIA GPU with CUDA support is highly recommended. A GPU with at least 4GB of VRAM can comfortably execute smaller models like `gemma3:1b` or `qwen3:0.6b`. For larger models (7B parameter and above), 8GB to 16GB of VRAM is advisable to ensure near-instantaneous translations.
38
+ * **Memory (RAM)**: System memory is crucial, especially if running models on the CPU or if the model size exceeds the GPU's VRAM. A minimum of 8GB RAM is required for basic operation with small models. 16GB or 32GB is recommended for smoother multitasking, ensuring that the translation process does not impede other active applications.
39
+ * **Storage**: An SSD (Solid State Drive) is strongly recommended over an HDD. Loading models into memory necessitates rapid read speeds. Sufficient disk space is required to store the models themselves; small models may occupy 1-2GB, while larger, higher-quality models can consume 5GB to 20GB or more.
40
+
41
+ ## Operating System
42
+
43
+ TransPaste is constructed using Python and the PySide6 framework (Qt for Python), rendering it inherently cross-platform.
44
+
45
+ * **Windows**: The application is fully tested and optimized for Windows 10 and Windows 11. It integrates seamlessly with the Windows system tray and clipboard subsystem. The provided screenshots and instructions are based on the Windows environment, ensuring a native aesthetic and experience.
46
+ * **Linux**: Linux users (specifically Ubuntu 24.04) can also operate TransPaste. The application forces the use of the XCB plugin to ensure compatibility with clipboard operations, even on Wayland-based systems (via XWayland).
47
+ * **Requirements**: Ensure `libxcb` and related libraries are installed. On Ubuntu:
48
+ ```bash
49
+ sudo apt install libxcb-cursor0 libxcb-xinerama0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xkb1 libxkbcommon-x11-0
50
+ ```
51
+ * This ensures the PySide6 application can launch and interact with the system tray and clipboard correctly.
52
+
53
+ ## Dependencies
54
+
55
+ To execute TransPaste successfully, several software components and Python libraries must be installed and configured on the system.
56
+
57
+ 1. **Python 3.10+**: The core application is written in Python. A relatively recent version of Python is required. Python 3.10 or newer is recommended to ensure compatibility with the latest type hinting features and library optimizations.
58
+ 2. **Ollama**: This serves as the backend engine powering the translations. Ollama must be downloaded and installed from [ollama.com](https://ollama.com). Ollama acts as a local server hosting the LLMs and exposing an API to which TransPaste connects. At least one model (e.g., `ollama pull gemma3:1b`) must be pulled for the application to function.
59
+ 3. **PySide6**: This library provides the graphical user interface (GUI) bindings for the Qt framework. It allows TransPaste to create the system tray icon, menus, and efficiently handle system-level clipboard events. It is a robust and mature framework for desktop application development.
60
+ 4. **Requests**: A simple yet powerful HTTP library for Python. TransPaste utilizes `requests` to communicate with the local Ollama API server, handling the transmission of prompts and the reception of generated translations.
61
+ 5. **Regex (re)**: A built-in Python module utilized for post-processing text to ensure clean output by stripping unnecessary quotes or conversational filler from the LLM's response.
62
+
63
+ ## Installation Process
64
+
65
+ Follow these steps to set up TransPaste on a local machine.
66
+
67
+ 1. **Install Ollama**:
68
+ * Visit [ollama.com](https://ollama.com) and download the installer for the operating system.
69
+ * Run the installer and adhere to the on-screen instructions.
70
+ * Open a terminal or command prompt and execute `ollama run gemma3:1b` (or `qwen3:0.6b`) to download and verify the model is functioning. Maintain the Ollama service running in the background.
71
+
72
+ 2. **Clone the Repository**:
73
+ * Open a terminal.
74
+ * Navigate to the desired directory for the project.
75
+ * Execute: `git clone https://github.com/CodeOfMe/TransPaste.git`
76
+ * Enter the directory: `cd TransPaste`
77
+
78
+ 3. **Set Up Python Environment**:
79
+ * (Optional but recommended) Create a virtual environment: `python -m venv venv`
80
+ * Activate the virtual environment:
81
+ * Windows: `venv\Scripts\activate`
82
+ * Linux: `source venv/bin/activate`
83
+
84
+ 4. **Install Dependencies**:
85
+ * Since TransPaste is a Python package, installation is simple via pip:
86
+ ```bash
87
+ pip install .
88
+ ```
89
+ * Or, if installing from PyPI (once published):
90
+ ```bash
91
+ pip install transpaste
92
+ ```
93
+
94
+ 5. **Run the Application**:
95
+ * Execute the command: `transpaste`
96
+ * A clipboard icon should appear in the system tray, indicating that TransPaste is active.
97
+ * Command line options are also available:
98
+ ```bash
99
+ transpaste --model qwen3:0.6b --target French
100
+ ```
101
+
102
+ ## Running Screenshots
103
+
104
+ Below are screenshots demonstrating the usage and configuration of TransPaste.
105
+
106
+ ### 1. Enable/Disable Toggle
107
+ This feature provides a quick way to pause translation without exiting the application. When disabled, the clipboard contents remain untouched, allowing for standard copy-paste operations.
108
+
109
+ ![Enable/Disable Toggle](images/2-启用开关.png)
110
+
111
+ ### 2. Source Language Selection
112
+ Right-click the system tray icon to access the menu. Under "Source Language," the language of the text being copied can be selected. "Auto Detect" is recommended for general use, allowing the model to infer the source language automatically.
113
+
114
+ ![Source Language Selection](images/0-原始语言选择.png)
115
+
116
+ ### 3. Target Language Selection
117
+ This menu permits the definition of the target language for translation. By default, it is set to English, but switching to Chinese, Japanese, French, and many others is easily accomplished depending on immediate requirements.
118
+
119
+ ![Target Language Selection](images/1-目标语言选择.png)
120
+
121
+ ### 4. Model Selection
122
+ TransPaste allows the selection of the local LLM to be utilized for translation. This menu dynamically populates based on the models available in Ollama. Switching between models like `gemma3:1b` or `qwen3:0.6b` can be performed instantly.
123
+
124
+ ![Model Selection](images/3-模型选择.png)
125
+
126
+ ## Authorization Agreement
127
+
128
+ TransPaste is free and open-source software licensed under the **GNU General Public License v3.0 (GPLv3)**.
129
+
130
+ This software is provided with the freedom to use, study, share, and modify. Redistribution and modification are permitted under the terms of the GPLv3, ensuring the software remains free and open for the community.
@@ -0,0 +1,118 @@
1
+ # TransPaste
2
+
3
+ TransPaste is a powerful and lightweight clipboard translation tool powered by local Large Language Models (LLMs) via Ollama. Designed to seamlessly integrate into daily workflows, TransPaste automatically detects text copied to the clipboard and replaces it with a high-quality translation in the target language.
4
+
5
+ ## Project Background
6
+
7
+ In the contemporary globalized digital environment, the necessity for rapid and accurate translation is ubiquitous. Traditional translation workflows frequently involve a tedious process of copying text, navigating to a translation website or application, pasting the text, awaiting the result, copying the translation, and finally returning to the original application to paste it. This persistent context switching disrupts focus and diminishes productivity. Furthermore, numerous online translation services necessitate transmitting sensitive data to cloud servers, precipitating significant privacy concerns for professionals handling confidential documents or personal communications.
8
+
9
+ TransPaste was conceived to address these two critical issues: workflow friction and data privacy. By leveraging the capabilities of local LLMs such as `gemma3:1b` and `qwen3:0.6b` through Ollama, TransPaste ensures that data never leaves the local machine. The translation process occurs entirely on local hardware, providing assurance regarding data security. Additionally, by automating the "translate-and-replace" mechanism directly within the clipboard, TransPaste eliminates the necessity for manual context switching. Users can simply copy text in one language and immediately paste it in another, rendering cross-lingual communication as natural as native typing. This project represents a progression towards more integrated, private, and efficient AI-assisted productivity tools.
10
+
11
+ ## Application Scenarios
12
+
13
+ TransPaste is versatile and applicable in numerous scenarios characterized by language barriers.
14
+
15
+ 1. **Cross-Border E-Commerce & Customer Support**: Support agents frequently need to communicate with customers in multiple languages. TransPaste facilitates the copying of a customer's query for instant comprehension, or the drafting of a response in a native language followed by the pasting of a translated version directly into the chat window, significantly accelerating response times.
16
+ 2. **Software Development**: Developers often encounter documentation, error messages, or code comments in languages not fluently spoken. With TransPaste, error logs in languages such as Japanese or Chinese can be copied and the English explanation pasted into notes or search engines, streamlining the debugging process. It also assists in variable naming by translating concepts into English identifiers.
17
+ 3. **Academic Research & Reading**: Researchers reviewing international papers can copy paragraphs of foreign text and paste the translation into summary notes. This fluid workflow encourages deeper engagement with international sources without the distraction of constant tab-switching.
18
+ 4. **Language Learning**: Language learners can utilize TransPaste to verify understanding. By copying a written sentence and pasting it back, the AI translation can be observed, or conversely, a foreign sentence can be copied to obtain an instant translation, reinforcing vocabulary and grammar knowledge in real-time.
19
+
20
+ ## Compatible Hardware
21
+
22
+ Since TransPaste relies on local LLM inference provided by Ollama, hardware requirements are primarily dictated by the chosen model.
23
+
24
+ * **Processor (CPU)**: A modern multi-core processor (Intel Core i5/i7/i9 or AMD Ryzen 5/7/9) is recommended. While Ollama can operate on CPU only, performance scales significantly with superior CPU clock speeds and core counts, particularly for quantized models.
25
+ * **Graphics Card (GPU)**: For the optimal experience, a dedicated NVIDIA GPU with CUDA support is highly recommended. A GPU with at least 4GB of VRAM can comfortably execute smaller models like `gemma3:1b` or `qwen3:0.6b`. For larger models (7B parameter and above), 8GB to 16GB of VRAM is advisable to ensure near-instantaneous translations.
26
+ * **Memory (RAM)**: System memory is crucial, especially if running models on the CPU or if the model size exceeds the GPU's VRAM. A minimum of 8GB RAM is required for basic operation with small models. 16GB or 32GB is recommended for smoother multitasking, ensuring that the translation process does not impede other active applications.
27
+ * **Storage**: An SSD (Solid State Drive) is strongly recommended over an HDD. Loading models into memory necessitates rapid read speeds. Sufficient disk space is required to store the models themselves; small models may occupy 1-2GB, while larger, higher-quality models can consume 5GB to 20GB or more.
28
+
29
+ ## Operating System
30
+
31
+ TransPaste is constructed using Python and the PySide6 framework (Qt for Python), rendering it inherently cross-platform.
32
+
33
+ * **Windows**: The application is fully tested and optimized for Windows 10 and Windows 11. It integrates seamlessly with the Windows system tray and clipboard subsystem. The provided screenshots and instructions are based on the Windows environment, ensuring a native aesthetic and experience.
34
+ * **Linux**: Linux users (specifically Ubuntu 24.04) can also operate TransPaste. The application forces the use of the XCB plugin to ensure compatibility with clipboard operations, even on Wayland-based systems (via XWayland).
35
+ * **Requirements**: Ensure `libxcb` and related libraries are installed. On Ubuntu:
36
+ ```bash
37
+ sudo apt install libxcb-cursor0 libxcb-xinerama0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xkb1 libxkbcommon-x11-0
38
+ ```
39
+ * This ensures the PySide6 application can launch and interact with the system tray and clipboard correctly.
40
+
41
+ ## Dependencies
42
+
43
+ To execute TransPaste successfully, several software components and Python libraries must be installed and configured on the system.
44
+
45
+ 1. **Python 3.10+**: The core application is written in Python. A relatively recent version of Python is required. Python 3.10 or newer is recommended to ensure compatibility with the latest type hinting features and library optimizations.
46
+ 2. **Ollama**: This serves as the backend engine powering the translations. Ollama must be downloaded and installed from [ollama.com](https://ollama.com). Ollama acts as a local server hosting the LLMs and exposing an API to which TransPaste connects. At least one model (e.g., `ollama pull gemma3:1b`) must be pulled for the application to function.
47
+ 3. **PySide6**: This library provides the graphical user interface (GUI) bindings for the Qt framework. It allows TransPaste to create the system tray icon, menus, and efficiently handle system-level clipboard events. It is a robust and mature framework for desktop application development.
48
+ 4. **Requests**: A simple yet powerful HTTP library for Python. TransPaste utilizes `requests` to communicate with the local Ollama API server, handling the transmission of prompts and the reception of generated translations.
49
+ 5. **Regex (re)**: A built-in Python module utilized for post-processing text to ensure clean output by stripping unnecessary quotes or conversational filler from the LLM's response.
50
+
51
+ ## Installation Process
52
+
53
+ Follow these steps to set up TransPaste on a local machine.
54
+
55
+ 1. **Install Ollama**:
56
+ * Visit [ollama.com](https://ollama.com) and download the installer for the operating system.
57
+ * Run the installer and adhere to the on-screen instructions.
58
+ * Open a terminal or command prompt and execute `ollama run gemma3:1b` (or `qwen3:0.6b`) to download and verify the model is functioning. Maintain the Ollama service running in the background.
59
+
60
+ 2. **Clone the Repository**:
61
+ * Open a terminal.
62
+ * Navigate to the desired directory for the project.
63
+ * Execute: `git clone https://github.com/CodeOfMe/TransPaste.git`
64
+ * Enter the directory: `cd TransPaste`
65
+
66
+ 3. **Set Up Python Environment**:
67
+ * (Optional but recommended) Create a virtual environment: `python -m venv venv`
68
+ * Activate the virtual environment:
69
+ * Windows: `venv\Scripts\activate`
70
+ * Linux: `source venv/bin/activate`
71
+
72
+ 4. **Install Dependencies**:
73
+ * Since TransPaste is a Python package, installation is simple via pip:
74
+ ```bash
75
+ pip install .
76
+ ```
77
+ * Or, if installing from PyPI (once published):
78
+ ```bash
79
+ pip install transpaste
80
+ ```
81
+
82
+ 5. **Run the Application**:
83
+ * Execute the command: `transpaste`
84
+ * A clipboard icon should appear in the system tray, indicating that TransPaste is active.
85
+ * Command line options are also available:
86
+ ```bash
87
+ transpaste --model qwen3:0.6b --target French
88
+ ```
89
+
90
+ ## Running Screenshots
91
+
92
+ Below are screenshots demonstrating the usage and configuration of TransPaste.
93
+
94
+ ### 1. Enable/Disable Toggle
95
+ This feature provides a quick way to pause translation without exiting the application. When disabled, the clipboard contents remain untouched, allowing for standard copy-paste operations.
96
+
97
+ ![Enable/Disable Toggle](images/2-启用开关.png)
98
+
99
+ ### 2. Source Language Selection
100
+ Right-click the system tray icon to access the menu. Under "Source Language," the language of the text being copied can be selected. "Auto Detect" is recommended for general use, allowing the model to infer the source language automatically.
101
+
102
+ ![Source Language Selection](images/0-原始语言选择.png)
103
+
104
+ ### 3. Target Language Selection
105
+ This menu permits the definition of the target language for translation. By default, it is set to English, but switching to Chinese, Japanese, French, and many others is easily accomplished depending on immediate requirements.
106
+
107
+ ![Target Language Selection](images/1-目标语言选择.png)
108
+
109
+ ### 4. Model Selection
110
+ TransPaste allows the selection of the local LLM to be utilized for translation. This menu dynamically populates based on the models available in Ollama. Switching between models like `gemma3:1b` or `qwen3:0.6b` can be performed instantly.
111
+
112
+ ![Model Selection](images/3-模型选择.png)
113
+
114
+ ## Authorization Agreement
115
+
116
+ TransPaste is free and open-source software licensed under the **GNU General Public License v3.0 (GPLv3)**.
117
+
118
+ This software is provided with the freedom to use, study, share, and modify. Redistribution and modification are permitted under the terms of the GPLv3, ensuring the software remains free and open for the community.
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "transpaste"
7
+ version = "0.1.0"
8
+ description = "A local LLM-based clipboard translator"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "GPL-3.0"}
12
+ authors = [
13
+ {name = "CodeOfMe", email = "wedonotuse@outlook.com"}
14
+ ]
15
+ dependencies = [
16
+ "PySide6",
17
+ "requests",
18
+ ]
19
+
20
+ [project.scripts]
21
+ transpaste = "transpaste.main:main"
22
+
23
+ [project.urls]
24
+ "Homepage" = "https://github.com/CodeOfMe/TransPaste"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ from .main import main
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ __all__ = ["main"]
@@ -0,0 +1,371 @@
1
+ import sys
2
+ import time
3
+ import requests
4
+ import json
5
+ import re
6
+ import os
7
+ import argparse
8
+ from PySide6.QtWidgets import QApplication, QSystemTrayIcon, QMenu, QMessageBox
9
+ from PySide6.QtGui import QIcon, QClipboard, QAction
10
+ from PySide6.QtCore import QObject, QThread, Signal, Slot, QTimer
11
+
12
+ # -----------------------------------------------------------------------------
13
+ # Configuration
14
+ # -----------------------------------------------------------------------------
15
+ OLLAMA_API_URL = "http://localhost:11434/api/generate"
16
+ OLLAMA_TAGS_URL = "http://localhost:11434/api/tags"
17
+ DEFAULT_MODEL = "gemma3:1b"
18
+ TIMEOUT_SECONDS = 120
19
+
20
+ # Force XCB on Linux to ensure clipboard access (XWayland compatibility)
21
+ if sys.platform.startswith("linux"):
22
+ os.environ["QT_QPA_PLATFORM"] = "xcb"
23
+
24
+ # A subset of common languages for the menu.
25
+ LANGUAGE_MAP = {
26
+ "Auto Detect": "auto",
27
+ "English": "en",
28
+ "Chinese (Simplified)": "zh-Hans",
29
+ "Chinese (Traditional)": "zh-Hant",
30
+ "Japanese": "ja",
31
+ "Korean": "ko",
32
+ "French": "fr",
33
+ "German": "de",
34
+ "Spanish": "es",
35
+ "Russian": "ru",
36
+ "Italian": "it",
37
+ "Portuguese": "pt",
38
+ }
39
+
40
+ PROMPT_TEMPLATE = """You are a professional {SOURCE_LANG} ({SOURCE_CODE}) to {TARGET_LANG} ({TARGET_CODE}) translator. Your goal is to accurately convey the meaning and nuances of the original {SOURCE_LANG} text while adhering to {TARGET_LANG} grammar, vocabulary, and cultural sensitivities.
41
+ Produce only the {TARGET_LANG} translation, without any additional explanations, notes, or commentary. Do not repeat the original text. Do not say "Here is the translation".
42
+
43
+ Please translate the following {SOURCE_LANG} text into {TARGET_LANG}:
44
+
45
+
46
+ {TEXT}"""
47
+
48
+
49
+ # -----------------------------------------------------------------------------
50
+ # Worker Thread for API Calls
51
+ # -----------------------------------------------------------------------------
52
+ class TranslatorWorker(QThread):
53
+ finished = Signal(str, str) # Emits (original_text, translated_text)
54
+ error = Signal(str)
55
+
56
+ def __init__(self, text, source_lang, target_lang, model):
57
+ super().__init__()
58
+ self.text = text
59
+ self.source_lang = source_lang
60
+ self.target_lang = target_lang
61
+ self.model = model
62
+
63
+ def run(self):
64
+ try:
65
+ # Prepare the prompt
66
+ source_name = self.source_lang
67
+ source_code = LANGUAGE_MAP.get(self.source_lang, "auto")
68
+ target_name = self.target_lang
69
+ target_code = LANGUAGE_MAP.get(self.target_lang, "en")
70
+
71
+ if source_code == "auto":
72
+ source_name = "Source Language"
73
+ source_code = "auto"
74
+
75
+ prompt = PROMPT_TEMPLATE.format(
76
+ SOURCE_LANG=source_name,
77
+ SOURCE_CODE=source_code,
78
+ TARGET_LANG=target_name,
79
+ TARGET_CODE=target_code,
80
+ TEXT=self.text
81
+ )
82
+
83
+ # Call Ollama
84
+ payload = {
85
+ "model": self.model,
86
+ "prompt": prompt,
87
+ "stream": False,
88
+ "options": {
89
+ "temperature": 0.3,
90
+ }
91
+ }
92
+
93
+ response = requests.post(OLLAMA_API_URL, json=payload, timeout=TIMEOUT_SECONDS)
94
+ response.raise_for_status()
95
+
96
+ result = response.json()
97
+ translated_text = result.get("response", "").strip()
98
+
99
+ # --- Post-processing ---
100
+ if translated_text:
101
+ # 1. Remove common prefixes
102
+ prefixes = [
103
+ r"^Here is the translation.*?:",
104
+ r"^Here's the translation.*?:",
105
+ r"^Sure, here is the translation.*?:",
106
+ r"^Translation:",
107
+ r"^Translated text:",
108
+ ]
109
+ for p in prefixes:
110
+ translated_text = re.sub(p, "", translated_text, flags=re.IGNORECASE | re.MULTILINE).strip()
111
+
112
+ # 2. Smart Quote Handling
113
+ original_has_quotes = (
114
+ (self.text.strip().startswith('"') and self.text.strip().endswith('"')) or
115
+ (self.text.strip().startswith("'") and self.text.strip().endswith("'"))
116
+ )
117
+
118
+ if not original_has_quotes:
119
+ if translated_text.startswith('"') and translated_text.endswith('"'):
120
+ translated_text = translated_text[1:-1].strip()
121
+ elif translated_text.startswith("'") and translated_text.endswith("'"):
122
+ translated_text = translated_text[1:-1].strip()
123
+
124
+ # 3. Remove Markdown code blocks if wrapped
125
+ code_block_pattern = r"^```(?:\w+)?\s*(.*?)\s*```$"
126
+ match = re.search(code_block_pattern, translated_text, re.DOTALL)
127
+ if match:
128
+ translated_text = match.group(1).strip()
129
+
130
+ self.finished.emit(self.text, translated_text)
131
+ else:
132
+ self.error.emit("Empty response from Ollama")
133
+
134
+ except requests.exceptions.ReadTimeout:
135
+ self.error.emit(f"Timeout after {TIMEOUT_SECONDS}s. The model took too long.")
136
+ except Exception as e:
137
+ self.error.emit(str(e))
138
+
139
+
140
+ # -----------------------------------------------------------------------------
141
+ # Main Application Logic
142
+ # -----------------------------------------------------------------------------
143
+ class ClipboardTranslator(QObject):
144
+ def __init__(self, initial_model=DEFAULT_MODEL, initial_source="Auto Detect", initial_target="English"):
145
+ super().__init__()
146
+ self.app = QApplication.instance()
147
+ self.clipboard = self.app.clipboard()
148
+
149
+ # State
150
+ self.is_enabled = True
151
+ self.current_source_lang = initial_source
152
+ self.current_target_lang = initial_target
153
+ self.current_model = initial_model
154
+ self.available_models = [initial_model]
155
+ self.last_clipboard_text = ""
156
+ self.ignore_next_change = False
157
+ self.translator_thread = None
158
+
159
+ # Fetch models
160
+ self.fetch_available_models()
161
+
162
+ # Setup System Tray
163
+ # Try to use a standard icon if theme icon fails, but theme is best for integration
164
+ self.tray_icon = QSystemTrayIcon(QIcon.fromTheme("edit-copy"), self.app)
165
+ if self.tray_icon.icon().isNull():
166
+ # Fallback: create a simple pixmap or use another standard icon
167
+ self.tray_icon.setIcon(QIcon.fromTheme("application-x-executable"))
168
+
169
+ self.tray_icon.setToolTip(f"TransPaste (Model: {self.current_model})")
170
+
171
+ # Setup Menu
172
+ self.menu = QMenu()
173
+ self.setup_menu()
174
+ self.tray_icon.setContextMenu(self.menu)
175
+ self.tray_icon.show()
176
+
177
+ # Connect Clipboard Signal
178
+ self.clipboard.dataChanged.connect(self.on_clipboard_changed)
179
+
180
+ # Wayland Polling Fallback (1s interval)
181
+ if sys.platform.startswith("linux"):
182
+ self.poll_timer = QTimer(self)
183
+ self.poll_timer.timeout.connect(self.process_clipboard)
184
+ self.poll_timer.start(1000)
185
+
186
+ # Notification
187
+ self.tray_icon.showMessage(
188
+ "TransPaste Started",
189
+ f"Model: {self.current_model}\nTarget: {self.current_target_lang}",
190
+ QSystemTrayIcon.Information,
191
+ 3000
192
+ )
193
+
194
+ def setup_menu(self):
195
+ self.menu.clear()
196
+
197
+ # Status Action
198
+ status_action = QAction("Status: Enabled" if self.is_enabled else "Status: Disabled", self.menu)
199
+ status_action.setCheckable(True)
200
+ status_action.setChecked(self.is_enabled)
201
+ status_action.triggered.connect(self.toggle_enabled)
202
+ self.menu.addAction(status_action)
203
+
204
+ self.menu.addSeparator()
205
+
206
+ # Source Language Menu
207
+ source_menu = self.menu.addMenu("Source Language")
208
+ for lang in LANGUAGE_MAP.keys():
209
+ action = QAction(lang, self.menu)
210
+ action.setCheckable(True)
211
+ action.setChecked(lang == self.current_source_lang)
212
+ action.triggered.connect(lambda checked, l=lang: self.set_source_lang(l))
213
+ source_menu.addAction(action)
214
+
215
+ # Target Language Menu
216
+ target_menu = self.menu.addMenu("Target Language")
217
+ for lang in LANGUAGE_MAP.keys():
218
+ if lang == "Auto Detect": continue
219
+ action = QAction(lang, self.menu)
220
+ action.setCheckable(True)
221
+ action.setChecked(lang == self.current_target_lang)
222
+ action.triggered.connect(lambda checked, l=lang: self.set_target_lang(l))
223
+ target_menu.addAction(action)
224
+
225
+ self.menu.addSeparator()
226
+
227
+ # Model Selection Menu
228
+ model_menu = self.menu.addMenu("Model")
229
+ for model in self.available_models:
230
+ action = QAction(model, self.menu)
231
+ action.setCheckable(True)
232
+ action.setChecked(model == self.current_model)
233
+ action.triggered.connect(lambda checked, m=model: self.set_model(m))
234
+ model_menu.addAction(action)
235
+
236
+ # Refresh Models Action
237
+ refresh_action = QAction("Refresh Models", self.menu)
238
+ refresh_action.triggered.connect(self.refresh_models)
239
+ model_menu.addSeparator()
240
+ model_menu.addAction(refresh_action)
241
+
242
+ self.menu.addSeparator()
243
+
244
+ # Quit Action
245
+ quit_action = QAction("Quit", self.menu)
246
+ quit_action.triggered.connect(self.app.quit)
247
+ self.menu.addAction(quit_action)
248
+
249
+ def toggle_enabled(self):
250
+ self.is_enabled = not self.is_enabled
251
+ self.setup_menu()
252
+ msg = "Translation Enabled" if self.is_enabled else "Translation Disabled"
253
+ self.tray_icon.showMessage("TransPaste", msg, QSystemTrayIcon.Information, 2000)
254
+
255
+ def set_source_lang(self, lang):
256
+ self.current_source_lang = lang
257
+ self.setup_menu()
258
+
259
+ def set_target_lang(self, lang):
260
+ self.current_target_lang = lang
261
+ self.setup_menu()
262
+
263
+ def set_model(self, model):
264
+ self.current_model = model
265
+ self.setup_menu()
266
+ self.tray_icon.setToolTip(f"TransPaste (Model: {self.current_model})")
267
+ print(f"Model switched to: {model}")
268
+
269
+ def fetch_available_models(self):
270
+ try:
271
+ response = requests.get(OLLAMA_TAGS_URL, timeout=2)
272
+ if response.status_code == 200:
273
+ data = response.json()
274
+ models = [m["name"] for m in data.get("models", [])]
275
+ if models:
276
+ self.available_models = sorted(list(set(models)))
277
+ if self.current_model not in self.available_models:
278
+ # Keep current even if not in list, or fallback
279
+ if DEFAULT_MODEL in self.available_models:
280
+ self.available_models.append(self.current_model)
281
+ self.available_models.sort()
282
+ except Exception as e:
283
+ print(f"Failed to fetch models: {e}")
284
+
285
+ def refresh_models(self):
286
+ self.fetch_available_models()
287
+ self.setup_menu()
288
+ self.tray_icon.showMessage("Models Refreshed", f"Found {len(self.available_models)} models.", QSystemTrayIcon.Information, 2000)
289
+
290
+ def on_clipboard_changed(self):
291
+ if not self.is_enabled:
292
+ return
293
+ QTimer.singleShot(100, self.process_clipboard)
294
+
295
+ def process_clipboard(self):
296
+ if self.ignore_next_change:
297
+ self.ignore_next_change = False
298
+ return
299
+
300
+ text = self.clipboard.text()
301
+ if not text or text.strip() == "":
302
+ return
303
+
304
+ if text == self.last_clipboard_text:
305
+ return
306
+
307
+ print(f"Detected copy: {text[:20]}...")
308
+
309
+ if self.translator_thread and self.translator_thread.isRunning():
310
+ try:
311
+ self.translator_thread.finished.disconnect(self.on_translation_finished)
312
+ self.translator_thread.error.disconnect(self.on_translation_error)
313
+ self.translator_thread.terminate()
314
+ self.translator_thread.wait()
315
+ except Exception:
316
+ pass
317
+
318
+ self.translator_thread = TranslatorWorker(
319
+ text,
320
+ self.current_source_lang,
321
+ self.current_target_lang,
322
+ self.current_model
323
+ )
324
+ self.translator_thread.finished.connect(self.on_translation_finished)
325
+ self.translator_thread.error.connect(self.on_translation_error)
326
+ self.translator_thread.start()
327
+
328
+ def on_translation_finished(self, original_text, translated_text):
329
+ print(f"Translation finished: {translated_text[:20]}...")
330
+
331
+ self.ignore_next_change = True
332
+ self.last_clipboard_text = translated_text
333
+ self.clipboard.setText(translated_text)
334
+
335
+ self.tray_icon.showMessage(
336
+ "Translated",
337
+ f"Result copied to clipboard.\n{translated_text[:50]}...",
338
+ QSystemTrayIcon.Information,
339
+ 2000
340
+ )
341
+
342
+ def on_translation_error(self, error_msg):
343
+ print(f"Translation Error: {error_msg}")
344
+ self.tray_icon.showMessage(
345
+ "Translation Failed",
346
+ f"Error: {error_msg}",
347
+ QSystemTrayIcon.Warning,
348
+ 3000
349
+ )
350
+
351
+ def main():
352
+ parser = argparse.ArgumentParser(description="TransPaste: Local LLM Clipboard Translator")
353
+ parser.add_argument("--model", type=str, default=DEFAULT_MODEL, help="Ollama model to use (default: gemma3:1b)")
354
+ parser.add_argument("--source", type=str, default="Auto Detect", help="Source language (default: Auto Detect)")
355
+ parser.add_argument("--target", type=str, default="English", help="Target language (default: English)")
356
+
357
+ args = parser.parse_args()
358
+
359
+ app = QApplication(sys.argv)
360
+ app.setQuitOnLastWindowClosed(False)
361
+
362
+ translator = ClipboardTranslator(
363
+ initial_model=args.model,
364
+ initial_source=args.source,
365
+ initial_target=args.target
366
+ )
367
+
368
+ sys.exit(app.exec())
369
+
370
+ if __name__ == "__main__":
371
+ main()
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: transpaste
3
+ Version: 0.1.0
4
+ Summary: A local LLM-based clipboard translator
5
+ Author-email: CodeOfMe <wedonotuse@outlook.com>
6
+ License: GPL-3.0
7
+ Project-URL: Homepage, https://github.com/CodeOfMe/TransPaste
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: PySide6
11
+ Requires-Dist: requests
12
+
13
+ # TransPaste
14
+
15
+ TransPaste is a powerful and lightweight clipboard translation tool powered by local Large Language Models (LLMs) via Ollama. Designed to seamlessly integrate into daily workflows, TransPaste automatically detects text copied to the clipboard and replaces it with a high-quality translation in the target language.
16
+
17
+ ## Project Background
18
+
19
+ In the contemporary globalized digital environment, the necessity for rapid and accurate translation is ubiquitous. Traditional translation workflows frequently involve a tedious process of copying text, navigating to a translation website or application, pasting the text, awaiting the result, copying the translation, and finally returning to the original application to paste it. This persistent context switching disrupts focus and diminishes productivity. Furthermore, numerous online translation services necessitate transmitting sensitive data to cloud servers, precipitating significant privacy concerns for professionals handling confidential documents or personal communications.
20
+
21
+ TransPaste was conceived to address these two critical issues: workflow friction and data privacy. By leveraging the capabilities of local LLMs such as `gemma3:1b` and `qwen3:0.6b` through Ollama, TransPaste ensures that data never leaves the local machine. The translation process occurs entirely on local hardware, providing assurance regarding data security. Additionally, by automating the "translate-and-replace" mechanism directly within the clipboard, TransPaste eliminates the necessity for manual context switching. Users can simply copy text in one language and immediately paste it in another, rendering cross-lingual communication as natural as native typing. This project represents a progression towards more integrated, private, and efficient AI-assisted productivity tools.
22
+
23
+ ## Application Scenarios
24
+
25
+ TransPaste is versatile and applicable in numerous scenarios characterized by language barriers.
26
+
27
+ 1. **Cross-Border E-Commerce & Customer Support**: Support agents frequently need to communicate with customers in multiple languages. TransPaste facilitates the copying of a customer's query for instant comprehension, or the drafting of a response in a native language followed by the pasting of a translated version directly into the chat window, significantly accelerating response times.
28
+ 2. **Software Development**: Developers often encounter documentation, error messages, or code comments in languages not fluently spoken. With TransPaste, error logs in languages such as Japanese or Chinese can be copied and the English explanation pasted into notes or search engines, streamlining the debugging process. It also assists in variable naming by translating concepts into English identifiers.
29
+ 3. **Academic Research & Reading**: Researchers reviewing international papers can copy paragraphs of foreign text and paste the translation into summary notes. This fluid workflow encourages deeper engagement with international sources without the distraction of constant tab-switching.
30
+ 4. **Language Learning**: Language learners can utilize TransPaste to verify understanding. By copying a written sentence and pasting it back, the AI translation can be observed, or conversely, a foreign sentence can be copied to obtain an instant translation, reinforcing vocabulary and grammar knowledge in real-time.
31
+
32
+ ## Compatible Hardware
33
+
34
+ Since TransPaste relies on local LLM inference provided by Ollama, hardware requirements are primarily dictated by the chosen model.
35
+
36
+ * **Processor (CPU)**: A modern multi-core processor (Intel Core i5/i7/i9 or AMD Ryzen 5/7/9) is recommended. While Ollama can operate on CPU only, performance scales significantly with superior CPU clock speeds and core counts, particularly for quantized models.
37
+ * **Graphics Card (GPU)**: For the optimal experience, a dedicated NVIDIA GPU with CUDA support is highly recommended. A GPU with at least 4GB of VRAM can comfortably execute smaller models like `gemma3:1b` or `qwen3:0.6b`. For larger models (7B parameter and above), 8GB to 16GB of VRAM is advisable to ensure near-instantaneous translations.
38
+ * **Memory (RAM)**: System memory is crucial, especially if running models on the CPU or if the model size exceeds the GPU's VRAM. A minimum of 8GB RAM is required for basic operation with small models. 16GB or 32GB is recommended for smoother multitasking, ensuring that the translation process does not impede other active applications.
39
+ * **Storage**: An SSD (Solid State Drive) is strongly recommended over an HDD. Loading models into memory necessitates rapid read speeds. Sufficient disk space is required to store the models themselves; small models may occupy 1-2GB, while larger, higher-quality models can consume 5GB to 20GB or more.
40
+
41
+ ## Operating System
42
+
43
+ TransPaste is constructed using Python and the PySide6 framework (Qt for Python), rendering it inherently cross-platform.
44
+
45
+ * **Windows**: The application is fully tested and optimized for Windows 10 and Windows 11. It integrates seamlessly with the Windows system tray and clipboard subsystem. The provided screenshots and instructions are based on the Windows environment, ensuring a native aesthetic and experience.
46
+ * **Linux**: Linux users (specifically Ubuntu 24.04) can also operate TransPaste. The application forces the use of the XCB plugin to ensure compatibility with clipboard operations, even on Wayland-based systems (via XWayland).
47
+ * **Requirements**: Ensure `libxcb` and related libraries are installed. On Ubuntu:
48
+ ```bash
49
+ sudo apt install libxcb-cursor0 libxcb-xinerama0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xkb1 libxkbcommon-x11-0
50
+ ```
51
+ * This ensures the PySide6 application can launch and interact with the system tray and clipboard correctly.
52
+
53
+ ## Dependencies
54
+
55
+ To execute TransPaste successfully, several software components and Python libraries must be installed and configured on the system.
56
+
57
+ 1. **Python 3.10+**: The core application is written in Python. A relatively recent version of Python is required. Python 3.10 or newer is recommended to ensure compatibility with the latest type hinting features and library optimizations.
58
+ 2. **Ollama**: This serves as the backend engine powering the translations. Ollama must be downloaded and installed from [ollama.com](https://ollama.com). Ollama acts as a local server hosting the LLMs and exposing an API to which TransPaste connects. At least one model (e.g., `ollama pull gemma3:1b`) must be pulled for the application to function.
59
+ 3. **PySide6**: This library provides the graphical user interface (GUI) bindings for the Qt framework. It allows TransPaste to create the system tray icon, menus, and efficiently handle system-level clipboard events. It is a robust and mature framework for desktop application development.
60
+ 4. **Requests**: A simple yet powerful HTTP library for Python. TransPaste utilizes `requests` to communicate with the local Ollama API server, handling the transmission of prompts and the reception of generated translations.
61
+ 5. **Regex (re)**: A built-in Python module utilized for post-processing text to ensure clean output by stripping unnecessary quotes or conversational filler from the LLM's response.
62
+
63
+ ## Installation Process
64
+
65
+ Follow these steps to set up TransPaste on a local machine.
66
+
67
+ 1. **Install Ollama**:
68
+ * Visit [ollama.com](https://ollama.com) and download the installer for the operating system.
69
+ * Run the installer and adhere to the on-screen instructions.
70
+ * Open a terminal or command prompt and execute `ollama run gemma3:1b` (or `qwen3:0.6b`) to download and verify the model is functioning. Maintain the Ollama service running in the background.
71
+
72
+ 2. **Clone the Repository**:
73
+ * Open a terminal.
74
+ * Navigate to the desired directory for the project.
75
+ * Execute: `git clone https://github.com/CodeOfMe/TransPaste.git`
76
+ * Enter the directory: `cd TransPaste`
77
+
78
+ 3. **Set Up Python Environment**:
79
+ * (Optional but recommended) Create a virtual environment: `python -m venv venv`
80
+ * Activate the virtual environment:
81
+ * Windows: `venv\Scripts\activate`
82
+ * Linux: `source venv/bin/activate`
83
+
84
+ 4. **Install Dependencies**:
85
+ * Since TransPaste is a Python package, installation is simple via pip:
86
+ ```bash
87
+ pip install .
88
+ ```
89
+ * Or, if installing from PyPI (once published):
90
+ ```bash
91
+ pip install transpaste
92
+ ```
93
+
94
+ 5. **Run the Application**:
95
+ * Execute the command: `transpaste`
96
+ * A clipboard icon should appear in the system tray, indicating that TransPaste is active.
97
+ * Command line options are also available:
98
+ ```bash
99
+ transpaste --model qwen3:0.6b --target French
100
+ ```
101
+
102
+ ## Running Screenshots
103
+
104
+ Below are screenshots demonstrating the usage and configuration of TransPaste.
105
+
106
+ ### 1. Enable/Disable Toggle
107
+ This feature provides a quick way to pause translation without exiting the application. When disabled, the clipboard contents remain untouched, allowing for standard copy-paste operations.
108
+
109
+ ![Enable/Disable Toggle](images/2-启用开关.png)
110
+
111
+ ### 2. Source Language Selection
112
+ Right-click the system tray icon to access the menu. Under "Source Language," the language of the text being copied can be selected. "Auto Detect" is recommended for general use, allowing the model to infer the source language automatically.
113
+
114
+ ![Source Language Selection](images/0-原始语言选择.png)
115
+
116
+ ### 3. Target Language Selection
117
+ This menu permits the definition of the target language for translation. By default, it is set to English, but switching to Chinese, Japanese, French, and many others is easily accomplished depending on immediate requirements.
118
+
119
+ ![Target Language Selection](images/1-目标语言选择.png)
120
+
121
+ ### 4. Model Selection
122
+ TransPaste allows the selection of the local LLM to be utilized for translation. This menu dynamically populates based on the models available in Ollama. Switching between models like `gemma3:1b` or `qwen3:0.6b` can be performed instantly.
123
+
124
+ ![Model Selection](images/3-模型选择.png)
125
+
126
+ ## Authorization Agreement
127
+
128
+ TransPaste is free and open-source software licensed under the **GNU General Public License v3.0 (GPLv3)**.
129
+
130
+ This software is provided with the freedom to use, study, share, and modify. Redistribution and modification are permitted under the terms of the GPLv3, ensuring the software remains free and open for the community.
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/transpaste/__init__.py
4
+ src/transpaste/main.py
5
+ src/transpaste.egg-info/PKG-INFO
6
+ src/transpaste.egg-info/SOURCES.txt
7
+ src/transpaste.egg-info/dependency_links.txt
8
+ src/transpaste.egg-info/entry_points.txt
9
+ src/transpaste.egg-info/requires.txt
10
+ src/transpaste.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ transpaste = transpaste.main:main
@@ -0,0 +1,2 @@
1
+ PySide6
2
+ requests
@@ -0,0 +1 @@
1
+ transpaste