1 Commits
main ... meson

Author SHA1 Message Date
837a83a32b chore(build): switch from pyproject to meson build system
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
2026-01-18 13:40:51 +05:00
26 changed files with 1641 additions and 91 deletions

View File

@@ -2,8 +2,14 @@ name: Nightly Build - AppImage, Arch, Fedora
on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to build'
required: false
default: 'main'
env:
BUILD_BRANCH: ${{ inputs.branch || 'main' }}
PKGDEST: "/tmp/portprotonqt"
PACKAGE: "portprotonqt"
@@ -22,6 +28,8 @@ jobs:
pacman -Syu --noconfirm --disable-download-timeout --needed git wget gnupg nodejs npm xorg-server-xvfb zsync
- uses: https://gitea.com/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
ref: ${{ env.BUILD_BRANCH }}
- name: Install appimage dependencies
run: |
@@ -55,9 +63,8 @@ jobs:
steps:
- name: Install build dependencies
run: |
dnf install -y git rpmdevtools python3-devel python3-wheel python3-pip \
python3-build pyproject-rpm-macros systemd-rpm-macros python3-setuptools \
redhat-rpm-config nodejs npm
dnf install -y git rpmdevtools meson ninja-build python3-devel \
systemd-rpm-macros redhat-rpm-config nodejs npm
- name: Setup rpmbuild environment
run: |
@@ -68,10 +75,13 @@ jobs:
- name: Checkout repo
uses: https://gitea.com/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
ref: ${{ env.BUILD_BRANCH }}
- name: Copy fedora.spec
run: |
cp build-aux/fedora-git.spec /home/rpmbuild/SPECS/${{ env.PACKAGE }}.spec
sed "s|git clone https://git.linux-gaming.ru/Boria138/PortProtonQt.git|git clone -b ${{ env.BUILD_BRANCH }} https://git.linux-gaming.ru/Boria138/PortProtonQt.git|" \
build-aux/fedora-git.spec > /home/rpmbuild/SPECS/${{ env.PACKAGE }}.spec
chown -R rpmbuild:users /home/rpmbuild
- name: Build RPM
@@ -118,13 +128,16 @@ jobs:
- name: Build
run: |
cd /__w/portproton-repo
git clone https://git.linux-gaming.ru/Boria138/PortProtonQt.git
git clone -b ${{ env.BUILD_BRANCH }} https://git.linux-gaming.ru/Boria138/PortProtonQt.git
cd /__w/portproton-repo/PortProtonQt/build-aux
sed -i "s|source=(\"git+https://git.linux-gaming.ru/Boria138/PortProtonQt.git\")|source=(\"git+https://git.linux-gaming.ru/Boria138/PortProtonQt.git#branch=${{ env.BUILD_BRANCH }}\")|" PKGBUILD-git
chown user -R ..
su user -c "yes '' | makepkg --noconfirm -s -p PKGBUILD-git"
- name: Checkout
uses: https://gitea.com/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
ref: ${{ env.BUILD_BRANCH }}
- name: Upload Arch package
uses: https://gitea.com/actions/gitea-upload-artifact@v4

View File

@@ -109,9 +109,8 @@ jobs:
steps:
- name: Install build dependencies
run: |
dnf install -y git rpmdevtools python3-devel python3-wheel python3-pip \
python3-build pyproject-rpm-macros systemd-rpm-macros python3-setuptools \
redhat-rpm-config nodejs npm
dnf install -y git rpmdevtools meson ninja-build python3-devel \
systemd-rpm-macros redhat-rpm-config nodejs npm
- name: Setup rpmbuild environment
run: |

View File

@@ -1,4 +1,4 @@
name: Check Translations (disabled until yaspeller is fixed)
name: Check Translations
run-name: Check spelling in translation files
on:
push:

View File

