Add English localization and MIT-licensed public release documentation
Tests / unit (de, 3.10) (push) Has been cancelled
Tests / unit (de, 3.14) (push) Has been cancelled
Tests / unit (en, 3.14) (push) Has been cancelled
Tests / unit (en, 3.10) (push) Has been cancelled

This commit is contained in:
Justin
2026-09-05 21:02:14 +02:00
parent 3579667c6e
commit dd0809e877
31 changed files with 1261 additions and 377 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
import unittest
from btd700.i18n import tr
from btd700.controller import Controller
from btd700.demo import DemoTransport
from btd700.protocol import Command as C
@@ -25,7 +26,7 @@ class ControllerTests(unittest.TestCase):
self.device.values.pop(C.GET_KEY)
status = self.controller.snapshot()
self.assertEqual(status.codec_name, 'aptX Adaptive')
self.assertEqual(status.quality, '24 Bit / 48 kHz')
self.assertEqual(status.quality, tr('24 Bit') + ' / 48 kHz')
self.assertEqual(status.firmware, '3.11.0')
self.assertEqual(self.device.writes, [])
self.assertNotIn('password', status.public_dict())
+67
View File
@@ -0,0 +1,67 @@
import json
import os
from pathlib import Path
import string
import subprocess
import sys
import unittest
from btd700.controller import Controller
from btd700.demo import DemoTransport
from btd700.i18n import ENGLISH, detect_language, get_language, set_language, tr
ROOT = Path(__file__).resolve().parents[1]
class TranslationTests(unittest.TestCase):
def setUp(self):
self.language = get_language()
def tearDown(self):
set_language(self.language)
def test_language_detection(self):
for env, expected in (({}, 'en'), ({'LANG': 'de_DE.UTF-8'}, 'de'),
({'LANG': 'fr_FR.UTF-8'}, 'en'),
({'LANGUAGE': 'de:en', 'LANG': 'en_GB.UTF-8'}, 'de'),
({'BTD700_LANGUAGE': 'en', 'LANG': 'de_DE.UTF-8'}, 'en')):
self.assertEqual(detect_language(env), expected)
def test_templates_keep_all_fields(self):
formatter = string.Formatter()
def fields(text):
return sorted((field, spec, conversion) for _, field, spec, conversion in formatter.parse(text) if field is not None)
for source, translated in ENGLISH.items():
self.assertTrue(translated)
self.assertEqual(fields(source), fields(translated), source)
def test_status_translates_without_changing_device_values(self):
controller = Controller(DemoTransport())
set_language('en')
english = controller.snapshot().public_dict()
self.assertEqual(english['state_name'], 'Playing audio')
self.assertEqual(english['transport_name'], 'Automatic')
self.assertEqual(english['audio_quality'], '24-bit / 48 kHz')
set_language('de')
german = controller.snapshot().public_dict()
self.assertEqual(german['state_name'], 'Musikwiedergabe')
self.assertEqual(german['audio_quality'], '24 Bit / 48 kHz')
for field in ('mode', 'transport', 'codec', 'firmware', 'broadcast_name'):
self.assertEqual(english[field], german[field])
def test_english_error(self):
set_language('en')
with self.assertRaisesRegex(ValueError, 'Unknown audio mode'):
Controller(DemoTransport()).set_mode(255)
set_language('de')
self.assertEqual(tr('Speichern'), 'Speichern')
self.assertEqual(tr('aptX Adaptive'), 'aptX Adaptive')
def test_cli_override_and_help(self):
env = dict(os.environ, BTD700_LANGUAGE='de')
command = [sys.executable, '-m', 'btd700', '--language', 'en']
result = subprocess.run(command + ['--demo', 'status'], cwd=ROOT, env=env, check=True, text=True, capture_output=True)
self.assertEqual(json.loads(result.stdout)['state_name'], 'Playing audio')
result = subprocess.run(command + ['--help'], cwd=ROOT, env=env, check=True, text=True, capture_output=True)
self.assertIn('Start in the system tray only', result.stdout)
self.assertNotIn('Nur im Infobereich', result.stdout)
+46
View File
@@ -0,0 +1,46 @@
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest
from unittest.mock import patch
from btd700.integration import APP_ID, autostart_path, desktop_entry, set_autostart
ROOT = Path(__file__).resolve().parents[1]
class IntegrationTests(unittest.TestCase):
def test_install_and_remove_only_own_entries(self):
with tempfile.TemporaryDirectory() as tmp:
env = dict(os.environ, XDG_DATA_HOME=tmp+'/data', XDG_CONFIG_HOME=tmp+'/config', BTD700_LANGUAGE='en')
desktop = Path(tmp) / 'data/applications' / f'{APP_ID}.desktop'
other = desktop.parent / 'other-app.desktop'
subprocess.run([sys.executable, 'install.py'], cwd=ROOT, env=env, check=True, capture_output=True)
self.assertIn('Comment=Linux controls', desktop.read_text())
self.assertIn('Comment[de]=', desktop.read_text())
other.write_text('do not remove')
with patch.dict(os.environ, env):
set_autostart(True)
startup = autostart_path()
self.assertTrue(startup.exists())
self.assertIn('--background', startup.read_text())
subprocess.run([sys.executable, 'install.py', '--uninstall'], cwd=ROOT, env=env, check=True, capture_output=True)
self.assertFalse(desktop.exists())
self.assertFalse(startup.exists())
self.assertEqual(other.read_text(), 'do not remove')
def test_launcher_quotes_special_path_characters(self):
with patch('btd700.integration.ROOT', Path('/tmp/BTD "Control" $home 100%')):
with patch.object(Path, 'is_file', return_value=True):
text = desktop_entry()
self.assertIn('\\"Control\\"', text)
self.assertIn('\\$home', text)
self.assertIn('100%%', text)
def test_installed_package_launcher_uses_python_module(self):
with patch.object(Path, 'is_file', return_value=False):
text = desktop_entry(background=True)
self.assertIn(' -m btd700 --background', text)
self.assertIn('Icon=audio-headphones', text)