feat(identity): rename user-visible identity to voculinux with one-time legacy import

The fork takes its own name everywhere a user can see it: binaries
(voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus
namespace (com.voculinux.Voculinux, no alias for the old name),
config/data/cache dirs, single-instance lock, IBus engine identity,
tray icons, resource prefixes, VOCULINUX_* environment names, and the
update-checker user agent. The internal Python module stays vocalinux
and the distribution metadata keeps the upstream URLs as provenance.

On first run a previous Vocalinux install's config.json, custom
dictionary, and portal restore token are copied once into the new
locations (new config always wins, no merge, no write-back); models
re-resolve through the pinned-checksum download path. An offline
naming-sweep test proves no old-name strings remain on user-visible
surfaces outside the allowlist.

Refs #18
This commit is contained in:
soubarnak
2026-11-06 01:29:39 +05:30
parent c565e6d946
commit ea7be5f111
251 changed files with 2449 additions and 1991 deletions
+16 -16
View File
@@ -1265,7 +1265,7 @@ class TestSettingsNavigation(unittest.TestCase):
"""Finalization keeps the Cancel button usable while recognition stops."""
finalize_body = self.source_code.split("def _finalize_test")[1].split("\n def ")[0]
self.assertIn("def stop_test", finalize_body)
self.assertIn('name="vocalinux-test-dictation-stop"', finalize_body)
self.assertIn('name="voculinux-test-dictation-stop"', finalize_body)
self.assertIn(
"GLib.timeout_add(100, self._wait_for_idle_then_restore_callbacks)",
finalize_body,
@@ -1342,7 +1342,7 @@ class TestAboutPage(unittest.TestCase):
cls.about = cls.about_source.split("def _build_about_section")[1].split("\n def ")[0]
def test_three_groups_keep_updater(self) -> None:
self.assertIn('title="Vocalinux"', self.about)
self.assertIn('title="Voculinux"', self.about)
self.assertIn('title="Part of VocaHQ"', self.about)
self.assertIn('title="Talk to us"', self.about)
self.assertIn('title="Updates"', self.about)
@@ -1369,7 +1369,7 @@ class TestAboutPage(unittest.TestCase):
def test_family_and_talk_urls(self):
for url in (
"https://vocalinux.com",
"https://voculinux.com",
"https://vocahq.com",
"https://vocamac.com",
"https://vocawin.com",
@@ -1395,29 +1395,29 @@ class TestAboutPage(unittest.TestCase):
self.assertIn("_set_accessible_name(button, tooltip)", helper)
self.assertIn('if label == "Open"', helper)
for name in (
"Open vocalinux.com website",
"Open voculinux.com website",
"Open vocahq.com",
"Open vocalinux.com",
"Open voculinux.com",
"Open vocamac.com",
"Open vocawin.com",
"Open vocaphone.vocahq.com",
"Open vocagateway.vocahq.com",
"Open the Vocalinux GitHub repository",
"Open the Voculinux GitHub repository",
"Open the latest release page",
):
self.assertIn(name, self.source)
self.assertIn("_set_accessible_name", self.about)
def test_website_is_product_site_not_only_github(self):
self.assertIn("VOCALINUX_SITE_URL", self.about)
self.assertIn("Product site at vocalinux.com", self.about)
self.assertNotIn("Open the Vocalinux GitHub page", self.about)
self.assertIn("VOCULINUX_SITE_URL", self.about)
self.assertIn("Product site at voculinux.com", self.about)
self.assertNotIn("Open the Voculinux GitHub page", self.about)
def test_source_code_row_sits_beside_website(self):
self.assertIn('label="Website"', self.about)
self.assertIn('label="Source code"', self.about)
self.assertIn("GITHUB_REPO_URL", self.about)
self.assertIn("Open the Vocalinux GitHub repository", self.about)
self.assertIn("Open the Voculinux GitHub repository", self.about)
self.assertLess(self.about.find('label="Website"'), self.about.find('label="Source code"'))
def test_talk_to_us_sits_above_updates(self):
@@ -1457,15 +1457,15 @@ class TestAboutPage(unittest.TestCase):
VOCAHQ_MAILTO_URL,
VOCAHQ_SITE_URL,
VOCAHQ_X_URL,
VOCALINUX_SITE_URL,
VOCAMAC_SITE_URL,
VOCAPHONE_SITE_URL,
VOCAWIN_SITE_URL,
VOCULINUX_SITE_URL,
_can_open_url,
)
for url in (
VOCALINUX_SITE_URL,
VOCULINUX_SITE_URL,
VOCAHQ_SITE_URL,
VOCAMAC_SITE_URL,
VOCAWIN_SITE_URL,
@@ -1542,22 +1542,22 @@ class TestAboutPage(unittest.TestCase):
/ "resources"
/ "icons"
/ "scalable"
/ "vocalinux.svg"
/ "voculinux.svg"
)
shipped = (
Path(__file__).resolve().parents[1]
/ "resources"
/ "icons"
/ "scalable"
/ "vocalinux.svg"
/ "voculinux.svg"
)
packaged_svg = packaged.read_text(encoding="utf-8")
shipped_svg = shipped.read_text(encoding="utf-8")
self.assertEqual(packaged_svg, shipped_svg)
self.assertIn('<circle cx="229" cy="231.5" r="221.5" fill="#0F6B57"/>', packaged_svg)
self.assertIn('aria-label="Vocalinux"', packaged_svg)
self.assertIn('aria-label="Voculinux"', packaged_svg)
self.assertNotIn("<rect", packaged_svg)
self.assertIn('get_icon_path("vocalinux")', self.about)
self.assertIn('get_icon_path("voculinux")', self.about)
def test_platform_marks_are_currentcolor_svgs(self):
from pathlib import Path