@@ -108,9 +108,8 @@ jobs:
steps:
- name: Install build dependencies
run: |
dnf install -y git rpmdevtools python3-devel python3-wheel python3-pip \
python3-build pyproject-rpm-macros python3-setuptools \
redhat-rpm-config nodejs npm
dnf install -y git rpmdevtools meson ninja-build python3-devel \
systemd-rpm-macros redhat-rpm-config nodejs npm
- name: Setup rpmbuild environment
run: |

View File

@@ -7,18 +7,15 @@ url="https://git.linux-gaming.ru/Boria138/PortProtonQt"
license=('GPL-3.0')
depends=('python-requests' 'python-babel' 'python-evdev' 'python-pyudev' 'python-orjson'
'python-psutil' 'python-tqdm' 'python-vdf' 'python-libarchive-c' 'pyside6' 'python-rapidfuzz' 'icoextract' 'python-pillow' 'perl-image-exiftool' 'xdg-utils' 'python-beautifulsoup4' 'python-websocket-client' 'cabextract' 'unzip' 'curl' 'unrar' 'qt6-svg')
makedepends=('python-'{'build','installer','setuptools','wheel'})
makedepends=('meson' 'ninja')
source=("git+https://git.linux-gaming.ru/Boria138/PortProtonQt#tag=v$pkgver")
sha256sums=('SKIP')
build() {
cd "$srcdir/PortProtonQt"
python -m build --wheel --no-isolation
arch-meson PortProtonQt build
meson compile -C build
}
package() {
cd "$srcdir/PortProtonQt"
python -m installer --destdir="$pkgdir" dist/*.whl
cp -r build-aux/share "$pkgdir/usr/"
cp -r build-aux/lib "$pkgdir/usr/"
meson install -C build --destdir "$pkgdir"
}

View File

@@ -7,7 +7,7 @@ url="https://git.linux-gaming.ru/Boria138/PortProtonQt"
license=('GPL-3.0')
depends=('python-requests' 'python-babel' 'python-evdev' 'python-pyudev' 'python-orjson'
'python-psutil' 'python-tqdm' 'python-vdf' 'python-libarchive-c' 'pyside6' 'icoextract' 'python-pillow' 'python-rapidfuzz' 'perl-image-exiftool' 'xdg-utils' 'python-beautifulsoup4' 'python-websocket-client' 'cabextract' 'unzip' 'curl' 'unrar' 'qt6-svg')
makedepends=('python-'{'build','installer','setuptools','wheel'})
makedepends=('meson' 'ninja')
source=("git+https://git.linux-gaming.ru/Boria138/PortProtonQt.git")
sha256sums=('SKIP')
@@ -17,13 +17,10 @@ pkgver() {
}
build() {
cd "$srcdir/PortProtonQt"
python -m build --wheel --no-isolation
arch-meson PortProtonQt build
meson compile -C build
}
package() {
cd "$srcdir/PortProtonQt"
python -m installer --destdir="$pkgdir" dist/*.whl
cp -r build-aux/share "$pkgdir/usr/"
cp -r build-aux/lib "$pkgdir/usr/"
meson install -C build --destdir "$pkgdir"
}

View File

@@ -1,12 +1,12 @@
%global pypi_name portprotonqt
%global pypi_version 0.1.1
%global pypi_version 0.1.10
%global oname PortProtonQt
%global build_timestamp %(date +"%Y%m%d")
%global _python_no_extras_requires 1
%global rel_build 1.git.%{build_timestamp}%{?dist}
Name: python-%{pypi_name}-git
Name: %{pypi_name}-git
Version: %{pypi_version}
Release: %{rel_build}
Summary: Modern GUI for managing and launching games from PortProton, Steam, and Epic Games Store (development build)
@@ -15,21 +15,15 @@ License: GPL-3.0
URL: https://git.linux-gaming.ru/Boria138/PortProtonQt
BuildArch: noarch
BuildRequires: meson >= 0.61.2
BuildRequires: ninja-build
BuildRequires: python3-devel
BuildRequires: python3-wheel
BuildRequires: python3-pip
BuildRequires: python3-build
BuildRequires: pyproject-rpm-macros
BuildRequires: python3dist(setuptools)
BuildRequires: git
BuildRequires: systemd-rpm-macros
%description
%{summary}
Obsoletes: python3-%{pypi_name}-git < %{version}-%{release}
Provides: python3-%{pypi_name}-git = %{version}-%{release}
%package -n python3-%{pypi_name}-git
Summary: %{summary}
%{?python_provide:%python_provide python3-%{pypi_name}}
Requires: python3-babel
Requires: python3-evdev
Requires: python3-icoextract
@@ -55,7 +49,7 @@ Requires: unzip
Requires: curl
Requires: unrar
%description -n python3-%{pypi_name}-git
%description
This application provides a sleek, intuitive graphical interface for managing and launching games from PortProton, Steam, and Epic Games Store. It consolidates your game libraries into a single, user-friendly hub for seamless navigation and organization. Its lightweight structure and cross-platform support deliver a cohesive gaming experience, eliminating the need for multiple launchers. Unique PortProton integration enhances Linux gaming, enabling effortless play of Windows-based titles with minimal setup.
%{?python_disable_dependency_generator}
@@ -65,17 +59,17 @@ git clone https://git.linux-gaming.ru/Boria138/PortProtonQt.git
%build
cd %{oname}
%pyproject_wheel
%meson -Dpython_libdir=%{python3_sitelib} -Dudevdir=%{_udevrulesdir}
%meson_build
%install
cd %{oname}
%pyproject_install
%pyproject_save_files %{pypi_name}
cp -r build-aux/share %{buildroot}/usr/
cp -r build-aux/lib %{buildroot}/usr/
%meson_install
%find_lang %{pypi_name}
%files -n python3-%{pypi_name}-git -f %{pyproject_files}
%files -f %{oname}/%{pypi_name}.lang
%{_bindir}/%{pypi_name}
%{python3_sitelib}/%{pypi_name}/
%{_datadir}/icons/hicolor/scalable/apps/ru.linux_gaming.PortProtonQt.svg
%{_metainfodir}/ru.linux_gaming.PortProtonQt.metainfo.xml
%{_udevrulesdir}/60-portprotonqt.rules

View File

@@ -3,7 +3,7 @@
%global oname PortProtonQt
%global _python_no_extras_requires 1
Name: python-%{pypi_name}
Name: %{pypi_name}
Version: %{pypi_version}
Release: 1%{?dist}
Summary: Modern GUI for managing and launching games from PortProton, Steam, and Epic Games Store
@@ -12,21 +12,15 @@ License: GPL-3.0
URL: https://git.linux-gaming.ru/Boria138/PortProtonQt
BuildArch: noarch
BuildRequires: meson >= 0.61.2
BuildRequires: ninja-build
BuildRequires: python3-devel
BuildRequires: python3-wheel
BuildRequires: python3-pip
BuildRequires: python3-build
BuildRequires: pyproject-rpm-macros
BuildRequires: python3dist(setuptools)
BuildRequires: git
BuildRequires: systemd-rpm-macros
%description
%{summary}
Obsoletes: python3-%{pypi_name} < %{version}-%{release}
Provides: python3-%{pypi_name} = %{version}-%{release}
%package -n python3-%{pypi_name}
Summary: %{summary}
%{?python_provide:%python_provide python3-%{pypi_name}}
Requires: python3-babel
Requires: python3-evdev
Requires: python3-icoextract
@@ -52,7 +46,7 @@ Requires: unzip
Requires: curl
Requires: unrar
%description -n python3-%{pypi_name}
%description
This application provides a sleek, intuitive graphical interface for managing and launching games from PortProton, Steam, and Epic Games Store. It consolidates your game libraries into a single, user-friendly hub for seamless navigation and organization. Its lightweight structure and cross-platform support deliver a cohesive gaming experience, eliminating the need for multiple launchers. Unique PortProton integration enhances Linux gaming, enabling effortless play of Windows-based titles with minimal setup.
%{?python_disable_dependency_generator}
@@ -64,17 +58,17 @@ git checkout v%{pypi_version}
%build
cd %{oname}
%pyproject_wheel
%meson -Dpython_libdir=%{python3_sitelib} -Dudevdir=%{_udevrulesdir}
%meson_build
%install
cd %{oname}
%pyproject_install
%pyproject_save_files %{pypi_name}
cp -r build-aux/share %{buildroot}/usr/
cp -r build-aux/lib %{buildroot}/usr/
%meson_install
%find_lang %{pypi_name}
%files -n python3-%{pypi_name} -f %{pyproject_files}
%files -f %{oname}/%{pypi_name}.lang
%{_bindir}/%{pypi_name}
%{python3_sitelib}/%{pypi_name}/
%{_datadir}/icons/hicolor/scalable/apps/ru.linux_gaming.PortProtonQt.svg
%{_metainfodir}/ru.linux_gaming.PortProtonQt.metainfo.xml
%{_udevrulesdir}/60-portprotonqt.rules

9
build-aux/portprotonqt Normal file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env python3
import sys
from portprotonqt.app import main
if __name__ == "__main__":
sys.exit(main())

View File

@@ -13,6 +13,7 @@ APPIMAGE_RECIPE = BASE_DIR / "build-aux" / "AppImageBuilder.yml"
ARCH_PKGBUILD = BASE_DIR / "build-aux" / "PKGBUILD"
FEDORA_SPEC = BASE_DIR / "build-aux" / "fedora.spec"
PYPROJECT = BASE_DIR / "pyproject.toml"
MESON_BUILD = BASE_DIR / "meson.build"
APP_PY = BASE_DIR / "portprotonqt" / "app.py"
GITEA_WORKFLOW = BASE_DIR / ".gitea" / "workflows" / "build.yml"
CHANGELOG = BASE_DIR / "CHANGELOG.md"
@@ -69,6 +70,19 @@ def bump_pyproject(path: Path, old: str, new: str) -> bool:
path.write_text(new_text, encoding='utf-8')
return bool(count)
def bump_meson(path: Path, old: str, new: str) -> bool:
"""
Update version in meson.build
"""
if not path.exists():
return False
text = path.read_text(encoding='utf-8')
pattern = re.compile(r"(version:\s*)'" + re.escape(old) + r"'")
new_text, count = pattern.subn(lambda m: m.group(1) + f"'{new}'", text)
if count:
path.write_text(new_text, encoding='utf-8')
return bool(count)
def bump_app_py(path: Path, old: str, new: str) -> bool:
"""
Update __app_version__ in app.py
@@ -121,6 +135,7 @@ def main():
(ARCH_PKGBUILD, bump_arch),
(FEDORA_SPEC, bump_fedora),
(PYPROJECT, bump_pyproject),
(MESON_BUILD, bump_meson),
(APP_PY, bump_app_py),
(GITEA_WORKFLOW, bump_workflow),
(CHANGELOG, bump_changelog)

View File

@@ -17,8 +17,9 @@ README_EN = GUIDE_DIR / "README.md"
README_RU = GUIDE_DIR / "README.ru.md"
LOCALES_PATH = Path(__file__).parent.parent / "portprotonqt" / "locales"
THEMES_PATH = Path(__file__).parent.parent / "portprotonqt" / "themes"
MESON_BUILD = Path(__file__).parent.parent / "portprotonqt" / "meson.build"
README_FILES = [README_EN, README_RU]
POT_FILE = LOCALES_PATH / "messages.pot"
POT_FILE = LOCALES_PATH / "portprotonqt.pot"
# ---------- Версия проекта ----------
def _get_version() -> str:
@@ -27,16 +28,16 @@ def _get_version() -> str:
# ---------- Обновление README ----------
def _update_coverage(lines: list[str]) -> None:
# Парсим статистику из вывода pybabel --statistics
locales_stats = [line for line in lines if line.endswith(".po")]
locales_stats = [line for line in lines if "portprotonqt.po" in line]
# Извлекаем (count, pct, locale) и сортируем
rows = sorted(
(m := re.search(
row for stat in locales_stats
if (m := re.search(
r"""(\d+\ of\ \d+).* # message counts
\((\d+\%)\).* # message percentage
locales\/(.*)\/LC_MESSAGES # locale name""",
locales\/([^/]+)\/LC_MESSAGES # locale name""",
stat, re.VERBOSE
)) and m.groups()
for stat in locales_stats
)) and (row := m.groups())
)
for md_file in README_FILES:
@@ -59,14 +60,14 @@ def _update_coverage(lines: list[str]) -> None:
"| Локаль | Прогресс | Переведено |\n"
"| :----- | -------: | ---------: |\n"
)
fmt = lambda count, pct, loc: f"| [{loc}](./{loc}/LC_MESSAGES/messages.po) | {pct} | {count.replace(' of ', ' из ')} |"
fmt = lambda count, pct, loc: f"| [{loc}](./{loc}/LC_MESSAGES/portprotonqt.po) | {pct} | {count.replace(' of ', ' из ')} |"
else:
table_header = (
"<!-- Auto-generated coverage table -->\n\n"
"| Locale | Progress | Translated |\n"
"| :----- | -------: | ---------: |\n"
)
fmt = lambda count, pct, loc: f"| [{loc}](./{loc}/LC_MESSAGES/messages.po) | {pct} | {count} |"
fmt = lambda count, pct, loc: f"| [{loc}](./{loc}/LC_MESSAGES/portprotonqt.po) | {pct} | {count} |"
# Собираем строки и добавляем '---' в конце
coverage_table = (
@@ -100,7 +101,7 @@ def _update_coverage(lines: list[str]) -> None:
def compile_locales() -> None:
CommandLineInterface().run([
"pybabel", "compile", "--use-fuzzy", "--directory",
f"{LOCALES_PATH.resolve()}", "--statistics"
f"{LOCALES_PATH.resolve()}", "--domain=portprotonqt", "--statistics"
])
def extract_strings() -> None:
@@ -121,10 +122,39 @@ def update_locales() -> None:
"pybabel", "update",
f"--input-file={POT_FILE.resolve()}",
f"--output-dir={LOCALES_PATH.resolve()}",
"--domain=portprotonqt",
"--ignore-obsolete",
"--update-header-comment",
])
def _update_meson_locales(new_locales: list[str]) -> None:
"""Обновляет список языков в meson.build."""
if not MESON_BUILD.exists():
return
text = MESON_BUILD.read_text(encoding="utf-8")
# Ищем foreach lang : ['de', 'es', 'pt', 'ru']
pattern = r"(foreach\s+lang\s*:\s*\[)([^\]]+)(\])"
match = re.search(pattern, text)
if not match:
return
# Парсим текущий список языков
current_langs_str = match.group(2)
current_langs = re.findall(r"'([^']+)'", current_langs_str)
# Добавляем новые языки и сортируем
all_langs = sorted(set(current_langs) | set(new_locales))
# Формируем новый список
new_langs_str = ", ".join(f"'{lang}'" for lang in all_langs)
new_text = text[:match.start()] + match.group(1) + new_langs_str + match.group(3) + text[match.end():]
if new_text != text:
MESON_BUILD.write_text(new_text, encoding="utf-8")
print(f"Updated meson.build with locales: {all_langs}")
def create_new(locales: list[str]) -> None:
if not POT_FILE.exists():
extract_strings()
@@ -133,8 +163,11 @@ def create_new(locales: list[str]) -> None:
"pybabel", "init",
f"--input-file={POT_FILE.resolve()}",
f"--output-dir={LOCALES_PATH.resolve()}",
"--domain=portprotonqt",
f"--locale={locale}"
])
# Обновляем meson.build с новыми локалями
_update_meson_locales(locales)
# ---------- Игнорируемые префиксы для spellcheck ----------
IGNORED_PREFIXES = ()
@@ -148,6 +181,41 @@ def load_ignored_prefixes(ignore_file=".spellignore"):
IGNORED_PREFIXES = load_ignored_prefixes() + ("PortProton", "flatpak")
# ---------- Проверка fuzzy строк ----------
def find_fuzzy_entries(filepath: Path) -> list[tuple[int, str, str]]:
"""Находит fuzzy записи в .po файле. Возвращает список (номер_строки, msgid, флаги)."""
fuzzy_entries = []
lines = filepath.read_text(encoding='utf-8').splitlines()
i = 0
while i < len(lines):
line = lines[i].strip()
# Ищем комментарий с флагами, содержащий fuzzy
if line.startswith('#,') and 'fuzzy' in line:
flags = line[2:].strip()
line_num = i + 1
# Ищем следующий msgid
msgid = ""
i += 1
while i < len(lines):
next_line = lines[i].strip()
if next_line.startswith('msgid '):
match = re.match(r'^msgid\s+"(.*)"', next_line)
if match:
msgid = match.group(1)
i += 1
# Собираем многострочный msgid
while i < len(lines) and lines[i].strip().startswith('"'):
msgid += lines[i].strip()[1:-1]
i += 1
break
i += 1
# Пропускаем пустой msgid (заголовок PO файла)
if msgid:
fuzzy_entries.append((line_num, msgid, flags))
else:
i += 1
return fuzzy_entries
# ---------- Проверка орфографии с параллелизмом ----------
speller = YandexSpeller()
MSGID_RE = re.compile(r'^msgid\s+"(.*)"')
@@ -208,17 +276,36 @@ def main(args) -> int:
if args.create_new:
create_new(args.create_new)
if args.spellcheck:
files = list(LOCALES_PATH.glob("**/*.po")) + [POT_FILE]
files = list(LOCALES_PATH.glob("**/portprotonqt.po")) + [POT_FILE]
seen = set(); has_err = False
issues_summary = defaultdict(list)
fuzzy_summary = defaultdict(list)
for f in files:
if not f.exists() or f in seen: continue
seen.add(f)
# Проверка fuzzy строк (только для .po файлов)
if f.suffix == '.po':
fuzzy_entries = find_fuzzy_entries(f)
if fuzzy_entries:
fuzzy_summary[f] = fuzzy_entries
has_err = True
if check_file(f, issues_summary):
has_err = True
else:
print(f"{f} — no errors found.")
if has_err:
if f not in fuzzy_summary:
print(f"{f} — no errors found.")
# Вывод fuzzy строк
if fuzzy_summary:
print("\n⚠️ Fuzzy Entries (require review before release):")
for file, entries in fuzzy_summary.items():
print(f"\n{file}")
print("-----")
for idx, (line_num, msgid, flags) in enumerate(entries, 1):
print(f"{idx}. Line {line_num}: [{flags}]")
print(f" msgid: \"{msgid[:80]}{'...' if len(msgid) > 80 else ''}\"")
print("-----")
# Вывод орфографических ошибок
if issues_summary:
print("\n📋 Summary of Spelling Errors:")
for file, errs in issues_summary.items():
print(f"\n{file}")

View File

@@ -13,7 +13,7 @@
## 📖 Overview
Localization in `PortProtonQT` is powered by `Babel` using `.po/.mo` files stored under `LC_MESSAGES/messages.po` for each language.
Localization in `PortProtonQT` is powered by `Babel` using `.po/.mo` files stored under `LC_MESSAGES/portprotonqt.po` for each language.
Current translation status:
@@ -21,9 +21,10 @@ Current translation status:
| Locale | Progress | Translated |
| :----- | -------: | ---------: |
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 376 |
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 376 |
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 376 of 376 |
| [de](./de/LC_MESSAGES/portprotonqt.po) | 0% | 0 of 376 |
| [es](./es/LC_MESSAGES/portprotonqt.po) | 0% | 0 of 376 |
| [pt](./pt/LC_MESSAGES/portprotonqt.po) | 0% | 0 of 376 |
| [ru](./ru/LC_MESSAGES/portprotonqt.po) | 100% | 376 of 376 |
---
@@ -39,7 +40,7 @@ source .venv/bin/activate
python dev-scripts/l10n.py --create-new <locale_code>
```
2. Edit the file `portprotonqt/locales/<locale>/LC_MESSAGES/messages.po` in Poedit or any text editor.
2. Edit the file `portprotonqt/locales/<locale>/LC_MESSAGES/portprotonqt.po` in Poedit or any text editor.
---

View File

@@ -13,7 +13,7 @@
## 📖 Обзор
Локализация в `PortProtonQT` осуществляется через систему `.po/.mo` файлов и управляется утилитой `Babel`. Все переводы находятся в подкаталогах вида `LC_MESSAGES/messages.po` для каждой поддерживаемой локали.
Локализация в `PortProtonQT` осуществляется через систему `.po/.mo` файлов и управляется утилитой `Babel`. Все переводы находятся в подкаталогах вида `LC_MESSAGES/portprotonqt.po` для каждой поддерживаемой локали.
Текущий статус перевода:
@@ -21,9 +21,10 @@
| Локаль | Прогресс | Переведено |
| :----- | -------: | ---------: |
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 376 |
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 376 |
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 376 из 376 |
| [de](./de/LC_MESSAGES/portprotonqt.po) | 0% | 0 из 376 |
| [es](./es/LC_MESSAGES/portprotonqt.po) | 0% | 0 из 376 |
| [pt](./pt/LC_MESSAGES/portprotonqt.po) | 0% | 0 из 376 |
| [ru](./ru/LC_MESSAGES/portprotonqt.po) | 100% | 376 из 376 |
---
@@ -39,7 +40,7 @@ source .venv/bin/activate
python dev-scripts/l10n.py --create-new <код_локали>
```
2. Отредактируйте файл `portprotonqt/locales/<локаль>/LC_MESSAGES/messages.po` в Poedit или любом текстовом редакторе.
2. Отредактируйте файл `portprotonqt/locales/<локаль>/LC_MESSAGES/portprotonqt.po` в Poedit или любом текстовом редакторе.
---

83
meson.build Normal file
View File

@@ -0,0 +1,83 @@
project('portprotonqt',
version: '0.1.10',
meson_version: '>= 0.61.2',
license: 'GPL-3.0',
)
# Project directories
prefix = get_option('prefix')
datadir = prefix / get_option('datadir')
bindir = prefix / get_option('bindir')
# Python module for site-packages path
python = import('python')
python3 = python.find_installation('python3')
pythondir = join_paths(prefix, python3.get_path('purelib'))
python_libdir = get_option('python_libdir')
if python_libdir == ''
python_installdir = pythondir
else
python_installdir = python_libdir
endif
pkgdatadir = python_installdir / meson.project_name()
conf = configuration_data()
conf.set('PYTHON', python.find_installation('python3').full_path())
# Install Python package
subdir('portprotonqt')
# Install entry point script with proper name to avoid conflict in build directory
configured_portprotonqt = configure_file(
input: 'build-aux/portprotonqt',
output: 'portprotonqt-script',
configuration: conf,
)
# Install the configured script with the correct name
install_data(configured_portprotonqt,
install_dir: bindir,
install_mode: 'rwxr-xr-x',
rename: 'portprotonqt')
# Install desktop file
install_data(
'build-aux/share/applications/ru.linux_gaming.PortProtonQt.desktop',
install_dir: datadir / 'applications',
)
# Install icon
install_data(
'build-aux/share/icons/hicolor/scalable/apps/ru.linux_gaming.PortProtonQt.svg',
install_dir: datadir / 'icons/hicolor/scalable/apps',
)
# Install metainfo
install_data(
'build-aux/share/metainfo/ru.linux_gaming.PortProtonQt.metainfo.xml',
install_dir: datadir / 'metainfo',
)
# Install bash completion
install_data(
'build-aux/share/bash-completion/completions/portprotonqt',
install_dir: datadir / 'bash-completion/completions',
)
# Install udev rules
udevdir = get_option('udevdir')
if udevdir == ''
udev = dependency('udev', required: false)
if udev.found()
udevdir = udev.get_variable(pkgconfig: 'udevdir') / 'rules.d'
else
udevdir = prefix / get_option('libdir') / 'udev/rules.d'
endif
endif
install_data(
'build-aux/lib/udev/rules.d/60-portprotonqt.rules',
install_dir: udevdir,
)

11
meson_options.txt Normal file
View File

@@ -0,0 +1,11 @@
option('udevdir',
type: 'string',
value: '',
description: 'Directory for udev rules (auto-detected if empty)',
)
option('python_libdir',
type: 'string',
value: '',
description: 'Python site-packages directory (auto-detected if empty)',
)

View File

@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PortProtonQt 0.1.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-01-12 20:59+0500\n"
"POT-Creation-Date: 2026-01-18 11:43+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -33,11 +33,21 @@ LOCALE_MAP = {
'el': 'greek',
}
translate = gettext.translation(
domain="messages",
localedir = Path(__file__).parent / "locales",
fallback=True,
)
# Try system locale directory first, fallback to local for development
_system_localedir = Path("/usr/share/locale")
_local_localedir = Path(__file__).parent / "locales"
try:
translate = gettext.translation(
domain="portprotonqt",
localedir=_system_localedir,
)
except FileNotFoundError:
translate = gettext.translation(
domain="portprotonqt",
localedir=_local_localedir,
fallback=True,
)
_ = translate.gettext
def get_system_locale():

