diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 6ddcd46..8901264 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -4,6 +4,17 @@ on:
push:
tags:
- 'v*'
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Manual build version tag (e.g. v2.7.5.dev0)'
+ required: false
+ default: 'v2.7.5.dev0'
+ publish_pypi:
+ description: 'Publish to PyPI during manual test?'
+ type: boolean
+ required: false
+ default: false
env:
PROJECT_NAME: qpypack
@@ -28,8 +39,8 @@ jobs:
- name: Checkout source code
uses: actions/checkout@v4
with:
- ref: main
- fetch-depth: 0
+ ref: ${{ github.ref }}
+ fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
@@ -42,33 +53,20 @@ jobs:
import re
import os
- tag = "${{ github.ref_name }}"
+ tag = "${{ inputs.version || github.ref_name }}"
version = tag[1:] if tag.lower().startswith('v') else tag
- print(f"Target version to sync: {version}")
toml_path = 'pyproject.toml'
- if not os.path.exists(toml_path):
- raise FileNotFoundError(f"Missing critical configuration: {toml_path}")
-
- with open(toml_path, 'r', encoding='utf-8') as f:
- content = f.read()
- new_content = re.sub(r'(version\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1)
- with open(toml_path, 'w', encoding='utf-8') as f:
- f.write(new_content)
- print("Successfully synchronized pyproject.toml.")
+ if os.path.exists(toml_path):
+ with open(toml_path, 'r', encoding='utf-8') as f: content = f.read()
+ new_content = re.sub(r'(version\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1)
+ with open(toml_path, 'w', encoding='utf-8') as f: f.write(new_content)
main_path = os.environ['MAIN_SCRIPT']
- if not os.path.exists(main_path):
- raise FileNotFoundError(f"Missing critical entrypoint: {main_path}")
-
- with open(main_path, 'r', encoding='utf-8') as f:
- content = f.read()
- new_content = re.sub(r'(__version__\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1)
- with open(main_path, 'w', encoding='utf-8') as f:
- f.write(new_content)
- print(f"Successfully synchronized {main_path}.")
-
- # 已删除原有 git commit & git push 步骤(避免产生多余 Commit)
+ if os.path.exists(main_path):
+ with open(main_path, 'r', encoding='utf-8') as f: content = f.read()
+ new_content = re.sub(r'(__version__\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1)
+ with open(main_path, 'w', encoding='utf-8') as f: f.write(new_content)
- name: Install build dependencies
if: env.BUILD_PIP_PACKAGE == 'true'
@@ -88,37 +86,33 @@ jobs:
dist/*.whl
dist/*.tar.gz
generate_release_notes: true
+ tag_name: ${{ inputs.version || github.ref_name }}
+ prerelease: ${{ contains(inputs.version || github.ref_name, 'dev') || contains(inputs.version || github.ref_name, 'rc') || contains(inputs.version || github.ref_name, 'alpha') || contains(inputs.version || github.ref_name, 'beta') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to PyPI
- if: env.BUILD_PIP_PACKAGE == 'true' && env.PUBLISH_TO_PYPI == 'true'
+ if: env.BUILD_PIP_PACKAGE == 'true' && env.PUBLISH_TO_PYPI == 'true' && (github.event_name == 'push' || inputs.publish_pypi == true)
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
build-binaries:
name: Build Standalone for ${{ matrix.os }} (${{ matrix.arch }})
- needs: publish-pypi
+ needs: publish-pypi
runs-on: ${{ matrix.os }}
permissions:
- contents: write
+ contents: write
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
arch: x64
- artifact_name: QPyPack.exe
- package_extension: zip
- os: macos-14
- arch: arm64
- artifact_name: QPyPack.app
- package_extension: zip
- - os: ubuntu-latest
+ arch: arm64
+ - os: ubuntu-22.04
arch: x64
- artifact_name: QPyPack
- package_extension: tar.gz
steps:
- name: Checkout source code
@@ -133,11 +127,10 @@ jobs:
- name: Extract version
shell: bash
run: |
- TAG_NAME=${{ github.ref_name }}
+ TAG_NAME="${{ inputs.version || github.ref_name }}"
VERSION=${TAG_NAME#v}
echo "VERSION=$VERSION" >> $GITHUB_ENV
- # 确保编译二进制文件前,main.py 中的 __version__ 也被同步为 Tag 版本
- name: Sync version to main.py
shell: python
run: |
@@ -145,84 +138,63 @@ jobs:
import os
version = os.environ['VERSION']
main_path = os.environ['MAIN_SCRIPT']
- with open(main_path, 'r', encoding='utf-8') as f:
- content = f.read()
+ with open(main_path, 'r', encoding='utf-8') as f: content = f.read()
new_content = re.sub(r'(__version__\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1)
- with open(main_path, 'w', encoding='utf-8') as f:
- f.write(new_content)
-
- - name: Generate Windows Version Info File
- if: runner.os == 'Windows'
- shell: python
- run: |
- import os
- import re
-
- version = os.environ['VERSION']
- parts = re.findall(r'\d+', version)
- v_num = (parts + ['0', '0', '0', '0'])[:4]
- v_tuple = ",".join(v_num)
- print(f"Windows FileVersion tuple parsed: ({v_tuple})")
-
- info_content = f"""
- VSVersionInfo(
- ffi=FixedFileInfo(
- filevers=({v_tuple}),
- prodvers=({v_tuple}),
- mask=0x3f,
- flags=0x0,
- OS=0x40004,
- fileType=0x1,
- subtype=0x0,
- date=(0,0)
- ),
- kids=[
- StringFileInfo(
- [
- StringTable(
- '040904B0',
- [
- StringStruct('CompanyName', '${{ env.COMPANY_NAME }}'),
- StringStruct('FileDescription', '${{ env.FILE_DESCRIPTION }}'),
- StringStruct('FileVersion', '{version}'),
- StringStruct('InternalName', '${{ env.EXE_NAME_PREFIX }}'),
- StringStruct('LegalCopyright', '${{ env.LEGAL_COPYRIGHT }}'),
- StringStruct('OriginalFilename', '${{ env.EXE_NAME_PREFIX }}.exe'),
- StringStruct('ProductName', '${{ env.PRODUCT_NAME }}'),
- StringStruct('ProductVersion', '{version}')
- ]
- )
- ]
- ),
- VarFileInfo([VarStruct('Translation', [1033, 1200])])
- ]
- )
- """
- with open('file_version_info.txt', 'w', encoding='utf-8') as f:
- f.write(info_content.strip())
+ with open(main_path, 'w', encoding='utf-8') as f: f.write(new_content)
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install PySide6 Pillow pyinstaller
- - name: Build with PyInstaller (Windows with Version Info)
- if: runner.os == 'Windows'
+ - name: Convert ICO to ICNS (macOS Only)
+ if: runner.os == 'macOS'
+ shell: python
run: |
- pyinstaller --clean --onefile --noconsole --version-file=file_version_info.txt --icon=${{ env.ICON_PATH }} --add-data "${{ env.ICON_PATH }};." --add-data "qpypack/locales;locales" --name="${{ env.EXE_NAME_PREFIX }}_Standalone" ${{ env.MAIN_SCRIPT }}
-
- pyinstaller --clean --onedir --noconsole --version-file=file_version_info.txt --icon=${{ env.ICON_PATH }} --add-data "${{ env.ICON_PATH }};." --add-data "qpypack/locales;locales" --name="${{ env.EXE_NAME_PREFIX }}_Portable" ${{ env.MAIN_SCRIPT }}
+ import os
+ from PIL import Image
+ img = Image.open(os.environ['ICON_PATH'])
+ icns_path = 'qpypack/icon.icns'
+ img.save(icns_path, format='ICNS')
+ with open(os.environ['GITHUB_ENV'], 'a') as f:
+ f.write(f"MAC_ICON_PATH={icns_path}\n")
- - name: Build with PyInstaller (macOS / Linux)
- if: runner.os != 'Windows'
+ - name: Generate Windows Version Info File
+ if: runner.os == 'Windows'
+ shell: python
+ run: |
+ import os, re
+ version = os.environ['VERSION']
+ parts = re.findall(r'\d+', version)
+ v_tuple = ",".join((parts + ['0', '0', '0', '0'])[:4])
+ info_content = f"""
+ VSVersionInfo(
+ ffi=FixedFileInfo(filevers=({v_tuple}),prodvers=({v_tuple}),mask=0x3f,flags=0x0,OS=0x40004,fileType=0x1,subtype=0x0,date=(0,0)),
+ kids=[
+ StringFileInfo([StringTable('040904B0',[StringStruct('CompanyName', '${{ env.COMPANY_NAME }}'),StringStruct('FileDescription', '${{ env.FILE_DESCRIPTION }}'),StringStruct('FileVersion', '{version}'),StringStruct('InternalName', '${{ env.EXE_NAME_PREFIX }}'),StringStruct('LegalCopyright', '${{ env.LEGAL_COPYRIGHT }}'),StringStruct('OriginalFilename', '${{ env.EXE_NAME_PREFIX }}.exe'),StringStruct('ProductName', '${{ env.PRODUCT_NAME }}'),StringStruct('ProductVersion', '{version}')])]),
+ VarFileInfo([VarStruct('Translation', [1033, 1200])])
+ ]
+ )
+ """
+ with open('file_version_info.txt', 'w', encoding='utf-8') as f: f.write(info_content.strip())
+
+ - name: Build with PyInstaller (All Platforms)
shell: bash
run: |
- if [ "${{ runner.os }}" = "macOS" ]; then
- pyinstaller --onefile --noconsole --name="${{ env.EXE_NAME_PREFIX }}_Standalone" --icon=${{ env.ICON_PATH }} --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
- pyinstaller --onedir --noconsole --name="${{ env.EXE_NAME_PREFIX }}_Portable" --icon=${{ env.ICON_PATH }} --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
+ if [ "${{ runner.os }}" = "Windows" ]; then
+ pyinstaller --clean --onefile --noconsole --version-file=file_version_info.txt --icon=${{ env.ICON_PATH }} --add-data "${{ env.ICON_PATH }};." --add-data "qpypack/locales;locales" --name="${{ env.EXE_NAME_PREFIX }}_Standalone" ${{ env.MAIN_SCRIPT }}
+ pyinstaller --clean --onedir --noconsole --version-file=file_version_info.txt --icon=${{ env.ICON_PATH }} --add-data "${{ env.ICON_PATH }};." --add-data "qpypack/locales;locales" --name="${{ env.EXE_NAME_PREFIX }}_Portable" ${{ env.MAIN_SCRIPT }}
+ elif [ "${{ runner.os }}" = "macOS" ]; then
+ pyinstaller --clean --onedir --noconsole --name="${{ env.EXE_NAME_PREFIX }}" --icon=${{ env.MAC_ICON_PATH }} --add-data "${{ env.ICON_PATH }}:." --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
+ codesign --force --deep --sign - dist/${{ env.EXE_NAME_PREFIX }}.app
else
- pyinstaller --onefile --noconsole --name="${{ env.EXE_NAME_PREFIX }}_Standalone" --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
- pyinstaller --onedir --noconsole --name="${{ env.EXE_NAME_PREFIX }}_Portable" --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
+ PYSIDE_PLUGINS=$(python -c "import PySide6, os; print(os.path.join(os.path.dirname(PySide6.__file__), 'Qt', 'plugins'))")
+ mkdir -p qt_plugins
+ cp -r "$PYSIDE_PLUGINS/platforms" qt_plugins/
+ cp -r "$PYSIDE_PLUGINS/wayland"* qt_plugins/ 2>/dev/null || true
+
+ pyinstaller --clean --noupx --onefile --noconsole --name="${{ env.EXE_NAME_PREFIX }}_Standalone" --icon=${{ env.ICON_PATH }} --add-data "${{ env.ICON_PATH }}:." --add-data "qt_plugins:PySide6/Qt/plugins" --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
+ pyinstaller --clean --noupx --onedir --noconsole --name="${{ env.EXE_NAME_PREFIX }}_Portable" --icon=${{ env.ICON_PATH }} --add-data "${{ env.ICON_PATH }}:." --add-data "qt_plugins:PySide6/Qt/plugins" --add-data "qpypack/locales:locales" ${{ env.MAIN_SCRIPT }}
fi
- name: Package Artifact (Windows)
@@ -230,39 +202,32 @@ jobs:
shell: pwsh
run: |
$BASE_NAME = "${{ env.EXE_NAME_PREFIX }}-${{ env.VERSION }}-windows-${{ matrix.arch }}"
-
Compress-Archive -Path "dist/${{ env.EXE_NAME_PREFIX }}_Standalone.exe" -DestinationPath "$BASE_NAME-Standalone.zip" -Force
-
Compress-Archive -Path "dist/${{ env.EXE_NAME_PREFIX }}_Portable" -DestinationPath "$BASE_NAME-Portable.zip" -Force
- name: Package Artifact (macOS / Linux)
if: runner.os != 'Windows'
shell: bash
run: |
- VERSION=${{ env.VERSION }}
OS_NAME=$(echo "${{ runner.os }}" | tr '[:upper:]' '[:lower:]')
- BASE_NAME="${{ env.EXE_NAME_PREFIX }}-${VERSION}-${OS_NAME}-${{ matrix.arch }}"
cd dist
-
if [ "${{ runner.os }}" = "macOS" ]; then
- TARGET_STANDALONE="${{ env.EXE_NAME_PREFIX }}_Standalone.app"
- TARGET_PORTABLE="${{ env.EXE_NAME_PREFIX }}_Portable.app"
+ BASE_NAME="${{ env.EXE_NAME_PREFIX }}-${{ env.VERSION }}-${OS_NAME}-${{ matrix.arch }}"
+ mkdir -p dmg_staging
+ mv "${{ env.EXE_NAME_PREFIX }}.app" dmg_staging/
+ ln -s /Applications dmg_staging/Applications
+ hdiutil create -volname "${{ env.EXE_NAME_PREFIX }}" -srcfolder dmg_staging -ov -format UDZO "../${BASE_NAME}.dmg"
else
- TARGET_STANDALONE="${{ env.EXE_NAME_PREFIX }}_Standalone"
- TARGET_PORTABLE="${{ env.EXE_NAME_PREFIX }}_Portable"
- fi
-
- if [ "${{ matrix.package_extension }}" = "zip" ]; then
- zip -r "../${BASE_NAME}-Standalone.zip" "$TARGET_STANDALONE"
- zip -r "../${BASE_NAME}-Portable.zip" "$TARGET_PORTABLE"
- else
- tar -czf "../${BASE_NAME}-Standalone.tar.gz" "$TARGET_STANDALONE"
- tar -czf "../${BASE_NAME}-Portable.tar.gz" "$TARGET_PORTABLE"
+ BASE_NAME="${{ env.EXE_NAME_PREFIX }}-${{ env.VERSION }}-${OS_NAME}-${{ matrix.arch }}"
+ tar -czf "../${BASE_NAME}-Standalone.tar.gz" "${{ env.EXE_NAME_PREFIX }}_Standalone"
+ tar -czf "../${BASE_NAME}-Portable.tar.gz" "${{ env.EXE_NAME_PREFIX }}_Portable"
fi
- name: Append Standalone Binary to GitHub Release
uses: softprops/action-gh-release@v2
with:
- files: ${{ env.EXE_NAME_PREFIX }}-*.*
+ files: ${{ env.EXE_NAME_PREFIX }}-*.*
+ tag_name: ${{ inputs.version || github.ref_name }}
+ prerelease: ${{ contains(inputs.version || github.ref_name, 'dev') || contains(inputs.version || github.ref_name, 'rc') || contains(inputs.version || github.ref_name, 'alpha') || contains(inputs.version || github.ref_name, 'beta') }}
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e278247..3f4b1b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,24 @@ QPyPack 项目的所有重要变更都将记录在此文件中。
---
+## [2.7.5] - 2026-08-06
+
+#### 新增
+- **代码签名与时间戳**:新增 Windows / macOS 产物自动数字签名功能,支持 `.pfx` 自签名证书生成与商业证书配置;Windows 签名集成微软、DigiCert、Sectigo 等权威时间戳服务器盖章支持。
+- **macOS DMG 构建**:CI/CD 构建流程支持自动生成 macOS 平台的 `.dmg` 安装包镜像。
+
+#### 改进
+- **macOS 默认签名**:macOS 平台默认开启 Ad-hoc 伪签名,解决 M 系列芯片上未签名二进制运行报“应用已损坏”的问题。
+- **跨平台构建打包**:重构 CI/CD 自动化构建流程,优化 Linux 平台 PySide6 插件依赖打包与稳定性。
+- **系统兼容性矩阵**:调整解释器检测逻辑,动态评估并展示各操作系统与架构的兼容性要求。
+- **界面与文案优化**:统一跨平台文件选择框渲染机制;默认开发者更名为“独立开发者”,应用描述更名为“桌面应用程序”。
+
+#### 修复
+- **多语言与国际化同步**:补全并同步简体/繁体中文、日、韩、德、法、西、葡、俄等 8+ 种语言的签名日志与文本框右键菜单翻译。
+- **进程资源回收**:优化打包任务异常终止时的进程管道与句柄清理逻辑。
+
+---
+
## [2.7.4] - 2026-08-05
#### 新增
diff --git a/CHANGELOG_EN.md b/CHANGELOG_EN.md
index ef6e65b..aa9382c 100644
--- a/CHANGELOG_EN.md
+++ b/CHANGELOG_EN.md
@@ -9,6 +9,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---
+## [2.7.5] - 2026-08-06
+
+#### Added
+- **Code Signing & Timestamping**: Added automatic digital signing for Windows / macOS build artifacts, supporting `.pfx` self-signed certificate generation and commercial certificate configuration; integrated timestamp server (TSA) stamping for Windows signatures with support for authoritative providers like Microsoft, DigiCert, and Sectigo.
+- **macOS DMG Building**: CI/CD build workflows now support automatically generating `.dmg` installer images for macOS.
+
+#### Improved
+- **macOS Default Signing**: Enabled Ad-hoc signing by default on macOS, resolving the "App is damaged and can't be opened" error when running unsigned binaries on M-series Apple Silicon chips.
+- **Cross-Platform Packaging**: Refactored CI/CD automated build workflows, optimizing PySide6 plugin dependency bundling and stability on Linux.
+- **OS Support Matrix**: Adjusted interpreter detection logic to dynamically evaluate and display compatibility requirements across operating systems and architectures.
+- **UI & Copywriting Enhancements**: Unified cross-platform file dialog rendering mechanics; updated default author to "Independent Developer" and app description to "Desktop Application".
+
+#### Fixed
+- **Localization & i18n Sync**: Completed and synchronized signature log entries and text box context menu translations across 8+ languages (Simplified/Traditional Chinese, Japanese, Korean, German, French, Spanish, Portuguese, Russian, etc.).
+- **Process Resource Cleanup**: Optimized process pipe and handle cleanup logic when packaging tasks terminate abnormally.
+
+---
+
## [2.7.4] - 2026-08-05
#### Added
diff --git a/qpypack/locales/de_DE.json b/qpypack/locales/de_DE.json
index 78595be..19d8444 100644
--- a/qpypack/locales/de_DE.json
+++ b/qpypack/locales/de_DE.json
@@ -18,7 +18,6 @@
"Engine": "Engine",
"Dependencies": "Abhängigkeiten",
"Resources": "Ressourcen",
- "Optimization": "Optimierung",
"Package Map": "Paket-Zuordnung",
"Execution Log": "Ausführungsprotokoll",
"Loaded: {filename}": "Geladen: {filename}",
@@ -79,7 +78,6 @@
"Output Location": "Ausgabeort der Anwendung",
"Preferences & System Behavior": "Einstellungen & Systemverhalten",
"Build Engine:": "Build-Engine:",
- "Python Interpreter:": "Python-Interpreter:",
"Output Name:": "Name der Ausgabedatei:",
"App Icon:": "Anwendungssymbol:",
"Primary PIP Index:": "Primärer PIP-Spiegelserver:",
@@ -139,7 +137,6 @@
"
Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} Unterstützung:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Vollständige Abwärtskompatibilität",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} Unterstützung:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} Unterstützung:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Automatische Erkennung und Verwaltung des C-Backend-Compilers",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Python Interpreter
Automatische Systemerkennung...",
"[INFO] Build Cancelled.": "[INFO] Build abgebrochen.",
"[INFO] Performing pre-flight environment checks...": "[INFO] Führe Vorab-Umgebungsprüfungen durch...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] Analysiere Quellcode und Abhängigkeiten...",
@@ -274,8 +271,6 @@
"One-Click Install": "Ein-Klick-Installation",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] Python-Installation fehlgeschlagen oder abgebrochen.",
"System Default ({sys_native})": "Systemstandard ({sys_native})",
- "My Studio": "My Studio",
- "Python Executable": "Python-Ausführbare",
"Invalid syntax": "Ungültige Syntax",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] Lade Playwright-Browser über Mirror herunter: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] Wiederhole Download der Playwright-Browser über offizielles CDN...",
@@ -291,5 +286,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "Kleinere Ausgabegröße. Empfohlen für 95 % der Standard-Apps.",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "Tipp: Erstellung im Lite-Modus fehlgeschlagen. Versuchen Sie in den [Buildeinstellungen] auf [Kompatibilitätsmodus] zu wechseln.",
"Keep Virtual Environment (Faster Rebuilds)": "Virtuelle Umgebung behalten (Schnellere Rebuilds)",
- "[INFO] Reusing existing virtual environment...": "[INFO] Bestehende virtuelle Umgebung wird wiederverwendet..."
+ "[INFO] Reusing existing virtual environment...": "[INFO] Bestehende virtuelle Umgebung wird wiederverwendet...",
+ "Interpreter:": "Interpreter:",
+ "Optimization & Security": "Optimierung & Sicherheit",
+ "Independent Developer": "Unabhängiger Entwickler",
+ "Desktop Application": "Desktop-Anwendung",
+ "Code Signing": "Code-Signierung",
+ "Enable Smart Code Signing": "Digitale Signatur aktivieren",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "Fügt der Anwendung automatisch eine digitale Signatur hinzu, um Warnungen zu vermeiden.",
+ "Use Custom Commercial Cert (Optional) ▸": "Kommerzielles Zertifikat konfigurieren (Optional) ▸",
+ "Hide Custom Cert Settings ▾": "Zertifikat-Einstellungen ausblenden ▾",
+ "Commercial PFX File:": "Kommerzielle PFX-Datei:",
+ "Cert Password:": "Zertifikatspasswort:",
+ "[INFO] Applying smart digital signature...": "[INFO] Wende digitale Signatur an...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] Digitale Signatur erfolgreich angewendet!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] Signierung fehlgeschlagen, Build-Ergebnis bleibt erhalten.",
+ "Create": "Erstellen",
+ "Create Self-Signed Cert": "Selbstsigniertes Zertifikat erstellen",
+ "Certificate Subject (e.g. My Company):": "Zertifikatsaussteller (z. B. Meine Firma):",
+ "Generate": "Generieren",
+ "Self-Signed Certificate (*.pfx)": "Selbstsigniertes Zertifikat (*.pfx)",
+ "Passwords do not match!": "Passwörter stimmen nicht überein!",
+ "Failed to generate certificate.": "Zertifikatserstellung fehlgeschlagen.",
+ "Certificate generated successfully!": "Zertifikat erfolgreich erstellt!",
+ "Only supported on Windows.": "Nur unter Windows unterstützt.",
+ "Save Certificate": "Zertifikat speichern",
+ "Error": "Fehler",
+ "Select .pfx / .p12 certificate file": ".pfx / .p12 Zertifikatsdatei auswählen",
+ "Certificate password": "Zertifikatspasswort",
+ "Undo": "Rückgängig",
+ "Cut": "Ausschneiden",
+ "Paste": "Einfügen",
+ "QPyPack Developer": "QPyPack-Entwickler",
+ "Password cannot be empty!": "Passwort darf nicht leer sein!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "Empfehlung: 6+ Zeichen, nur alphanumerisch, '-' und '_'. Keine Leerzeichen.",
+ "OS Support Matrix:": "BS-Unterstützungsmatrix:",
+ "Platform Support Matrix:": "Plattform-Unterstützungsmatrix:",
+ "No Windows 7 Support": "Keine Windows 7-Unterstützung",
+ "Full backward compatibility": "Vollständige Abwärtskompatibilität",
+ "Legacy macOS Compatible": "Kompatibel mit älterem macOS",
+ "Apple Silicon (M1/M2) & Intel": "Unterstützt Apple Silicon (M1/M2) & Intel",
+ "Apple Silicon (M-Series) & Intel": "Unterstützt Apple Silicon (M-Serie) & Intel",
+ "Compatibility depends on build environment glibc version.": "Kompatibilität hängt von der glibc-Version ab.",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka verwaltet C-Compiler automatisch",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "Interpreter
Automatische System- und BS-Erkennung...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Zeitstempel-Server Zeitüberschreitung, führe lokale schnelle Signierung durch...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] Digitale Signatur mit Zeitstempel ({tsa}) erfolgreich angewendet..."
}
\ No newline at end of file
diff --git a/qpypack/locales/es_ES.json b/qpypack/locales/es_ES.json
index 7f23ecb..f922f00 100644
--- a/qpypack/locales/es_ES.json
+++ b/qpypack/locales/es_ES.json
@@ -17,7 +17,6 @@
"Engine": "Motor",
"Dependencies": "Dependencias",
"Resources": "Recursos",
- "Optimization": "Optimización",
"Package Map": "Mapeo",
"Execution Log": "Registro de Ejecución",
"Loaded: {filename}": "Cargado: {filename}",
@@ -78,7 +77,6 @@
"Output Location": "Ubicación del archivo ejecutable",
"Preferences & System Behavior": "Preferencias y comportamiento",
"Build Engine:": "Motor de compilación:",
- "Python Interpreter:": "Intérprete de Python:",
"Output Name:": "Nombre del ejecutable:",
"App Icon:": "Icono de la aplicación:",
"Primary PIP Index:": "Índice PIP principal:",
@@ -138,7 +136,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} Soporte:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
SO Heredado Compatibilidad total hacia atrás",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} Soporte:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} Soporte:
✖ Windows 7 ✖ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.13+ ✔ Linux
Nuitka Detectando y gestionando automáticamente el compilador backend C",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Intérprete Python
Detectando automáticamente el entorno del sistema...",
"[INFO] Build Cancelled.": "[INFO] Compilación cancelada.",
"[INFO] Performing pre-flight environment checks...": "[INFO] Realizando controles de seguridad del entorno...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] Analizando el código fuente y las dependencias...",
@@ -274,8 +271,6 @@
"One-Click Install": "Instalación con un clic",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] La instalación de Python falló o fue cancelada.",
"System Default ({sys_native})": "Predeterminado del sistema ({sys_native})",
- "My Studio": "My Studio",
- "Python Executable": "Ejecutable Python",
"Invalid syntax": "Sintaxis no válida",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] Descargando navegadores Playwright vía espejo: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] Reintentando la descarga del navegador Playwright a través del CDN oficial...",
@@ -292,5 +287,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "Menor tamaño de salida. Recomendado para el 95% de las aplicaciones estándar.",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "Consejo: Error al compilar en modo ligero. Intente cambiar a [Modo de compatibilidad] en la configuración y vuelva a compilar.",
"Keep Virtual Environment (Faster Rebuilds)": "Conservar entorno virtual (Reconstrucción más rápida)",
- "[INFO] Reusing existing virtual environment...": "[INFO] Reutilizando el entorno virtual existente..."
-}
+ "[INFO] Reusing existing virtual environment...": "[INFO] Reutilizando el entorno virtual existente...",
+ "Interpreter:": "Intérprete:",
+ "Optimization & Security": "Optimización y Seguridad",
+ "Independent Developer": "Desarrollador independiente",
+ "Desktop Application": "Aplicación de escritorio",
+ "Code Signing": "Firma de código",
+ "Enable Smart Code Signing": "Habilitar firma digital",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "Aplica automáticamente una firma digital a la app creada, eliminando la advertencia de 'Editor desconocido'.",
+ "Use Custom Commercial Cert (Optional) ▸": "Configurar certificado comercial (Opcional) ▸",
+ "Hide Custom Cert Settings ▾": "Ocultar configuración de certificado ▾",
+ "Commercial PFX File:": "Archivo PFX comercial:",
+ "Cert Password:": "Contraseña del certificado:",
+ "[INFO] Applying smart digital signature...": "[INFO] Aplicando firma digital...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] ¡Firma digital aplicada con éxito!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] La firma digital falló, pero el ejecutable se ha conservado.",
+ "Create": "Crear",
+ "Create Self-Signed Cert": "Crear certificado autosignado",
+ "Certificate Subject (e.g. My Company):": "Emisor del certificado (ej. Mi Empresa):",
+ "Generate": "Generar",
+ "Self-Signed Certificate (*.pfx)": "Certificado autosignado (*.pfx)",
+ "Passwords do not match!": "¡Las contraseñas no coinciden!",
+ "Failed to generate certificate.": "Error al generar el certificado.",
+ "Certificate generated successfully!": "¡Certificado generado con éxito!",
+ "Only supported on Windows.": "Solo compatible con Windows.",
+ "Save Certificate": "Guardar certificado",
+ "Error": "Error",
+ "Select .pfx / .p12 certificate file": "Seleccionar archivo de certificado .pfx / .p12",
+ "Certificate password": "Contraseña del certificado",
+ "Undo": "Deshacer",
+ "Cut": "Cortar",
+ "Paste": "Pegar",
+ "QPyPack Developer": "Desarrollador QPyPack",
+ "Password cannot be empty!": "¡La contraseña no puede estar vacía!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "Recomendación: 6+ caracteres, solo alfanuméricos, '-' y '_'. Evite espacios.",
+ "OS Support Matrix:": "Matriz de compatibilidad de SO:",
+ "Platform Support Matrix:": "Matriz de compatibilidad de plataforma:",
+ "No Windows 7 Support": "Sin soporte para Windows 7",
+ "Full backward compatibility": "Compatibilidad total hacia atrás",
+ "Legacy macOS Compatible": "Compatible con macOS heredado",
+ "Apple Silicon (M1/M2) & Intel": "Soporta Apple Silicon (M1/M2) e Intel",
+ "Apple Silicon (M-Series) & Intel": "Soporta Apple Silicon (Serie M) e Intel",
+ "Compatibility depends on build environment glibc version.": "La compatibilidad depende de la versión de glibc del entorno.",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka gestiona automáticamente el compilador C",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "Intérprete
Detectando automáticamente el entorno y la matriz de soporte...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Tiempo de espera del servidor de sellado agotado, realizando firma rápida local...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] Firma digital aplicada con sello de tiempo ({tsa})..."
+}
\ No newline at end of file
diff --git a/qpypack/locales/fr_FR.json b/qpypack/locales/fr_FR.json
index f94e575..9359a0f 100644
--- a/qpypack/locales/fr_FR.json
+++ b/qpypack/locales/fr_FR.json
@@ -18,7 +18,6 @@
"Engine": "Moteur",
"Dependencies": "Dépendances",
"Resources": "Ressources",
- "Optimization": "Optimisation",
"Package Map": "Mappage",
"Execution Log": "Journal d'exécution",
"Loaded: {filename}": "Chargé : {filename}",
@@ -79,7 +78,6 @@
"Output Location": "Emplacement de sortie",
"Preferences & System Behavior": "Préférences et comportement",
"Build Engine:": "Moteur de compilation :",
- "Python Interpreter:": "Interprète Python :",
"Output Name:": "Nom de l'exécutable :",
"App Icon:": "Icône de l'application :",
"Primary PIP Index:": "Index PIP principal :",
@@ -139,7 +137,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Support Python {ver} :
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
OS Hérités Rétrocompatibilité totale",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Support Python {ver} :
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Support Python {ver} :
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Détection et gestion automatiques du compilateur backend C",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Interprète Python
Détection automatique de l'environnement...",
"[INFO] Build Cancelled.": "[INFO] Compilation annulée.",
"[INFO] Performing pre-flight environment checks...": "[INFO] Vérifications de l'environnement en cours...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] Analyse du code source et des dépendances...",
@@ -275,8 +272,6 @@
"One-Click Install": "Installation en un clic",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] L'installation de Python a échoué ou a été annulée.",
"System Default ({sys_native})": "Par défaut ({sys_native})",
- "My Studio": "Mon Studio",
- "Python Executable": "Exécutable Python",
"Invalid syntax": "Syntaxe invalide",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] Téléchargement des navigateurs Playwright via le miroir : {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] Nouvelle tentative de téléchargement du navigateur Playwright via le CDN officiel...",
@@ -293,5 +288,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "Taille de sortie plus petite. Recommandé pour 95 % des applications standard.",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "Conseil : Échec de la compilation en mode léger. Essayez de passer en [Mode de compatibilité] dans les paramètres et recompiler.",
"Keep Virtual Environment (Faster Rebuilds)": "Conserver l'environnement virtuel (Recompilation plus rapide)",
- "[INFO] Reusing existing virtual environment...": "[INFO] Réutilisation de l'environnement virtuel existant..."
-}
+ "[INFO] Reusing existing virtual environment...": "[INFO] Réutilisation de l'environnement virtuel existant...",
+ "Interpreter:": "Interprète :",
+ "Optimization & Security": "Optimisation et Sécurité",
+ "Independent Developer": "Développeur indépendant",
+ "Desktop Application": "Application de bureau",
+ "Code Signing": "Signature de code",
+ "Enable Smart Code Signing": "Activer la signature numérique",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "Applique automatiquement une signature numérique pour éliminer l'avertissement 'Éditeur inconnu'.",
+ "Use Custom Commercial Cert (Optional) ▸": "Configurer un certificat commercial (Optionnel) ▸",
+ "Hide Custom Cert Settings ▾": "Masquer les paramètres du certificat ▾",
+ "Commercial PFX File:": "Fichier PFX commercial :",
+ "Cert Password:": "Mot de passe du certificat :",
+ "[INFO] Applying smart digital signature...": "[INFO] Application de la signature numérique...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] Signature numérique appliquée avec succès !",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] Échec de la signature, mais le produit compilé est conservé.",
+ "Create": "Créer",
+ "Create Self-Signed Cert": "Créer un certificat auto-signé",
+ "Certificate Subject (e.g. My Company):": "Émetteur du certificat (ex : Ma Société) :",
+ "Generate": "Générer",
+ "Self-Signed Certificate (*.pfx)": "Certificat auto-signé (*.pfx)",
+ "Passwords do not match!": "Les mots de passe ne correspondent pas !",
+ "Failed to generate certificate.": "Échec de la génération du certificat.",
+ "Certificate generated successfully!": "Certificat généré avec succès !",
+ "Only supported on Windows.": "Pris en charge uniquement sur Windows.",
+ "Save Certificate": "Enregistrer le certificat",
+ "Error": "Erreur",
+ "Select .pfx / .p12 certificate file": "Sélectionner un fichier de certificat .pfx / .p12",
+ "Certificate password": "Mot de passe du certificat",
+ "Undo": "Annuler",
+ "Cut": "Couper",
+ "Paste": "Coller",
+ "QPyPack Developer": "Développeur QPyPack",
+ "Password cannot be empty!": "Le mot de passe ne peut pas être vide !",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "Recommandation : 6+ caractères, alphanumériques, '-' et '_' uniquement.",
+ "OS Support Matrix:": "Matrice de support des OS :",
+ "Platform Support Matrix:": "Matrice de support des plateformes :",
+ "No Windows 7 Support": "Pas de support Windows 7",
+ "Full backward compatibility": "Rétrocompatibilité totale",
+ "Legacy macOS Compatible": "Compatible anciens macOS",
+ "Apple Silicon (M1/M2) & Intel": "Supporte Apple Silicon (M1/M2) & Intel",
+ "Apple Silicon (M-Series) & Intel": "Supporte Apple Silicon (Série M) & Intel",
+ "Compatibility depends on build environment glibc version.": "La compatibilité dépend de la version glibc de l'environnement.",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka gère automatiquement le compilateur C",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "Interprète
Détection automatique de l'environnement et du support OS...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Délai d'attente du serveur d'horodatage dépassé, signature rapide locale en cours...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] Signature numérique appliquée avec horodatage ({tsa})..."
+}
\ No newline at end of file
diff --git a/qpypack/locales/ja_JP.json b/qpypack/locales/ja_JP.json
index 567fd66..0f9c76b 100644
--- a/qpypack/locales/ja_JP.json
+++ b/qpypack/locales/ja_JP.json
@@ -17,7 +17,6 @@
"Engine": "エンジン",
"Dependencies": "依存関係",
"Resources": "リソース",
- "Optimization": "最適化",
"Package Map": "パッケージマップ",
"Execution Log": "実行ログ",
"Loaded: {filename}": "読み込み済み: {filename}",
@@ -78,7 +77,6 @@
"Output Location": "出力先",
"Preferences & System Behavior": "環境設定と動作",
"Build Engine:": "ビルドエンジン:",
- "Python Interpreter:": "インタープリター:",
"Output Name:": "出力アプリ名:",
"App Icon:": "アプリアイコン:",
"Primary PIP Index:": "メイン PIP インデックス:",
@@ -138,7 +136,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} サポート:
✔ Windows 7 ✔ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux
レガシー OS 完全な後方互換性",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} サポート:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} サポート:
✖ Windows 7 ✖ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.13+ ✔ Linux
Nuitka C バックエンドコンパイラを自動検出して管理",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Python インタープリター
システム環境を自動検出中...",
"[INFO] Build Cancelled.": "[INFO] ビルドがキャンセルされました。",
"[INFO] Performing pre-flight environment checks...": "[INFO] 事前環境チェックを実行中...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] ソースコードと依存関係を解析中...",
@@ -273,8 +270,6 @@
"One-Click Install": "ワンクリックインストール",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] Python のインストールが失敗したか、キャンセルされました。",
"System Default ({sys_native})": "システム既定 ({sys_native})",
- "My Studio": "My Studio",
- "Python Executable": "Python 実行ファイル",
"Invalid syntax": "無効な構文",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] ミラーから Playwright ブラウザーをダウンロード中: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] 公式 CDN 経由で Playwright ブラウザーのダウンロードを再試行中...",
@@ -290,5 +285,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "出力サイズを最小化。一般的なアプリに推奨。",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "ヒント: 軽量モードでのビルドに失敗しました。[ビルド設定] で [互換モード] に切り替えて再ビルドをお試しください。",
"Keep Virtual Environment (Faster Rebuilds)": "仮想環境を保持 (高速再ビルド)",
- "[INFO] Reusing existing virtual environment...": "[INFO] 既存のローカル仮想環境を再利用中..."
+ "[INFO] Reusing existing virtual environment...": "[INFO] 既存のローカル仮想環境を再利用中...",
+ "Interpreter:": "インタープリター:",
+ "Optimization & Security": "最適化とセキュリティ",
+ "Independent Developer": "個人開発者",
+ "Desktop Application": "デスクトップアプリケーション",
+ "Code Signing": "コード署名",
+ "Enable Smart Code Signing": "デジタル署名を有効化",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "生成されたアプリにデジタル署名を自動適用し、「不明な発行元」警告を回避します。",
+ "Use Custom Commercial Cert (Optional) ▸": "商用証明書の設定 (オプション) ▸",
+ "Hide Custom Cert Settings ▾": "証明書の詳細設定を折りたたむ ▾",
+ "Commercial PFX File:": "商用 PFX ファイル:",
+ "Cert Password:": "証明書パスワード:",
+ "[INFO] Applying smart digital signature...": "[INFO] アプリケーションにデジタル署名を適用中...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] デジタル署名が正常に適用されました!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] デジタル署名に失敗しましたが、ビルド成果物は保持されます。",
+ "Create": "作成",
+ "Create Self-Signed Cert": "自己署名証明書の作成",
+ "Certificate Subject (e.g. My Company):": "証明書の発行者 (例: My Company):",
+ "Generate": "生成",
+ "Self-Signed Certificate (*.pfx)": "自己署名証明書 (*.pfx)",
+ "Passwords do not match!": "パスワードが一致しません!",
+ "Failed to generate certificate.": "証明書の生成に失敗しました。",
+ "Certificate generated successfully!": "証明書が正常に生成されました!",
+ "Only supported on Windows.": "Windows 環境でのみサポートされています。",
+ "Save Certificate": "証明書を保存",
+ "Error": "エラー",
+ "Select .pfx / .p12 certificate file": ".pfx / .p12 形式の証明書を選択してください",
+ "Certificate password": "証明書のパスワード",
+ "Undo": "元に戻す",
+ "Cut": "切り取り",
+ "Paste": "貼り付け",
+ "QPyPack Developer": "QPyPack 開発者",
+ "Password cannot be empty!": "パスワードを入力してください!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "推奨: 6文字以上の半角英数字、'-'、'_' のみ。スペースや全角文字は避けてください。",
+ "OS Support Matrix:": "OS サポート状況:",
+ "Platform Support Matrix:": "プラットフォームサポート:",
+ "No Windows 7 Support": "Windows 7 未対応",
+ "Full backward compatibility": "旧 OS 互換",
+ "Legacy macOS Compatible": "旧版 macOS 互換",
+ "Apple Silicon (M1/M2) & Intel": "Apple Silicon (M1/M2) および Intel 対応",
+ "Apple Silicon (M-Series) & Intel": "Apple Silicon (Mシリーズ) および Intel 対応",
+ "Compatibility depends on build environment glibc version.": "互換性は現在のシステムの glibc バージョンに依存します。",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka が C コンパイラを自動管理",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "インタープリター
システム環境と OS サポート状況を自動検出中...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] タイムスタンプサーバー接続タイムアウト。ローカル高速署名を実行します...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] タイムスタンプサーバー ({tsa}) 経由でデジタル署名を適用しました..."
}
\ No newline at end of file
diff --git a/qpypack/locales/ko_KR.json b/qpypack/locales/ko_KR.json
index f1ff4b4..9b0fd69 100644
--- a/qpypack/locales/ko_KR.json
+++ b/qpypack/locales/ko_KR.json
@@ -18,7 +18,6 @@
"Engine": "엔진",
"Dependencies": "의존성",
"Resources": "리소스",
- "Optimization": "최적화",
"Package Map": "패키지 매핑",
"Execution Log": "실행 기록",
"Loaded: {filename}": "로드 완료: {filename}",
@@ -79,7 +78,6 @@
"Output Location": "결과물 출력 위치",
"Preferences & System Behavior": "환경 설정 및 동작",
"Build Engine:": "빌드 엔진:",
- "Python Interpreter:": "Python 인터프리터:",
"Output Name:": "출력 파일 이름:",
"App Icon:": "애플리케이션 아이콘:",
"Primary PIP Index:": "기본 PIP 인덱스:",
@@ -138,7 +136,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} 지원:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
레거시 OS 완벽한 하위 호환성",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} 지원:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} 지원:
✖ Windows 7 ✖ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.13+ ✔ Linux
Nuitka C 백엔드 컴파일러 자동 감지 및 관리 중",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Python 인터프리터
시스템 환경 자동 감지 중...",
"[INFO] Build Cancelled.": "[INFO] 빌드가 취소되었습니다.",
"[INFO] Performing pre-flight environment checks...": "[INFO] 환경 사전 점검 수행 중...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] 소스 코드 및 의존성 분석 중...",
@@ -274,8 +271,6 @@
"One-Click Install": "원클릭 설치",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] Python 설치가 실패했거나 취소되었습니다.",
"System Default ({sys_native})": "시스템 기본값 ({sys_native})",
- "My Studio": "My Studio",
- "Python Executable": "Python 실행 파일",
"Invalid syntax": "잘못된 구문",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] 미러를 통해 Playwright 브라우저를 다운로드하는 중: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] 공식 CDN을 통해 Playwright 브라우저 다운로드를 재시도하는 중...",
@@ -292,5 +287,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "최소 출력 용량. 95%의 일반 앱에 권장.",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "팁: 경량 모드에서 빌드에 실패했습니다. [빌드 설정]에서 [호환 모드]로 전환 후 다시 시도해 보세요.",
"Keep Virtual Environment (Faster Rebuilds)": "가상 환경 유지 (빠른 재빌드)",
- "[INFO] Reusing existing virtual environment...": "[INFO] 기존 로컬 가상 환경 재사용 중..."
+ "[INFO] Reusing existing virtual environment...": "[INFO] 기존 로컬 가상 환경 재사용 중...",
+ "Interpreter:": "인터프리터:",
+ "Optimization & Security": "최적화 및 보안",
+ "Independent Developer": "독립 개발자",
+ "Desktop Application": "데스크톱 애플리케이션",
+ "Code Signing": "코드 서명",
+ "Enable Smart Code Signing": "디지털 서명 활성화",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "생성된 앱에 디지털 서명을 자동으로 적용하여 '알 수 없는 게시자' 경고를 방지합니다.",
+ "Use Custom Commercial Cert (Optional) ▸": "상용 디지털 인증서 구성 (선택 사항) ▸",
+ "Hide Custom Cert Settings ▾": "인증서 고급 설정 접기 ▾",
+ "Commercial PFX File:": "상용 PFX 파일:",
+ "Cert Password:": "인증서 비밀번호:",
+ "[INFO] Applying smart digital signature...": "[INFO] 애플리케이션에 디지털 서명 적용 중...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] 디지털 서명이 성공적으로 적용되었습니다!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] 디지털 서명 실패, 결과물은 정상적으로 보존됩니다.",
+ "Create": "생성",
+ "Create Self-Signed Cert": "자체 서명 인증서 생성",
+ "Certificate Subject (e.g. My Company):": "인증서 발급자 (예: My Company):",
+ "Generate": "생성",
+ "Self-Signed Certificate (*.pfx)": "자체 서명 인증서 (*.pfx)",
+ "Passwords do not match!": "비밀번호가 일치하지 않습니다!",
+ "Failed to generate certificate.": "인증서 생성 실패.",
+ "Certificate generated successfully!": "인증서가 성공적으로 생성되었습니다!",
+ "Only supported on Windows.": "Windows 환경에서만 지원됩니다.",
+ "Save Certificate": "인증서 저장",
+ "Error": "오류",
+ "Select .pfx / .p12 certificate file": ".pfx / .p12 형식의 인증서 파일을 선택하세요",
+ "Certificate password": "인증서 비밀번호",
+ "Undo": "실행 취소",
+ "Cut": "잘라내기",
+ "Paste": "붙여넣기",
+ "QPyPack Developer": "QPyPack 개발자",
+ "Password cannot be empty!": "비밀번호를 입력해야 합니다!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "권장: 6자 이상, 영문자, 숫자, '-' 및 '_'만 사용. 공백이나 특수문자 제외.",
+ "OS Support Matrix:": "OS 지원 현황:",
+ "Platform Support Matrix:": "플랫폼 지원:",
+ "No Windows 7 Support": "Windows 7 미지원",
+ "Full backward compatibility": "구형 OS 호환",
+ "Legacy macOS Compatible": "구형 macOS 호환",
+ "Apple Silicon (M1/M2) & Intel": "Apple Silicon (M1/M2) 및 Intel 지원",
+ "Apple Silicon (M-Series) & Intel": "Apple Silicon (M 시리즈) 및 Intel 지원",
+ "Compatibility depends on build environment glibc version.": "호환성은 현재 시스템의 glibc 버전에 따라 달라집니다.",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka가 C 컴파일러를 자동으로 관리함",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "인터프리터
시스템 환경 및 OS 지원 현황 자동 감지 중...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] 타임스탬프 서버 연결 시간 초과, 로컬 빠른 서명을 진행합니다...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] 타임스탬프 서버({tsa})를 통해 디지털 서명을 완료했습니다..."
}
\ No newline at end of file
diff --git a/qpypack/locales/pt_BR.json b/qpypack/locales/pt_BR.json
index 36a9df3..edb4f34 100644
--- a/qpypack/locales/pt_BR.json
+++ b/qpypack/locales/pt_BR.json
@@ -17,7 +17,6 @@
"Engine": "Motor",
"Dependencies": "Dependências",
"Resources": "Recursos",
- "Optimization": "Otimização",
"Package Map": "Mapeamento",
"Execution Log": "Log de Execução",
"Loaded: {filename}": "Carregado: {filename}",
@@ -78,7 +77,6 @@
"Output Location": "Local de saída",
"Preferences & System Behavior": "Preferências e comportamento",
"Build Engine:": "Motor de compilação:",
- "Python Interpreter:": "Intérprete Python:",
"Output Name:": "Nome do executável:",
"App Icon:": "Ícone do aplicativo:",
"Primary PIP Index:": "Servidor PIP principal:",
@@ -138,7 +136,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} Suporte:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
SO Legado Compatibilidade total",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} Suporte:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} Suporte:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Detectando e gerenciando automaticamente o compilador backend C",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Intérprete Python
Detectando ambiente do sistema...",
"[INFO] Build Cancelled.": "[INFO] Compilação cancelada.",
"[INFO] Performing pre-flight environment checks...": "[INFO] Realizando verificações do ambiente...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] Analisando código fonte e dependências...",
@@ -273,8 +270,6 @@
"One-Click Install": "Instalação com Um Clique",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] A instalação do Python falhou ou foi cancelada.",
"System Default ({sys_native})": "Padrão do Sistema ({sys_native})",
- "My Studio": "My Studio",
- "Python Executable": "Executável Python",
"Invalid syntax": "Sintaxe inválida",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] Baixando navegadores Playwright via espelho: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] Tentando novamente baixar os navegadores Playwright via CDN oficial...",
@@ -290,5 +285,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "Menor tamanho de saída. Recomendado para 95% dos aplicativos padrão.",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "Dica: Falha ao compilar no Modo Leve. Tente alternar para o [Modo de Compatibilidade] nas Configurações e recompilar.",
"Keep Virtual Environment (Faster Rebuilds)": "Manter ambiente virtual (Recompilação mais rápida)",
- "[INFO] Reusing existing virtual environment...": "[INFO] Reutilizando o ambiente virtual existente..."
-}
+ "[INFO] Reusing existing virtual environment...": "[INFO] Reutilizando o ambiente virtual existente...",
+ "Interpreter:": "Intérprete:",
+ "Optimization & Security": "Otimização e Segurança",
+ "Independent Developer": "Desenvolvedor Independente",
+ "Desktop Application": "Aplicativo de Trabalho",
+ "Code Signing": "Assinatura de Código",
+ "Enable Smart Code Signing": "Habilitar Assinatura Digital",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "Aplica automaticamente assinatura digital ao app, eliminando o aviso de 'Editor Desconhecido'.",
+ "Use Custom Commercial Cert (Optional) ▸": "Configurar Certificado Comercial (Opcional) ▸",
+ "Hide Custom Cert Settings ▾": "Ocultar Configurações do Certificado ▾",
+ "Commercial PFX File:": "Arquivo PFX Comercial:",
+ "Cert Password:": "Senha do Certificado:",
+ "[INFO] Applying smart digital signature...": "[INFO] Aplicando assinatura digital...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] Assinatura digital aplicada com sucesso!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] Assinatura digital falhou, mas o executável foi mantido.",
+ "Create": "Criar",
+ "Create Self-Signed Cert": "Criar Certificado Autoassinado",
+ "Certificate Subject (e.g. My Company):": "Emissor do Certificado (ex: Minha Empresa):",
+ "Generate": "Gerar",
+ "Self-Signed Certificate (*.pfx)": "Certificado Autoassinado (*.pfx)",
+ "Passwords do not match!": "As senhas não coincidem!",
+ "Failed to generate certificate.": "Falha ao gerar o certificado.",
+ "Certificate generated successfully!": "Certificado gerado com sucesso!",
+ "Only supported on Windows.": "Suportado apenas no Windows.",
+ "Save Certificate": "Salvar Certificado",
+ "Error": "Erro",
+ "Select .pfx / .p12 certificate file": "Selecionar arquivo de certificado .pfx / .p12",
+ "Certificate password": "Senha do certificado",
+ "Undo": "Desfazer",
+ "Cut": "Recortar",
+ "Paste": "Colar",
+ "QPyPack Developer": "Desenvolvedor QPyPack",
+ "Password cannot be empty!": "A senha não pode estar vazia!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "Recomendação: 6+ caracteres, apenas alfanuméricos, '-' e '_'. Evite espaços.",
+ "OS Support Matrix:": "Matriz de Suporte a SO:",
+ "Platform Support Matrix:": "Matriz de Suporte a Plataforma:",
+ "No Windows 7 Support": "Sem Suporte ao Windows 7",
+ "Full backward compatibility": "Compatibilidade total com versões anteriores",
+ "Legacy macOS Compatible": "Compatível com macOS legado",
+ "Apple Silicon (M1/M2) & Intel": "Suporta Apple Silicon (M1/M2) e Intel",
+ "Apple Silicon (M-Series) & Intel": "Suporta Apple Silicon (Série M) e Intel",
+ "Compatibility depends on build environment glibc version.": "A compatibilidade depende da versão da glibc do ambiente.",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka gerencia o compilador C automaticamente",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "Intérprete
Detectando automaticamente o ambiente e matriz de suporte...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Tempo limite do servidor de carimbo esgotado, realizando assinatura rápida local...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] Assinatura digital aplicada com carimbo de data/hora ({tsa})..."
+}
\ No newline at end of file
diff --git a/qpypack/locales/ru_RU.json b/qpypack/locales/ru_RU.json
index 215a853..b52c521 100644
--- a/qpypack/locales/ru_RU.json
+++ b/qpypack/locales/ru_RU.json
@@ -17,7 +17,6 @@
"Engine": "Движок",
"Dependencies": "Зависимости",
"Resources": "Ресурсы",
- "Optimization": "Оптимизация",
"Package Map": "Сопоставление",
"Execution Log": "Журнал работы",
"Loaded: {filename}": "Загружено: {filename}",
@@ -78,7 +77,6 @@
"Output Location": "Расположение файла",
"Preferences & System Behavior": "Предпочтения и поведение",
"Build Engine:": "Движок сборки:",
- "Python Interpreter:": "Интерпретатор Python:",
"Output Name:": "Имя файла:",
"App Icon:": "Иконка:",
"Primary PIP Index:": "Основное зеркало PIP:",
@@ -138,7 +136,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} Поддержка:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Устаревшая ОС Полная совместимость",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} Поддержка:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} Поддержка:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Автоопределение и управление C-компилятором",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Интерпретатор Python
Автоопределение среды...",
"[INFO] Build Cancelled.": "[INFO] Сборка отменена.",
"[INFO] Performing pre-flight environment checks...": "[INFO] Выполнение проверок среды...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] Анализ исходного кода и зависимостей...",
@@ -274,8 +271,6 @@
"One-Click Install": "Установка в один клик",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] Установка Python не удалась или была отменена.",
"System Default ({sys_native})": "Системный ({sys_native})",
- "My Studio": "My Studio",
- "Python Executable": "Исполняемый файл Python",
"Invalid syntax": "Неверный синтаксис",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] Загрузка браузеров Playwright через зеркало: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] Повторная попытка загрузки браузера Playwright через официальный CDN...",
@@ -291,5 +286,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "Меньший размер файла. Рекомендуется для 95% стандартных приложений.",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "Совет: Сборка в облегченном режиме не удалась. Попробуйте переключиться на [Режим совместимости] в настройках и повторить сборку.",
"Keep Virtual Environment (Faster Rebuilds)": "Сохранять виртуальное окружение (Ускоряет пересборку)",
- "[INFO] Reusing existing virtual environment...": "[INFO] Повторное использование существующего виртуального окружения..."
+ "[INFO] Reusing existing virtual environment...": "[INFO] Повторное использование существующего виртуального окружения...",
+ "Interpreter:": "Интерпретатор:",
+ "Optimization & Security": "Оптимизация и безопасность",
+ "Independent Developer": "Независимый разработчик",
+ "Desktop Application": "Настольное приложение",
+ "Code Signing": "Подпись кода",
+ "Enable Smart Code Signing": "Включить цифровую подпись",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "Автоматически подписывает приложение, устраняя предупреждение о «Неизвестном издателе».",
+ "Use Custom Commercial Cert (Optional) ▸": "Настроить коммерческий сертификат (Опционально) ▸",
+ "Hide Custom Cert Settings ▾": "Скрыть настройки сертификата ▾",
+ "Commercial PFX File:": "Коммерческий файл PFX:",
+ "Cert Password:": "Пароль сертификата:",
+ "[INFO] Applying smart digital signature...": "[INFO] Применение цифровой подписи...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] Цифровая подпись успешно применена!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] Подпись не удалась, но исполняемый файл сохранен.",
+ "Create": "Создать",
+ "Create Self-Signed Cert": "Создать самоподписанный сертификат",
+ "Certificate Subject (e.g. My Company):": "Издатель сертификата (напр. Моя Компания):",
+ "Generate": "Сгенерировать",
+ "Self-Signed Certificate (*.pfx)": "Самоподписанный сертификат (*.pfx)",
+ "Passwords do not match!": "Пароли не совпадают!",
+ "Failed to generate certificate.": "Не удалось сгенерировать сертификат.",
+ "Certificate generated successfully!": "Сертификат успешно сгенерирован!",
+ "Only supported on Windows.": "Поддерживается только в Windows.",
+ "Save Certificate": "Сохранить сертификат",
+ "Error": "Ошибка",
+ "Select .pfx / .p12 certificate file": "Выберите файл сертификата .pfx / .p12",
+ "Certificate password": "Пароль сертификата",
+ "Undo": "Отменить",
+ "Cut": "Вырезать",
+ "Paste": "Вставить",
+ "QPyPack Developer": "Разработчик QPyPack",
+ "Password cannot be empty!": "Пароль не может быть пустым!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "Рекомендация: от 6 символов, только латиница, цифры, '-' и '_'. Без пробелов.",
+ "OS Support Matrix:": "Матрица поддержки ОС:",
+ "Platform Support Matrix:": "Матрица поддержки платформ:",
+ "No Windows 7 Support": "Без поддержки Windows 7",
+ "Full backward compatibility": "Полная обратная совместимость",
+ "Legacy macOS Compatible": "Совместимо со старыми macOS",
+ "Apple Silicon (M1/M2) & Intel": "Поддержка Apple Silicon (M1/M2) и Intel",
+ "Apple Silicon (M-Series) & Intel": "Поддержка Apple Silicon (Серия M) и Intel",
+ "Compatibility depends on build environment glibc version.": "Совместимость зависит от версии glibc среды сборки.",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka автоматически управляет компилятором C",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "Интерпретатор
Автоопределение среды и матрицы поддержки ОС...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Превышено время ожидания сервера штампа времени, выполняется локальная быстрая подпись...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] Цифровая подпись со штампом времени ({tsa}) успешно применена..."
}
\ No newline at end of file
diff --git a/qpypack/locales/zh_TW.json b/qpypack/locales/zh_TW.json
index ff57c98..a63065e 100644
--- a/qpypack/locales/zh_TW.json
+++ b/qpypack/locales/zh_TW.json
@@ -18,7 +18,6 @@
"Engine": "建置引擎",
"Dependencies": "依賴管理",
"Resources": "附加資源",
- "Optimization": "效能優化",
"Package Map": "套件名稱對映",
"Execution Log": "執行日誌",
"Loaded: {filename}": "已載入: {filename}",
@@ -79,7 +78,6 @@
"Output Location": "輸出位置",
"Preferences & System Behavior": "偏好與系統行為",
"Build Engine:": "建置引擎:",
- "Python Interpreter:": "Python 解譯器:",
"Output Name:": "輸出名稱:",
"App Icon:": "應用程式圖示:",
"Primary PIP Index:": "主 PIP 源:",
@@ -139,7 +137,6 @@
"Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility": "Python {ver} 平台支援:
✔ Windows 7 ✔ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux
相容舊系統 支援 Windows 7 及舊版作業系統",
"Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux": "Python {ver} 平台支援:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux",
"Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler": "Python {ver} 平台支援:
✖ Windows 7 ✖ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.13+ ✔ Linux
Nuitka 自動偵測並管理 C 後端編譯器",
- "Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...": "Python 解譯器
自動偵測系統環境 (Win/macOS/Linux)...",
"[INFO] Build Cancelled.": "[INFO] 建置已取消。",
"[INFO] Performing pre-flight environment checks...": "[INFO] 執行環境安全檢查...",
"[INFO] Analyzing source code and project dependencies...": "[INFO] 分析原始碼與依賴...",
@@ -275,8 +272,6 @@
"One-Click Install": "一鍵安裝",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] Python 安裝失敗或已被主動取消。",
"System Default ({sys_native})": "系統預設 ({sys_native})",
- "My Studio": "我的工作室",
- "Python Executable": "Python 執行檔",
"Invalid syntax": "無效語法",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] 透過鏡像下載 Playwright 瀏覽器: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] 透過官方 CDN 重試下載 Playwright 瀏覽器...",
@@ -292,5 +287,50 @@
"Smaller output size. Recommended for 95% of standard apps.": "產物體積最小。推薦 95% 的常規應用程式使用。",
"Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "提示: 精簡模式建置失敗。您可以嘗試在【建置設定】中勾選 [相容模式] 重新打包。",
"Keep Virtual Environment (Faster Rebuilds)": "保留虛擬環境 (加速重編)",
- "[INFO] Reusing existing virtual environment...": "[INFO] 複用本地已存在的虛擬環境..."
+ "[INFO] Reusing existing virtual environment...": "[INFO] 複用本地已存在的虛擬環境...",
+ "Interpreter:": "解譯器:",
+ "Optimization & Security": "效能優化與安全",
+ "Independent Developer": "獨立開發者",
+ "Desktop Application": "桌面應用程式",
+ "Code Signing": "程式碼簽章",
+ "Enable Smart Code Signing": "開啟數位簽章",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "自動為產生的應用程式新增數位簽章,提升系統信任度",
+ "Use Custom Commercial Cert (Optional) ▸": "設定商業數位憑證 (選填) ▸",
+ "Hide Custom Cert Settings ▾": "折疊憑證進階設定 ▾",
+ "Commercial PFX File:": "商業憑證檔案 (.pfx):",
+ "Cert Password:": "憑證金鑰密碼:",
+ "[INFO] Applying smart digital signature...": "[INFO] 正在為應用程式新增數位簽章...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] 數位簽章新增成功!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] 數位簽章未成功,但應用產物已正常保留。",
+ "Create": "建立",
+ "Create Self-Signed Cert": "建立自簽憑證",
+ "Certificate Subject (e.g. My Company):": "憑證頒發者 (如 My Company):",
+ "Generate": "產生",
+ "Self-Signed Certificate (*.pfx)": "自簽名憑證 (*.pfx)",
+ "Passwords do not match!": "兩次輸入的密碼不一致!",
+ "Failed to generate certificate.": "產生憑證失敗。",
+ "Certificate generated successfully!": "憑證產生成功!",
+ "Only supported on Windows.": "僅支援在 Windows 系統下產生 .pfx 憑證。",
+ "Save Certificate": "儲存憑證",
+ "Error": "錯誤",
+ "Select .pfx / .p12 certificate file": "請選擇 .pfx / .p12 格式憑證",
+ "Certificate password": "憑證金鑰密碼",
+ "Undo": "復原",
+ "Cut": "剪切",
+ "Paste": "貼上",
+ "QPyPack Developer": "QPyPack 開發者",
+ "Password cannot be empty!": "密碼不能為空!",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "建議:6位以上,僅使用英文字母、數字、減號及底線。避免使用中文或空格以防簽章失敗。",
+ "OS Support Matrix:": "支援作業系統情況:",
+ "Platform Support Matrix:": "平台支援:",
+ "No Windows 7 Support": "不支援 Windows 7",
+ "Full backward compatibility": "相容舊版作業系統",
+ "Legacy macOS Compatible": "相容舊版 macOS",
+ "Apple Silicon (M1/M2) & Intel": "支援 Apple Silicon (M1/M2) 與 Intel",
+ "Apple Silicon (M-Series) & Intel": "支援 Apple Silicon (M系列) 與 Intel",
+ "Compatibility depends on build environment glibc version.": "相容性取決於當前系統的 glibc 版本",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka 自動接管 C 編譯器",
+ "Interpreter
Auto-detecting system environment and OS support matrix...": "解譯器
正在自動偵測系統環境與支援作業系統情況...",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] 時間戳記伺服器連線逾時,進行本地快速簽章...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] 已透過時間戳記伺服器 ({tsa}) 完成數位簽章與蓋章..."
}
\ No newline at end of file
diff --git a/qpypack/main.py b/qpypack/main.py
index 8ba6f80..56f2aba 100644
--- a/qpypack/main.py
+++ b/qpypack/main.py
@@ -71,6 +71,7 @@ ZH_CN_DICT = {
"Huawei Cloud (China)": "华为云镜像",
"USTC (China)": "中科大镜像",
+ "Modern Cross-Platform Python Application Packager": "现代化的跨平台 Python 应用打包工具",
"Modern Cross-Platform Python Packaging GUI Powered by PyInstaller & Nuitka": "基于 PyInstaller 与 Nuitka 的现代化跨平台 Python 打包工具",
"Python Packaging, Reimagined.": "重新定义 Python 应用打包体验",
"Drop Python source code to start": "拖拽 Python 源码至此开始",
@@ -82,7 +83,7 @@ ZH_CN_DICT = {
"Engine": "构建引擎",
"Dependencies": "依赖管理",
"Resources": "附加资源",
- "Optimization": "性能优化",
+ "Optimization & Security": "优化与安全",
"Package Map": "包名映射",
"Execution Log": "执行日志",
@@ -134,6 +135,13 @@ ZH_CN_DICT = {
"Clear Log": "清空日志",
"Export Log...": "导出日志...",
"Reset": "重置",
+ "Undo": "撤销",
+ "Cut": "剪切",
+ "Paste": "粘贴",
+ "Create": "创建",
+ "Generate": "生成",
+ "Save Certificate": "保存证书",
+ "Error": "错误",
"Are you sure you want to reset all preferences?
All settings will be restored to default state.":
"确定重置所有偏好设置?
所有设置将恢复为默认状态。",
@@ -142,14 +150,17 @@ ZH_CN_DICT = {
"Mirrors & Scanner": "镜像与扫描",
"Additional Resources (Drag & Drop Supported)": "附加资源 (支持拖拽)",
"Performance Optimization": "性能优化",
+ "Code Signing": "代码签名",
"Lock Core Dependencies": "锁定核心依赖",
"Package Name Mappings": "包名映射",
"UI Language:": "界面语言:",
"App Metadata & Presets": "元数据与预设",
"Output Location": "输出位置",
"Preferences & System Behavior": "偏好与行为",
+
"Build Engine:": "构建引擎:",
- "Python Interpreter:": "Python 解释器:",
+ "Packaging Mode:": "打包模式:",
+ "Interpreter:": "解释器:",
"Output Name:": "输出名称:",
"App Icon:": "应用图标:",
"Primary PIP Index:": "主 PIP 源:",
@@ -179,8 +190,16 @@ ZH_CN_DICT = {
"Target relative path:": "目标相对路径:",
"Import name (e.g. cv2):": "导入名 (如 cv2):",
"PyPI package name for [{imp_name}]:": "[{imp_name}] 对应 PyPI 包名:",
- "Script and settings retained. Ready to rebuild.": "已保留当前配置,就绪等待重新构建。",
+ "Commercial PFX File:": "商业证书文件 (.pfx):",
+ "Cert Password:": "证书密钥密码:",
+ "Certificate Subject (e.g. My Company):": "证书颁发者 (如 My Company):",
+ "Confirm Password:": "确认密码:",
+ "Compatibility Mode (Default)": "兼容模式 (默认)",
+ "Lite Mode (Smaller size)": "精简模式 (体积小)",
+ "Maximum compatibility. Recommended for apps with complex dynamic imports.": "最大兼容性。适合使用了复杂动态导入的项目。",
+ "Smaller output size. Recommended for 95% of standard apps.": "产物体积最小。推荐 95% 的常规应用使用。",
+ "Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "提示: 精简模式构建失败。您可以尝试在【构建设置】中勾选 [兼容模式] 重新打包。",
"One-File Mode (--onefile)": "单文件模式 (--onefile)",
"Folder Mode (--onedir)": "文件夹模式 (--onedir)",
"Contents Directory (--contents-directory):": "内部资源目录:",
@@ -188,38 +207,50 @@ ZH_CN_DICT = {
"Hide Console (--noconsole)": "隐藏控制台 (--noconsole)",
"Use Virtual Environment (Recommended)": "使用虚拟环境 (推荐)",
"Keep Virtual Environment (Faster Rebuilds)": "保留虚拟环境 (适合频繁重编)",
- "[INFO] Reusing existing virtual environment...": "[INFO] 复用本地已存在的虚拟环境...",
"Install requirements.txt": "安装 requirements.txt",
"Analyze Dependencies (AST)": "分析依赖 (原生 AST)",
"Scan Entire Folder": "扫描整个文件夹",
"Enable UPX Compression": "启用 UPX 压缩",
+ "Enable Smart Code Signing": "开启数字签名",
+ "Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning": "自动为生成的应用程序添加数字签名,提升系统信任度",
+ "Use Custom Commercial Cert (Optional) ▸": "配置商业数字证书 (可选) ▸",
+ "Hide Custom Cert Settings ▾": "折叠证书高级设置 ▾",
+ "Create Self-Signed Cert": "创建自签证书",
+ "Self-Signed Certificate (*.pfx)": "自签名证书 (*.pfx)",
"Concise Log Output": "精简日志",
"Auto-save Build Log": "自动保存日志",
"Auto Extract Icon": "自动提取图标",
"Clean Temporary Cache After Build": "构建后清理缓存",
"Sound Notification": "完成提示音",
+
"Leave blank to auto-detect system default Python": "留空则自动检测系统 Python",
"Leave blank to auto-match script name": "留空则自动匹配脚本名",
"Leave blank to auto-search requirements.txt in current directory": "留空则自动检索当前目录 requirements.txt",
"Comma separated (e.g. pandas, PyQt5)": "逗号分隔 (如 pandas, PyQt5)",
"Comma separated (e.g. tkinter, matplotlib)": "逗号分隔 (如 tkinter, matplotlib)",
"Leave blank to auto-detect from environment variables": "留空则从环境变量自动检测",
+ "Select .pfx / .p12 certificate file": "请选择 .pfx / .p12 格式证书",
+ "Certificate password": "证书密钥密码",
"Double-click to edit target path; Drag & drop supported": "双击编辑目标路径;支持拖拽",
"Double-click to edit target path; Drag & drop supported. Use 'Export Preset' to save for reuse.": "双击编辑目标路径;支持拖拽。建议使用「导出预设」进行保存。",
+ "Project-specific. Not saved to global preferences. Use 'Export Preset' to save config.": "提示:此处资源配置仅对当前项目生效。如需长期复用,请使用「导出预设」。",
+ "Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors.": "建议:6位以上,仅使用英文字母、数字、减号及下划线。避免使用中文或空格以防签名失败。",
"PyInstaller — Bundles Python interpreter and bytecode. Fast build speed, zero configuration (no C compiler needed), and excellent compatibility.":
"PyInstaller — 打包解释器与字节码。构建迅速,零配置 (无需 C 编译器),兼容性优异。",
"Nuitka — Compiles source code into native C/C++ binary. Produces smaller package size, faster execution, and deep anti-decompilation protection (requires C compiler).":
"Nuitka — 编译为原生 C/C++ 二进制。体积更小,执行更快,具备强抗反编译能力 (需 C 编译器)。",
-
- 'Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility':
- 'Python {ver} 平台支持:
✔ Windows 7 ✔ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux
兼容旧系统 支持 Windows 7 及旧版操作系统',
- 'Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux':
- 'Python {ver} 平台支持:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10/11 ✔ macOS 10.9+ ✔ Linux',
- 'Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler':
- 'Python {ver} 平台支持:
✖ Windows 7 ✖ Windows 8/8.1 ✔ Windows 10/11 ✔ macOS 10.13+ ✔ Linux
Nuitka 自动检测并管理 C 后端编译器',
- 'Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...':
- 'Python 解释器
自动检测系统环境 (Win/macOS/Linux)...',
+ "OS Support Matrix:": "支持操作系统情况:",
+ "Platform Support Matrix:": "平台支持:",
+ "No Windows 7 Support": "不支持 Windows 7",
+ "Full backward compatibility": "兼容旧版操作系统",
+ "Legacy macOS Compatible": "兼容旧版 macOS",
+ "Apple Silicon (M1/M2) & Intel": "支持 Apple Silicon (M1/M2) 与 Intel",
+ "Apple Silicon (M-Series) & Intel": "支持 Apple Silicon (M系列) 与 Intel",
+ "Compatibility depends on build environment glibc version.": "兼容性取决于当前系统的 glibc 版本",
+ "* Nuitka Auto-manages C Compiler": "* Nuitka 自动接管 C 编译器",
+ 'Interpreter
Auto-detecting system environment and OS support matrix...':
+ '解释器
正在自动检测系统环境与支持操作系统情况...',
"[INFO] Build Cancelled.": "[INFO] 构建已取消。",
"[INFO] Performing pre-flight environment checks...": "[INFO] 执行预构建环境检查...",
@@ -228,6 +259,7 @@ ZH_CN_DICT = {
"[INFO] Playwright detected. Installing built-in browsers (PLAYWRIGHT_BROWSERS_PATH=0)...": "[INFO] 检测到 Playwright。正在安装内置浏览器驱动...",
"[INFO] Python interpreter path: {path}": "[INFO] Python 路径: {path}",
"[INFO] Creating virtual environment...": "[INFO] 创建虚拟环境...",
+ "[INFO] Reusing existing virtual environment...": "[INFO] 复用本地已存在的虚拟环境...",
"[INFO] Synchronizing and upgrading pip package manager...": "[INFO] 更新 pip...",
"[INFO] Scanning project source code via AST engine...": "[INFO] 使用原生 AST 引擎扫描依赖...",
"[INFO] Nuitka Tip: If prompted to download GCC/MinGW compiler on first build, please ensure stable network connection.": "[INFO] Nuitka 提示: 首次构建如需下载 GCC/MinGW,请确保网络畅通。",
@@ -258,6 +290,9 @@ ZH_CN_DICT = {
"[INFO] Freeing up space, cleaning temporary build environment...": "[INFO] 清理临时构建环境...",
"[INFO] Downloading Playwright browsers via mirror: {url}": "[INFO] 通过镜像下载 Playwright 浏览器: {url}",
"[INFO] Retrying Playwright browser download via official CDN...": "[INFO] 通过官方 CDN 重试下载 Playwright 浏览器...",
+ "[INFO] Applying smart digital signature...": "[INFO] 正在为应用程序添加数字签名...",
+ "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] 数字签名添加成功!",
+ "[WARN] Smart signing failed, but build output is retained.": "[WARN] 数字签名未成功,但应用产物已正常保留。",
"[SUCCESS] Compilation completed, output path: {path}": "[SUCCESS] 构建成功,输出路径: {path}",
"[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] 项目位于云同步目录,可能锁定构建文件。",
"[WARN] Specified versions failed to install. Stripping version constraints for automatic compatibility match...": "[WARN] 指定版本安装失败,尝试自动匹配兼容版本...",
@@ -278,6 +313,7 @@ ZH_CN_DICT = {
"[WARN] Playwright browser installation failed across all sources, build will proceed with risk...": "[WARN] 所有 Playwright 浏览器下载源均失败,继续构建 (有风险)...",
"[WARN] Icon conversion to .icns failed, building without icon.": "[WARN] 图标转换为 .icns 失败,将不使用图标构建。",
"[INFO] Tip: Packaged executables might be falsely flagged by Windows Defender/Antivirus. Adding exclusions or code-signing is recommended.": "[INFO] 提示: 独立可执行程序可能被安全软件误报。建议加入白名单或添加代码签名。",
+
"[ERROR] Build aborted: Insufficient disk space (NoSpaceLeft / Errno 28). Please clean up drive space (at least 5 GB free space recommended) and try again.": "[ERROR] 构建中止: 磁盘空间不足 (NoSpaceLeft / Errno 28)。建议预留至少 5GB 可用空间。",
"[ERROR] Output directory is missing write permissions: {error}": "[ERROR] 目标输出目录无写入权限: {error}",
"[ERROR] Requirements file not found: {path}": "[ERROR] 指定的依赖清单文件不存在: {path}",
@@ -299,56 +335,33 @@ ZH_CN_DICT = {
"[ERROR] System execution exception: {error}": "[ERROR] 系统执行异常: {error}",
"[ERROR] I/O Exception: {err_msg}": "[ERROR] I/O 异常: {err_msg}",
"[ERROR] Python installation failed or was cancelled.": "[ERROR] Python 安装失败或已被主动取消。",
- "[ERROR] Build completed, but the following dependencies failed to install:\n\n - {pkgs}\n\nNote: The application might raise ModuleNotFoundError at runtime.":
+ "Passwords do not match!": "两次输入的密码不一致!",
+ "Failed to generate certificate.": "生成证书失败。",
+ "Certificate generated successfully!": "证书生成成功!",
+ "Only supported on Windows.": "仅支持在 Windows 系统下生成 .pfx 证书。",
+ "Password cannot be empty!": "密码不能为空!",
+
+ "[ERROR] Build completed, but the following dependencies failed to install:\n\n - {pkgs}\n\nNote: The application might raise ModuleNotFoundError at runtime.":
"[ERROR] 构建完成,但以下依赖安装失败:\n\n - {pkgs}\n\n注意: 运行时程序可能会抛出 ModuleNotFoundError。",
- "[Syntax Error] Source code syntax parsing failed, build aborted:\n"
- " - File: {file}\n"
- " - Line: Line {line}\n"
- " - Detail: {desc}\n\n"
- "Tip: This is usually NOT a fault of the packaging tool.\n"
- "Please ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\n"
- "Using newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\n"
- "We recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.":
- "[Syntax Error] 源码语法解析失败,构建中止:\n"
- " - 文件: {file}\n"
- " - 行号: {line}\n"
- " - 详情: {desc}\n\n"
- "提示:这通常不是打包工具的故障。\n"
- "请确认您当前选择的【打包 Python 版本】与您【编写代码时的版本】是否一致。\n"
- "高版本语法(如海象运算符 :=、类型联合 |、match-case 等)在低版本 Python 中会导致此错误。\n"
- "建议前往【构建设置】->【构建引擎】切换至对应版本的 Python。",
+ "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.":
+ "[Syntax Error] 源码语法解析失败,构建中止:\n - 文件: {file}\n - 行号: {line}\n - 详情: {desc}\n\n提示:这通常不是打包工具的故障。\n请确认您当前选择的【打包 Python 版本】与您【编写代码时的版本】是否一致。\n高版本语法(如海象运算符 :=、类型联合 |、match-case 等)在低版本 Python 中会导致此错误。\n建议前往【构建设置】->【构建引擎】切换至对应版本的 Python。",
- "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.":
+ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.":
"[ERROR] 源码语法错误,构建中止:\n - 文件: {file}\n - 类型: {type}\n - 行号: {line}\n - 详情: {desc}\n\n提示: 请确保源码可在本地运行。",
-
- "[FAILED] Build interrupted exceptionally!\n\n"
- "Common Troubleshooting:\n"
- "1. Environment Mismatch (Most Common): The selected Python version is incompatible with your source code. Please go to [Build Settings] to switch to the Python version you normally use for this code.\n"
- "2. Missing Dependencies: Click 'Detailed Mode' above to check for ModuleNotFoundError.\n"
- "3. Antivirus Block: Ensure your security software is not blocking the build process.\n\n"
- "(Note: This is usually caused by environment/code discrepancies rather than the packaging engine itself. Please check the detailed log for exact reasons.)":
- "[FAILED] 构建异常中断!\n\n"
- "常见原因排查:\n"
- "1. 环境不匹配 (最常见):您选择的打包 Python 版本与您的源码不兼容。请前往【构建设置】切换为您平时开发运行该代码的 Python 版本。\n"
- "2. 依赖缺失:请点击上方切换至「详细日志」,查看是否有模块未找到 (ModuleNotFoundError)。\n"
- "3. 杀毒软件拦截:请检查是否有安全软件阻止了打包过程。\n\n"
- "(注意:这通常是环境配置与代码差异导致,并非打包引擎本身故障,请查阅详细日志获取确切原因。)",
- "[FAILED] Compilation interrupted with exceptions, please click 'Detailed Mode' above the log window for troubleshooting.":
+
+ "[FAILED] Build interrupted exceptionally!\n\nCommon Troubleshooting:\n1. Environment Mismatch (Most Common): The selected Python version is incompatible with your source code. Please go to [Build Settings] to switch to the Python version you normally use for this code.\n2. Missing Dependencies: Click 'Detailed Mode' above to check for ModuleNotFoundError.\n3. Antivirus Block: Ensure your security software is not blocking the build process.\n\n(Note: This is usually caused by environment/code discrepancies rather than the packaging engine itself. Please check the detailed log for exact reasons.)":
+ "[FAILED] 构建异常中断!\n\n常见原因排查:\n1. 环境不匹配 (最常见):您选择的打包 Python 版本与您的源码不兼容。请前往【构建设置】切换为您平时开发运行该代码的 Python 版本。\n2. 依赖缺失:请点击上方切换至「详细日志」,查看是否有模块未找到 (ModuleNotFoundError)。\n3. 杀毒软件拦截:请检查是否有安全软件阻止了打包过程。\n\n(注意:这通常是环境配置与代码差异导致,并非打包引擎本身故障,请查阅详细日志获取确切原因。)",
+
+ "[FAILED] Compilation interrupted with exceptions, please click 'Detailed Mode' above the log window for troubleshooting.":
"[FAILED] 构建异常中断,请切换至「详细日志」排查原因。",
- "No log content.": "无日志内容。",
- "Log saved to: {path}": "日志已保存: {path}",
- "\\nProgram execution completed, press Enter to exit...": "\\n程序执行完成,按回车键退出...",
- "Project-specific. Not saved to global preferences. Use 'Export Preset' to save config.":
- "提示:此处资源配置仅对当前项目生效。如需长期复用,请使用「导出预设」。",
"GitHub Repository": "GitHub 仓库",
"Issues & Feedback": "问题与反馈",
"PyPI Home": "PyPI 主页",
"Sponsor": "赞助支持",
"QPyPack is a free and open-source tool. If it has improved your efficiency or solved packaging problems, consider buying the author a coffee!": "QPyPack 是一款免费开源工具。如果它提升了您的效率或解决了打包难题,欢迎赞助支持本开源项目。",
"* Sponsorship is completely voluntary, serves as an unconditional encouragement to the open-source community, and involves no commercial commitments. Thank you for your support!": "* 赞助完全出于自愿,属于对开源社区的无偿鼓励,不涉及任何商业承诺。感谢您的支持!",
-
"Python Environment Required": "需要 Python 环境",
"Python is not detected on your system!
QPyPack requires a Python environment to compile your code.
If you haven't installed Python, please download and install it (remember to check 'Add Python.exe to PATH' during installation).": "未在系统中检测到有效的 Python 环境
QPyPack 需要依赖 Python 才能编译代码。
如果您尚未安装,请前往官网下载安装 (提示:安装界面底部请务必勾选 'Add Python.exe to PATH')。",
"Download Python": "前往下载 Python",
@@ -397,19 +410,19 @@ ZH_CN_DICT = {
"Config preset exported to: {path}": "配置预设已成功导出至: {path}",
"Config preset imported successfully.": "配置预设已成功导入。",
"AST scan completed, found {count} dependencies.": "AST 扫描完成,发现 {count} 个隐式依赖。",
+ "No log content.": "无日志内容。",
+ "Log saved to: {path}": "日志已保存: {path}",
"Attention: Please check the log for details.": "提示: 请检查下方日志排查详细原因。",
-
"System Default ({sys_native})": "系统默认 ({sys_native})",
- "My Studio": "我的工作室",
- "Python Executable": "Python 可执行程序",
+ "Independent Developer": "独立开发者",
+ "Desktop Application": "桌面应用程序",
"Invalid syntax": "无效语法",
"OK": "确定",
- "Packaging Mode:": "打包模式:",
- "Compatibility Mode (Default)": "兼容模式 (默认)",
- "Lite Mode (Smaller size)": "精简模式 (体积小)",
- "Maximum compatibility. Recommended for apps with complex dynamic imports.": "最大兼容性。适合使用了复杂动态导入的项目。",
- "Smaller output size. Recommended for 95% of standard apps.": "产物体积最小。推荐 95% 的常规应用使用。",
- "Tip: Build failed in Lite Mode. You can try switching to [Compatibility Mode] in Build Settings and rebuild.": "提示: 精简模式构建失败。您可以尝试在【构建设置】中勾选 [兼容模式] 重新打包。",
+ "QPyPack Developer": "QPyPack 开发者",
+ "\\nProgram execution completed, press Enter to exit...": "\\n程序执行完成,按回车键退出...",
+ "Script and settings retained. Ready to rebuild.": "已保留当前配置,就绪等待重新构建。",
+ "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] 时间戳服务器连通超时,进行本地快速签名...",
+ "[INFO] Applied digital signature with timestamp ({tsa})...": "[INFO] 已通过时间戳服务器 ({tsa}) 完成数字签名与盖章...",
"Unknown": "未知"
}
@@ -689,6 +702,9 @@ def load_config(retry=True):
default_updates = {
'language': 'auto',
'keep_venv': 'False',
+ 'enable_sign': 'True' if sys.platform == 'darwin' else 'False',
+ 'cert_path': '',
+ 'cert_pass': '',
'pip_index': default_mirror,
'pip_index_backup': default_backup,
'concise_log': 'True',
@@ -1093,6 +1109,82 @@ class CustomInputDialog(QDialog):
def get_text(self):
return self.edit.text()
+class GenCertDialog(QDialog):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setWindowTitle(_("Create Self-Signed Cert"))
+ self.setMinimumWidth(380)
+ self.setStyleSheet("""
+ QDialog { background-color: #ffffff; }
+ QLabel { font-size: 12px; color: #111827; }
+ QLineEdit { padding: 6px 10px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 12px; }
+ QLineEdit:focus { border: 1px solid #2563eb; }
+ QPushButton { background-color: #f1f5f9; color: #475569; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 12px; font-weight: bold; padding: 6px 16px; min-width: 70px; }
+ QPushButton:hover { background-color: #e2e8f0; }
+ QPushButton#btnOk { background-color: #2563eb; color: #ffffff; border: none; }
+ QPushButton#btnOk:hover { background-color: #1d4ed8; }
+ """)
+
+ lay = QVBoxLayout(self)
+ lay.setSpacing(10)
+ lay.setContentsMargins(20, 20, 20, 20)
+
+ form_lay = QFormLayout()
+
+ self.subject_edit = QLineEdit(_("QPyPack Developer"))
+ self.pass_edit = QLineEdit()
+ self.pass_edit.setEchoMode(QLineEdit.EchoMode.Password)
+ self.confirm_edit = QLineEdit()
+ self.confirm_edit.setEchoMode(QLineEdit.EchoMode.Password)
+
+ form_lay.addRow(QLabel(_("Certificate Subject (e.g. My Company):")), self.subject_edit)
+ form_lay.addRow(QLabel(_("Password:")), self.pass_edit)
+ form_lay.addRow(QLabel(_("Confirm Password:")), self.confirm_edit)
+
+ lay.addLayout(form_lay)
+
+ self.hint_label = QLabel(_("Recommendation: 6+ chars, alphanumeric, '-' and '_' only. Avoid spaces or Chinese to prevent signing errors."))
+ self.hint_label.setWordWrap(True)
+ self.hint_label.setStyleSheet("color: #64748b; font-size: 11px; margin-top: 2px;")
+ lay.addWidget(self.hint_label)
+
+ lay.addSpacing(10)
+
+ btn_lay = QHBoxLayout()
+ btn_lay.addStretch()
+
+ self.btn_ok = QPushButton(_("Generate"))
+ self.btn_ok.setObjectName("btnOk")
+ self.btn_ok.clicked.connect(self.on_generate)
+
+ self.btn_cancel = QPushButton(_("Cancel"))
+ self.btn_cancel.clicked.connect(self.reject)
+
+ btn_lay.addWidget(self.btn_ok)
+ btn_lay.addWidget(self.btn_cancel)
+ lay.addLayout(btn_lay)
+
+ self.cert_info = None
+
+ def on_generate(self):
+ subject = self.subject_edit.text().strip()
+ pwd = self.pass_edit.text()
+ confirm = self.confirm_edit.text()
+
+ if not subject:
+ return
+
+ if not pwd:
+ QMessageBox.warning(self, _("Error"), _("Password cannot be empty!"))
+ return
+
+ if pwd != confirm:
+ QMessageBox.warning(self, _("Error"), _("Passwords do not match!"))
+ return
+
+ self.cert_info = (subject, pwd)
+ self.accept()
+
class ComboItemDelegate(QStyledItemDelegate):
def sizeHint(self, option, index):
s = super().sizeHint(option, index)
@@ -1653,7 +1745,8 @@ class DropArea(QFrame):
self,
_("Drag & Drop Python script (.py/.pyw) here\nor Click to Browse"),
"",
- "Python Scripts (*.py *.pyw);;All Files (*)"
+ "Python Scripts (*.py *.pyw);;All Files (*)",
+ options=QFileDialog.Option.DontUseNativeDialog
)
if fp: self.fileDropped.emit(fp)
@@ -2041,13 +2134,13 @@ class SettingsPanel(QWidget):
sub_scroll3, _cnt3, lay_sub3 = self._create_scroll_tab()
sub_scroll4, _cnt4, lay_sub4 = self._create_scroll_tab()
sub_scroll5, _cnt5, lay_sub5 = self._create_scroll_tab()
-
+
self.sub_tabs.addTab(sub_scroll1, get_svg_icon('engine', "#5F6368", 16), _("Engine"))
self.sub_tabs.addTab(sub_scroll2, get_svg_icon('package', "#5F6368", 16), _("Dependencies"))
self.sub_tabs.addTab(sub_scroll3, get_svg_icon('folder', "#5F6368", 16), _("Resources"))
- self.sub_tabs.addTab(sub_scroll4, get_svg_icon('bolt', "#5F6368", 16), _("Optimization"))
+ self.sub_tabs.addTab(sub_scroll4, get_svg_icon('bolt', "#5F6368", 16), _("Optimization & Security"))
self.sub_tabs.addTab(sub_scroll5, get_svg_icon('link', "#5F6368", 16), _("Package Map"))
-
+
self.card_engine, c_lay_engine = self._create_card(_("Engine & Environment"))
self.form_engine = QFormLayout()
self.form_engine.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
@@ -2158,7 +2251,7 @@ class SettingsPanel(QWidget):
self.lbl_eng_title = QLabel(_("Build Engine:"))
self.lbl_pack_mode_title = QLabel(_("Packaging Mode:"))
- self.lbl_py_title = QLabel(_("Python Interpreter:"))
+ self.lbl_py_title = QLabel(_("Interpreter:"))
self.lbl_app_title = QLabel(_("Output Name:"))
self.lbl_icon_title = QLabel(_("App Icon:"))
@@ -2366,9 +2459,54 @@ class SettingsPanel(QWidget):
self.lbl_upx_path = QLabel(_("UPX Path:"))
self.form_opt.addRow(self.lbl_upx_path, h_upx_row)
-
c_lay_opt.addLayout(self.form_opt)
+ self.card_sign, c_lay_sign = self._create_card(_("Code Signing"))
+ self.enable_sign_check = QCheckBox(_("Enable Smart Code Signing"))
+ self.enable_sign_check.setToolTip(_("Auto-applies digital signature to built app, eliminating 'Unknown Publisher' warning"))
+ c_lay_sign.addWidget(self.enable_sign_check)
+
+ self.adv_sign_container = QWidget()
+ form_adv_sign = QFormLayout(self.adv_sign_container)
+ form_adv_sign.setContentsMargins(0, 5, 0, 0)
+ form_adv_sign.setSpacing(10)
+
+ self.cert_path_edit = QLineEdit()
+ self.cert_path_edit.setPlaceholderText(_("Select .pfx / .p12 certificate file"))
+
+ self.btn_cert = QPushButton(_("Browse"))
+ self.btn_cert.setProperty("class", "ToolBtn")
+ self.btn_cert.clicked.connect(self.select_cert_file)
+
+ self.btn_gen_cert = QPushButton(_("Create"))
+ self.btn_gen_cert.setProperty("class", "ToolBtn")
+ self.btn_gen_cert.setToolTip(_("Create Self-Signed Cert"))
+ self.btn_gen_cert.clicked.connect(self.create_self_signed_cert)
+
+ cert_cont = QWidget()
+ h_cert = QHBoxLayout(cert_cont)
+ h_cert.setContentsMargins(0, 0, 0, 0)
+ h_cert.setSpacing(6)
+ h_cert.addWidget(self.cert_path_edit, 1)
+ h_cert.addWidget(self.btn_cert)
+ h_cert.addWidget(self.btn_gen_cert)
+
+ self.cert_pass_edit = QLineEdit()
+ self.cert_pass_edit.setEchoMode(QLineEdit.EchoMode.Password)
+ self.cert_pass_edit.setPlaceholderText(_("Certificate password"))
+
+ form_adv_sign.addRow(QLabel(_("Commercial PFX File:")), cert_cont)
+ form_adv_sign.addRow(QLabel(_("Cert Password:")), self.cert_pass_edit)
+ self.adv_sign_container.setVisible(False)
+
+ self.btn_toggle_adv_sign = QPushButton(_("Use Custom Commercial Cert (Optional) ▸"))
+ self.btn_toggle_adv_sign.setFlat(True)
+ self.btn_toggle_adv_sign.setStyleSheet("QPushButton { color: #2563eb; font-size: 12px; text-align: left; background: transparent; border: none; font-weight: bold; } QPushButton:hover { text-decoration: underline; }")
+ self.btn_toggle_adv_sign.clicked.connect(self.toggle_adv_sign_ui)
+
+ c_lay_sign.addWidget(self.btn_toggle_adv_sign)
+ c_lay_sign.addWidget(self.adv_sign_container)
+
self.card_ver, c_lay_ver = self._create_card(_("Lock Core Dependencies"))
self.form_ver = QFormLayout()
self.form_ver.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
@@ -2385,6 +2523,7 @@ class SettingsPanel(QWidget):
c_lay_ver.addLayout(self.form_ver)
lay_sub4.addWidget(self.card_opt)
+ lay_sub4.addWidget(self.card_sign)
lay_sub4.addWidget(self.card_ver)
lay_sub4.addStretch()
@@ -2420,7 +2559,7 @@ class SettingsPanel(QWidget):
lay_sub5.addWidget(self.card_map)
lay_sub5.addStretch()
-
+
main_lay.addWidget(self.sub_tabs)
self.on_engine_changed()
@@ -2444,8 +2583,8 @@ class SettingsPanel(QWidget):
self.form_meta.setSpacing(15)
self.ver_ver = QLineEdit("1.0.0")
- self.ver_comp = QLineEdit(_("My Studio"))
- self.ver_desc = QLineEdit(_("Python Executable"))
+ self.ver_comp = QLineEdit(_("Independent Developer"))
+ self.ver_desc = QLineEdit(_("Desktop Application"))
self.lbl_ver_title = QLabel(_("Version:"))
self.lbl_company_title = QLabel(_("Author/Company:"))
@@ -2655,7 +2794,7 @@ class SettingsPanel(QWidget):
self.sub_tabs.setTabText(0, _("Engine"))
self.sub_tabs.setTabText(1, _("Dependencies"))
self.sub_tabs.setTabText(2, _("Resources"))
- self.sub_tabs.setTabText(3, _("Optimization"))
+ self.sub_tabs.setTabText(3, _("Optimization & Security"))
self.sub_tabs.setTabText(4, _("Package Map"))
self.card_engine.findChild(QLabel, "CardTitle").setText(_("Engine & Environment"))
@@ -2677,7 +2816,7 @@ class SettingsPanel(QWidget):
self.rb_compat_mode.setToolTip(_("Maximum compatibility. Recommended for apps with complex dynamic imports."))
self.rb_lite_mode.setToolTip(_("Smaller output size. Recommended for 95% of standard apps."))
- self.lbl_py_title.setText(_("Python Interpreter:"))
+ self.lbl_py_title.setText(_("Interpreter:"))
self.lbl_app_title.setText(_("Output Name:"))
self.lbl_icon_title.setText(_("App Icon:"))
self.lbl_pip_main.setText(_("Primary PIP Index:"))
@@ -2700,10 +2839,10 @@ class SettingsPanel(QWidget):
self.sandbox_mode_combo.setItemText(1, _("System Temp Directory"))
if not self.ver_comp.isModified():
- self.ver_comp.setText(_("My Studio"))
+ self.ver_comp.setText(_("Independent Developer"))
if not self.ver_desc.isModified():
- self.ver_desc.setText(_("Python Executable"))
+ self.ver_desc.setText(_("Desktop Application"))
if hasattr(self, 'pip_source_combo') and hasattr(self, 'pip_backup_combo'):
cur_main = self._get_url_from_combo(self.pip_source_combo)
@@ -2730,6 +2869,11 @@ class SettingsPanel(QWidget):
self.btn_python_path.setText(_("Browse"))
self.btn_download_py.setText(_("View Python"))
self.btn_icon.setText(_("Browse"))
+ self.btn_cert.setText(_("Browse"))
+ self.btn_gen_cert.setText(_("Create"))
+ self.btn_gen_cert.setToolTip(_("Create Self-Signed Cert"))
+ self.cert_path_edit.setPlaceholderText(_("Select .pfx / .p12 certificate file"))
+ self.cert_pass_edit.setPlaceholderText(_("Certificate password"))
self.btn_reqs.setText(_("Browse"))
self.btn_scan.setText(_("AST Scan"))
self.btn_upx.setText(_("Browse"))
@@ -2853,8 +2997,63 @@ class SettingsPanel(QWidget):
if hasattr(self.parent_win, "show_notification"):
self.parent_win.show_notification(_("Package mappings have been reset to defaults."))
+ def toggle_adv_sign_ui(self):
+ is_visible = not self.adv_sign_container.isVisible()
+ self.adv_sign_container.setVisible(is_visible)
+ if is_visible:
+ self.btn_toggle_adv_sign.setText(_("Hide Custom Cert Settings ▾"))
+ else:
+ self.btn_toggle_adv_sign.setText(_("Use Custom Commercial Cert (Optional) ▸"))
+
+ def select_cert_file(self):
+ f, _filter = QFileDialog.getOpenFileName(self, _("Commercial PFX File:"), "", "PKCS#12 Certificate (*.pfx *.p12);;All Files (*)", options=QFileDialog.Option.DontUseNativeDialog)
+ if f: self.cert_path_edit.setText(Path(f).resolve().as_posix())
+
+ def create_self_signed_cert(self):
+ if os.name != 'nt':
+ if hasattr(self.parent_win, "show_notification"):
+ self.parent_win.show_notification(_("Only supported on Windows."))
+ return
+
+ dlg = GenCertDialog(self)
+ if dlg.exec() == QDialog.DialogCode.Accepted:
+ subject, pwd = dlg.cert_info
+
+ fp, _filter = QFileDialog.getSaveFileName(
+ self,
+ _("Save Certificate"),
+ "my_cert.pfx",
+ _("Self-Signed Certificate (*.pfx)"),
+ options=QFileDialog.Option.DontUseNativeDialog
+ )
+
+ if fp:
+ try:
+ fp_posix = Path(fp).resolve().as_posix()
+ safe_subject = subject.replace("'", "''")
+ safe_pwd = pwd.replace("'", "''")
+ ps_cmd = (
+ f'$subject = "CN={safe_subject}"; '
+ f'$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject $subject -CertStoreLocation "Cert:\\CurrentUser\\My"; '
+ f'$pwd = ConvertTo-SecureString -String \'{safe_pwd}\' -Force -AsPlainText; '
+ f'Export-PfxCertificate -Cert $cert -FilePath "{fp_posix}" -Password $pwd; '
+ f'Remove-Item -Path "Cert:\\CurrentUser\\My\\$($cert.Thumbprint)"'
+ )
+ res = subprocess.run(["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", ps_cmd], capture_output=True, text=True, creationflags=subprocess.CREATE_NO_WINDOW)
+ if res.returncode == 0 and Path(fp).exists():
+ self.cert_path_edit.setText(fp_posix)
+ self.cert_pass_edit.setText(pwd)
+ if hasattr(self.parent_win, "show_notification"):
+ self.parent_win.show_notification(_("Certificate generated successfully!"))
+ else:
+ if hasattr(self.parent_win, "show_error_log"):
+ self.parent_win.show_error_log(_("Failed to generate certificate.") + f" {res.stderr}")
+ except Exception as e:
+ if hasattr(self.parent_win, "show_error_log"):
+ self.parent_win.show_error_log(_("Failed to generate certificate.") + f" {str(e)}")
+
def export_preset(self):
- fp, _filter = QFileDialog.getSaveFileName(self, _("Export Preset..."), "project_config.qpypack", "QPyPack Presets (*.qpypack *.json)")
+ fp, _filter = QFileDialog.getSaveFileName(self, _("Export Preset..."), "project_config.qpypack", "QPyPack Presets (*.qpypack *.json)", options=QFileDialog.Option.DontUseNativeDialog)
if fp:
try:
data = {
@@ -2887,7 +3086,7 @@ class SettingsPanel(QWidget):
self.parent_win.show_error_log(_("[ERROR] Failed to export preset file: {error}", error=str(e)))
def import_preset(self):
- fp, _filter = QFileDialog.getOpenFileName(self, _("Import Preset..."), "", "QPyPack Presets (*.qpypack *.json);;All Files (*)")
+ fp, _filter = QFileDialog.getOpenFileName(self, _("Import Preset..."), "", "QPyPack Presets (*.qpypack *.json);;All Files (*)", options=QFileDialog.Option.DontUseNativeDialog)
if fp:
try:
data = json.loads(Path(fp).read_text(encoding='utf-8'))
@@ -2990,7 +3189,16 @@ class SettingsPanel(QWidget):
self.pyi_ver_edit.setText(s.get('pyi_version', '6.21.0'))
self.nuitka_ver_edit.setText(s.get('nuitka_version', '4.1.3'))
-
+
+ default_sign_on_os = True if sys.platform == 'darwin' else False
+ self.enable_sign_check.setChecked(s.getboolean('enable_sign', default_sign_on_os))
+
+ self.cert_path_edit.setText(s.get('cert_path', ''))
+ self.cert_pass_edit.setText(s.get('cert_pass', ''))
+ if self.cert_path_edit.text():
+ self.adv_sign_container.setVisible(True)
+ self.btn_toggle_adv_sign.setText(_("Hide Custom Cert Settings ▾"))
+
self.add_data_list.clear()
if 'Mappings' in config:
@@ -3041,7 +3249,11 @@ class SettingsPanel(QWidget):
s['pyi_version'] = self.pyi_ver_edit.text().strip()
s['nuitka_version'] = self.nuitka_ver_edit.text().strip()
-
+
+ s['enable_sign'] = str(self.enable_sign_check.isChecked())
+ s['cert_path'] = self.cert_path_edit.text().strip()
+ s['cert_pass'] = self.cert_pass_edit.text().strip()
+
s['add_data_list'] = ''
config['Mappings'] = {}
@@ -3090,24 +3302,53 @@ class SettingsPanel(QWidget):
m_path = re.search(r'python(\d)(\d+)', raw_text, re.I)
if m_path: ver_str = f"{m_path.group(1)}.{m_path.group(2)}"
- self.python_desc_lbl.setStyleSheet("QLabel { background-color: #f8fafc; color: #334155; border: 1px solid #e2e8f0; border-radius: 6px; padding: 8px 12px; font-size: 12px; line-height: 1.5; }")
+ self.python_desc_lbl.setStyleSheet("QLabel { background-color: #f8fafc; color: #334155; border: 1px solid #e2e8f0; border-radius: 6px; padding: 10px 14px; font-size: 12px; line-height: 1.6; }")
if ver_str:
try:
parts = [int(x) for x in ver_str.split('.')]
major, minor = parts[0], parts[1]
- if (major, minor) <= (3, 8):
- self.python_desc_lbl.setText(_('Python {ver} Platform Matrix:
✔ Windows 7 ✔ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux
Legacy OS Full backward compatibility', ver=ver_str))
- elif (major, minor) <= (3, 10):
- self.python_desc_lbl.setText(_('Python {ver} Platform Matrix:
✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ macOS 10.9+ ✔ Linux', ver=ver_str))
+ html = f'Python {ver_str} { _("OS Support Matrix:") }
'
+
+ tag_style = "background-color:#f1f5f9; color:#475569; padding:2px 8px; border-radius:4px; font-weight:bold; font-size:10px; margin-right: 8px;"
+
+ if sys.platform == "win32":
+ if (major, minor) <= (3, 8):
+ html += '✔ Windows 7 / 8 / 8.1 ✔ Windows 10 / 11 ✔ Windows Server 2008+
'
+ html += f'x86 / AMD64{_("Full backward compatibility")}
'
+ elif (major, minor) <= (3, 10):
+ html += '✖ Windows 7 ✔ Windows 8.1 ✔ Windows 10 / 11 ✔ Windows Server 2012+
'
+ html += f'AMD64 / ARM64{_("No Windows 7 Support")}
'
+ else:
+ html += '✖ Windows 7 / 8 / 8.1 ✔ Windows 10 / 11 ✔ Windows Server 2016+
'
+ html += f'{_("* Nuitka Auto-manages C Compiler")}
'
+
+ elif sys.platform == "darwin":
+ if (major, minor) <= (3, 8):
+ html += '✔ OS X 10.9 (Mavericks) + ✔ macOS 10.15 (Catalina)
'
+ html += f'x86_64 Intel Only{_("Legacy macOS Compatible")}
'
+ elif (major, minor) <= (3, 10):
+ html += '✔ macOS 10.9 (Mavericks) + ✔ macOS 11 (Big Sur) +
'
+ html += f'Universal2 Binary{_("Apple Silicon (M1/M2) & Intel")}
'
+ else:
+ html += '✔ macOS 10.13 (High Sierra) + ✔ macOS 13 / 14 / 15+
'
+ html += f'Universal2 Binary{_("Apple Silicon (M-Series) & Intel")}
'
+
else:
- self.python_desc_lbl.setText(_('Python {ver} Platform Matrix:
✖ Windows 7 ✖ Windows 8 / 8.1 ✔ Windows 10 / 11 ✔ macOS 10.13+ ✔ Linux
Nuitka Auto-detecting and managing C backend compiler', ver=ver_str))
+ if (major, minor) <= (3, 9):
+ html += '✔ Ubuntu 16.04+ ✔ CentOS / RHEL 7+ ✔ Debian 9+
'
+ html += f'x86_64 / aarch64glibc >= 2.17
'
+ else:
+ html += '✔ Ubuntu 20.04+ ✔ Fedora 32+ ✔ Debian 11+ ✔ RHEL 8+
'
+ html += f'x86_64 / aarch64glibc >= 2.28
'
+
+ self.python_desc_lbl.setText(html)
return
except Exception:
pass
- self.python_desc_lbl.setText(_('Python Interpreter
Auto-detecting system environment for Windows, macOS & Linux...'))
+ self.python_desc_lbl.setText(_('Interpreter
Auto-detecting system environment and OS support matrix...'))
def on_upx_toggled(self, checked):
if getattr(self, 'upx_path_container', None) is not None:
@@ -3119,20 +3360,20 @@ class SettingsPanel(QWidget):
self.out_dir_container.setVisible(show_custom)
def select_out_dir(self):
- d = QFileDialog.getExistingDirectory(self, _("Target Directory:"))
+ d = QFileDialog.getExistingDirectory(self, _("Target Directory:"), options=QFileDialog.Option.DontUseNativeDialog)
if d: self.out_dir_edit.setText(Path(d).resolve().as_posix())
def select_upx_path(self):
- d = QFileDialog.getExistingDirectory(self, _("UPX Path:"))
+ d = QFileDialog.getExistingDirectory(self, _("UPX Path:"), options=QFileDialog.Option.DontUseNativeDialog)
if d: self.upx_path_edit.setText(Path(d).resolve().as_posix())
def select_reqs_file(self):
- f, _filter = QFileDialog.getOpenFileName(self, _("Requirements File:"), "", "Requirements Files (*.txt);;All Files (*)")
+ f, _filter = QFileDialog.getOpenFileName(self, _("Requirements File:"), "", "Requirements Files (*.txt);;All Files (*)", options=QFileDialog.Option.DontUseNativeDialog)
if f: self.reqs_file_edit.setText(Path(f).resolve().as_posix())
def select_python_path(self):
exe_filter = "Executable (*.exe);;All Files (*)" if os.name == 'nt' else "All Files (*)"
- f, _filter = QFileDialog.getOpenFileName(self, _("Python Interpreter:"), "", exe_filter)
+ f, _filter = QFileDialog.getOpenFileName(self, _("Interpreter:"), "", exe_filter, options=QFileDialog.Option.DontUseNativeDialog)
if f: self.python_path_combo.setCurrentText(Path(f).resolve().as_posix())
def on_download_python_clicked(self):
@@ -3148,7 +3389,7 @@ class SettingsPanel(QWidget):
self.icon_preview.clear()
def select_icon(self):
- p, _filter = QFileDialog.getOpenFileName(self, _("App Icon:"), "", "Icon Files (*.ico *.svg *.png *.icns)")
+ p, _filter = QFileDialog.getOpenFileName(self, _("App Icon:"), "", "Icon Files (*.ico *.svg *.png *.icns)", options=QFileDialog.Option.DontUseNativeDialog)
if p: self.icon_edit.setText(Path(p).resolve().as_posix())
def auto_scan_hidden(self):
@@ -3177,13 +3418,13 @@ class SettingsPanel(QWidget):
self._add_resource_item('dir', p.as_posix(), p.name)
def add_resource_files(self):
- files, _filter = QFileDialog.getOpenFileNames(self, _("Add File"), "", "All Files (*)")
+ files, _filter = QFileDialog.getOpenFileNames(self, _("Add File"), "", "All Files (*)", options=QFileDialog.Option.DontUseNativeDialog)
for f in files:
src = Path(f).resolve().as_posix()
self._add_resource_item('file', src, ".")
def add_resource_dir(self):
- folder = QFileDialog.getExistingDirectory(self, _("Add Dir"))
+ folder = QFileDialog.getExistingDirectory(self, _("Add Dir"), options=QFileDialog.Option.DontUseNativeDialog)
if folder:
src = Path(folder).resolve().as_posix()
dst = Path(folder).name
@@ -3199,27 +3440,27 @@ class SettingsPanel(QWidget):
def _show_lineedit_menu(self, line_edit, pos):
menu = QMenu(line_edit)
- act_undo = menu.addAction(_("Undo") if False else "Undo")
+ act_undo = menu.addAction(_("Undo"))
act_undo.triggered.connect(line_edit.undo)
act_undo.setEnabled(line_edit.isUndoAvailable())
menu.addSeparator()
- act_cut = menu.addAction("Cut")
+ act_cut = menu.addAction(_("Cut"))
act_cut.triggered.connect(line_edit.cut)
act_cut.setEnabled(line_edit.hasSelectedText() and not line_edit.isReadOnly())
- act_copy = menu.addAction("Copy")
+ act_copy = menu.addAction(_("Copy"))
act_copy.triggered.connect(line_edit.copy)
act_copy.setEnabled(line_edit.hasSelectedText())
- act_paste = menu.addAction("Paste")
+ act_paste = menu.addAction(_("Paste"))
act_paste.triggered.connect(line_edit.paste)
act_paste.setEnabled(not line_edit.isReadOnly())
menu.addSeparator()
- act_select_all = menu.addAction("Select All")
+ act_select_all = menu.addAction(_("Select All"))
act_select_all.triggered.connect(line_edit.selectAll)
menu.exec(line_edit.mapToGlobal(pos))
@@ -3305,8 +3546,8 @@ class ScriptAnalysisThread(QThread):
app_name = Path(self.path).stem
version = ""
- author = "My Studio"
- desc = "Python Executable"
+ author = "Independent Developer"
+ desc = "Desktop Application"
script_imports = set()
try:
@@ -3422,6 +3663,9 @@ class PackingThread(QThread):
stripped = line.rstrip('\r\n')
self.all_raw_logs.append(stripped)
+
+ if silent_error:
+ continue
buffer.append(stripped)
if len(buffer) >= 15 or (time.time() - last_emit) > 0.1:
@@ -3429,7 +3673,8 @@ class PackingThread(QThread):
buffer.clear()
last_emit = time.time()
- if buffer: self.progress.emit('\n'.join(buffer))
+ if buffer and not silent_error:
+ self.progress.emit('\n'.join(buffer))
self.process.wait()
if is_timeout[0]:
@@ -3445,9 +3690,14 @@ class PackingThread(QThread):
return False
finally:
if timer: timer.cancel()
- if self.process and self.process.stdout:
+ if self.process:
+ if self.process.stdout:
+ try:
+ self.process.stdout.close()
+ except Exception:
+ pass
try:
- self.process.stdout.close()
+ self.process.wait(timeout=5)
except Exception:
pass
@@ -3551,6 +3801,199 @@ class PackingThread(QThread):
}
return {"is_code_error": False}
+ def auto_sign_executable(self, target_path: Path) -> bool:
+ is_macos = (sys.platform == 'darwin')
+ enable_sign_setting = self.params.get('enable_sign', False)
+
+ if not is_macos and not enable_sign_setting:
+ return True
+
+ self.progress.emit(_("[INFO] Applying smart digital signature..."))
+
+ if os.name == 'nt':
+ if target_path.is_file():
+ for _wait in range(6):
+ try:
+ with open(target_path, 'r+b'):
+ break
+ except (IOError, OSError):
+ time.sleep(0.5)
+
+ cert_path = self.params.get('cert_path', '').strip()
+ cert_pass = self.params.get('cert_pass', '').strip()
+
+ targets = []
+ if target_path.is_dir():
+ targets.extend(list(target_path.rglob("*.exe")))
+ targets.extend(list(target_path.rglob("*.dll")))
+ targets.extend(list(target_path.rglob("*.pyd")))
+ else:
+ targets.append(target_path)
+
+ if not targets:
+ return True
+
+ tsa_servers = [
+ "http://timestamp.digicert.com",
+ "http://ts.ssl.com",
+ "http://timestamp.sectigo.com",
+ "http://timestamp.acs.microsoft.com",
+ "http://timestamp.comodoca.com",
+ ]
+
+ signtool_exe = self._find_signtool()
+ success_all = True
+
+ for target_file in targets:
+ target_str = target_file.resolve().as_posix()
+ signed_with_ts = False
+
+ if signtool_exe:
+ signed_with_ts = self._sign_with_signtool(
+ signtool_exe, target_str, cert_path, cert_pass, tsa_servers
+ )
+ if signed_with_ts and target_file == targets[0]:
+ self.progress.emit(_("[INFO] Applied digital signature with timestamp ({tsa})...", tsa="RFC3161/signtool"))
+
+ if not signed_with_ts:
+ signed_with_ts = self._sign_with_powershell(
+ target_str, cert_path, cert_pass, tsa_servers, is_first=(target_file == targets[0])
+ )
+
+ if not signed_with_ts:
+ success_all = False
+
+ if success_all:
+ self.progress.emit(_("[SUCCESS] Digital signature applied successfully!"))
+ return True
+ else:
+ self.progress.emit(_("[WARN] Smart signing failed, but build output is retained."))
+ return False
+
+ elif is_macos:
+ target_posix = target_path.resolve().as_posix()
+ cmd = ["codesign", "--force", "--deep", "--options", "runtime", "--sign", "-", target_posix]
+
+ ok = self.run_cmd(cmd, silent_error=True)
+ if not ok:
+ fallback_cmd = ["codesign", "--force", "--deep", "--sign", "-", target_posix]
+ ok = self.run_cmd(fallback_cmd, silent_error=True)
+
+ if ok:
+ self.progress.emit(_("[SUCCESS] Digital signature applied successfully!"))
+ return True
+ else:
+ self.progress.emit(_("[WARN] Smart signing failed, but build output is retained."))
+ return False
+
+ return True
+
+ def _find_signtool(self) -> str:
+ signtool = shutil.which("signtool") or shutil.which("signtool.exe")
+ if signtool:
+ return signtool
+
+ sdk_base = Path(os.environ.get("ProgramFiles(x86)", "C:\\Program Files (x86)")) / "Windows Kits" / "10" / "bin"
+ if sdk_base.exists():
+ candidates = sorted(sdk_base.glob("10.*/x64/signtool.exe"), reverse=True)
+ if candidates:
+ return candidates[0].as_posix()
+
+ return ""
+
+ def _sign_with_signtool(self, signtool_exe, target_path, cert_path, cert_pass, tsa_servers) -> bool:
+ thumbprint = None
+
+ if not (cert_path and Path(cert_path).exists()):
+ company_name = self.params.get('ver_comp', '').strip() or 'QPyPack App'
+ safe_company = company_name.replace("'", "''").replace('"', '""')
+ ps_create = (
+ f'$subject = "CN={safe_company}"; '
+ '$cert = Get-ChildItem Cert:\\CurrentUser\\My -CodeSigningCert | Where-Object { $_.Subject -eq $subject } | Select-Object -First 1; '
+ 'if (-not $cert) { $cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject $subject -CertStoreLocation Cert:\\CurrentUser\\My }; '
+ 'Write-Output $cert.Thumbprint'
+ )
+ try:
+ kw = {"capture_output": True, "text": True, "timeout": 10, "errors": "ignore"}
+ if os.name == 'nt':
+ kw["creationflags"] = subprocess.CREATE_NO_WINDOW
+ res = subprocess.run(
+ ["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", ps_create],
+ **kw
+ )
+ thumbprint = res.stdout.strip().split('\n')[-1].strip() if res.returncode == 0 else ""
+ if not thumbprint:
+ return False
+ except Exception:
+ return False
+
+ for tsa in tsa_servers:
+ if self._is_cancelled:
+ return False
+
+ if cert_path and Path(cert_path).exists():
+ cmd = [signtool_exe, "sign", "/f", cert_path, "/fd", "sha256",
+ "/tr", tsa, "/td", "sha256"]
+ if cert_pass:
+ cmd.extend(["/p", cert_pass])
+ cmd.append(target_path)
+ else:
+ cmd = [signtool_exe, "sign", "/sha1", thumbprint, "/fd", "sha256",
+ "/tr", tsa, "/td", "sha256", target_path]
+
+ if self.run_cmd(cmd, silent_error=True, timeout=30):
+ return True
+
+ return False
+
+ def _sign_with_powershell(self, target_path, cert_path, cert_pass, tsa_servers, is_first=False) -> bool:
+ company_name = self.params.get('ver_comp', '').strip()
+ if not company_name:
+ app_title = self.params.get('app_name', 'App').strip() or 'App'
+ company_name = f"{app_title} Developer"
+
+ safe_company = company_name.replace("'", "''").replace('"', '""')
+
+ if cert_path and Path(cert_path).exists():
+ safe_pwd = (cert_pass or '').replace("'", "''")
+ pass_part = f' -Password (ConvertTo-SecureString -String \'{safe_pwd}\' -Force -AsPlainText)' if cert_pass else ''
+ base_cert_script = f'$cert = Get-PfxCertificate -FilePath "{cert_path}"{pass_part}; '
+ else:
+ base_cert_script = (
+ f'$subject = "CN={safe_company}"; '
+ '$cert = Get-ChildItem Cert:\\CurrentUser\\My -CodeSigningCert | Where-Object { $_.Subject -eq $subject } | Select-Object -First 1; '
+ 'if (-not $cert) { '
+ '$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject $subject -CertStoreLocation Cert:\\CurrentUser\\My '
+ '}; '
+ )
+
+ for tsa in tsa_servers:
+ if self._is_cancelled:
+ return False
+
+ ps_cmd = (
+ f'{base_cert_script}'
+ f'$sig = Set-AuthenticodeSignature -FilePath "{target_path}" -Certificate $cert '
+ f'-TimestampServer "{tsa}" -HashAlgorithm SHA256; '
+ f'if ($sig.Status -ne "Valid" -and $sig.Status -ne "UnknownError") {{ exit 1 }}; '
+ f'if ($null -eq $sig.TimeStamperCertificate) {{ exit 1 }}'
+ )
+ if self.run_cmd(["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", ps_cmd],
+ silent_error=True, timeout=30):
+ if is_first:
+ self.progress.emit(_("[INFO] Applied digital signature with timestamp ({tsa})...", tsa=tsa))
+ return True
+
+ self.progress.emit(_("[WARN] Timestamp server connection timed out, performing local fast signing..."))
+
+ ps_cmd_no_ts = (
+ f'{base_cert_script}'
+ f'$sig = Set-AuthenticodeSignature -FilePath "{target_path}" -Certificate $cert -HashAlgorithm SHA256; '
+ f'if ($sig.Status -ne "Valid" -and $sig.Status -ne "UnknownError") {{ exit 1 }}'
+ )
+ return self.run_cmd(["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", ps_cmd_no_ts],
+ silent_error=True, timeout=15)
+
def run(self):
os.environ["NUITKA_ACCEPT_DOWNLOADS"] = "yes"
engine = self.params['engine']
@@ -4310,6 +4753,9 @@ class PackingThread(QThread):
self.progress.emit(_("[ERROR] Could not locate valid executable product in temporary build directory: {path}", path=str(src_out)))
if success and final_out.exists():
+ if self.params.get('enable_sign'):
+ self.auto_sign_executable(final_out)
+
self.progress.emit(_("[INFO] Validating output files and generating final product..."))
if self.params.get('auto_save_log') and self.all_raw_logs:
try:
@@ -5143,8 +5589,8 @@ class MainWindow(QMainWindow):
if version: self.settings_panel.ver_ver.setText(version)
else: self.settings_panel.ver_ver.setText("1.0.0")
- self.settings_panel.ver_comp.setText(_(author) if author == "My Studio" else author)
- self.settings_panel.ver_desc.setText(_(desc) if desc == "Python Executable" else desc)
+ self.settings_panel.ver_comp.setText(_(author) if author == "Independent Developer" else author)
+ self.settings_panel.ver_desc.setText(_(desc) if desc == "Desktop Application" else desc)
gui_libs = {
'pyqt5', 'pyqt6', 'pyside2', 'pyside6', 'tkinter', 'wx', 'kivy', 'libavg',
@@ -5333,6 +5779,9 @@ class MainWindow(QMainWindow):
'engine': engine,
'python_exe': raw_py,
'script_path': self.script_path,
+ 'enable_sign': sp.enable_sign_check.isChecked(),
+ 'cert_path': sp.cert_path_edit.text().strip(),
+ 'cert_pass': sp.cert_pass_edit.text().strip(),
'app_name': app_name,
'onefile': sp.rb_onefile.isChecked(),
'contents_dir': sp.contents_dir_edit.text().strip() or '_internal',
@@ -5366,6 +5815,7 @@ class MainWindow(QMainWindow):
'lite_mode': sp.rb_lite_mode.isChecked(),
'pyi_version': sp.pyi_ver_edit.text().strip(),
'nuitka_version': sp.nuitka_ver_edit.text().strip(),
+ 'mappings': mappings,
}
self.log_concise.clear()
@@ -5445,8 +5895,8 @@ class MainWindow(QMainWindow):
self.settings_panel.reqs_file_edit.clear()
self.settings_panel.out_dir_edit.clear()
self.settings_panel.ver_ver.setText("1.0.0")
- self.settings_panel.ver_comp.setText(_("My Studio"))
- self.settings_panel.ver_desc.setText(_("Python Executable"))
+ self.settings_panel.ver_comp.setText(_("Independent Developer"))
+ self.settings_panel.ver_desc.setText(_("Desktop Application"))
self.log_concise.clear()
self.log_detailed.clear()
@@ -5591,7 +6041,7 @@ class MainWindow(QMainWindow):
if self.script_path:
default_name = f"qpypack_{Path(self.script_path).stem}.log"
- fp, _filter = QFileDialog.getSaveFileName(self, _("Export Log..."), default_name, "Log Files (*.log);;Text Files (*.txt);;All Files (*)")
+ fp, _filter = QFileDialog.getSaveFileName(self, _("Export Log..."), default_name, "Log Files (*.log);;Text Files (*.txt);;All Files (*)", options=QFileDialog.Option.DontUseNativeDialog)
if fp:
try:
Path(fp).write_text(content, encoding='utf-8')