54
portprotonqt/meson.build Normal file
View File

@@ -0,0 +1,54 @@
# Install Python source files
install_data(
'__init__.py',
'animations.py',
'app.py',
'cli.py',
'config_utils.py',
'context_menu_manager.py',
'custom_widgets.py',
'detail_pages.py',
'dialogs.py',
'downloader.py',
'egs_api.py',
'game_card.py',
'game_library_manager.py',
'get_wine_module.py',
'howlongtobeat_api.py',
'image_utils.py',
'input_manager.py',
'keyboard_layouts.py',
'localization.py',
'logger.py',
'main_window.py',
'portproton_api.py',
'preloader.py',
'search_utils.py',
'settings_manager.py',
'steam_api.py',
'system_overlay.py',
'theme_manager.py',
'theme_security.py',
'time_utils.py',
'tray_manager.py',
'version_utils.py',
'virtual_keyboard.py',
install_dir: pkgdatadir,
)
# Install themes
install_subdir(
'themes',
install_dir: pkgdatadir,
exclude_directories: ['__pycache__'],
exclude_files: ['*.pyc'],
)
# Install locales - only .mo files (compiled translations)
# exclude_files doesn't work recursively, so we install each language manually
foreach lang : ['de', 'es', 'pt', 'ru']
install_data(
'locales' / lang / 'LC_MESSAGES' / 'portprotonqt.mo',
install_dir: get_option('localedir') / 'locales' / lang / 'LC_MESSAGES',
)
endforeach