Skip to content

TEST#6

Open
Radiump123 wants to merge 11 commits into
testing-stufffrom
dev
Open

TEST#6
Radiump123 wants to merge 11 commits into
testing-stufffrom
dev

Conversation

@Radiump123
Copy link
Copy Markdown
Owner

@Radiump123 Radiump123 commented May 14, 2026

Summary by Sourcery

Update GUI behavior, language handling, and URL opening to improve usability, persistence, and non-root browser launching, while rebranding GitHub references to the Hogjects organization.

New Features:

  • Add system-locale based language detection with persistence across runs and elevation.
  • Introduce a reusable helper to open URLs as the original non-root user when running elevated.
  • Add a Rufus-style destructive-flash confirmation dialog before starting the USB flashing process.

Bug Fixes:

  • Ensure progress parsing in the USB flashing pipeline reads stderr in fixed-size chunks rather than line-based reads to avoid stalls or truncation.
  • Restore theme and language settings consistently when launching or elevating the GUI as root.

Enhancements:

  • Persist language changes to a config file and load them on startup, including when elevated via pkexec.
  • Refine About and log dialogs with adjusted sizing, font tweaks, a Close button, and localized OK/Cancel buttons for Windows tweaks settings.
  • Route all GitHub- and release-related links through the new non-root URL opener and update project metadata (bundle ID, author, URLs) to the Hogjects namespace.

Build:

  • Update pyproject metadata to reference the Hogjects GitHub org and adjust Briefcase bundle and author information accordingly.

Documentation:

  • Update README badges to point to the new Hogjects GitHub repository.

Tests:

  • Extend flashing tests to assert the new stderr read behavior, and add unit tests for the non-root URL opener covering regular, pkexec, and sudo scenarios.

R. Larocque added 9 commits May 13, 2026 12:49
…re missing, replaced mentions of the old GitHub by the new repo, fixed the issue Hogjects#200.

No AI used.
 Please enter the commit message for your changes. Lines starting
 with '' will be ignored, and an empty message aborts the commit.

 On branch dev
 Your branch is up to date with 'origin/dev'.

 Changes to be committed:
	modified:   src/lufus/gui/dialogs.py
	modified:   src/lufus/gui/gui.py
	modified:   src/lufus/gui/languages/Deutsch.csv
	modified:   src/lufus/gui/languages/English.csv
	modified:   "src/lufus/gui/languages/Espa\303\261ol.csv"
	modified:   "src/lufus/gui/languages/Fran\303\247ais.csv"
	modified:   "src/lufus/gui/languages/Portugue\314\202s Brasileiro.csv"
	modified:   src/lufus/gui/languages/Svenska.csv
	modified:   "src/lufus/gui/languages/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.csv"
	modified:   "src/lufus/gui/languages/\321\203\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.csv"
	modified:   "src/lufus/gui/languages/\330\271\330\261\330\250\331\212.csv"
	modified:   "src/lufus/gui/languages/\340\246\254\340\246\276\340\246\202\340\246\262\340\246\276.csv"
 Please enter the commit message for your changes. Lines starting
 with '' will be ignored, and an empty message aborts the commit.

 On branch dev
 Your branch is ahead of 'origin/dev' by 1 commit.
   (use "git push" to publish your local commits)

 Changes to be committed:
	modified:   src/lufus/gui/dialogs.py
	modified:   src/lufus/gui/gui.py
	modified:   "src/lufus/gui/languages/Espa\303\261ol.csv"
	modified:   "src/lufus/gui/languages/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.csv"
	modified:   "src/lufus/gui/languages/\321\203\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.csv"
	modified:   "src/lufus/gui/languages/\330\271\330\261\330\250\331\212.csv"
	modified:   "src/lufus/gui/languages/\340\246\254\340\246\276\340\246\202\340\246\262\340\246\276.csv"
…d some scaling.

 Please enter the commit message for your changes. Lines starting
 with '' will be ignored, and an empty message aborts the commit.

 On branch dev
 Your branch is ahead of 'origin/dev' by 2 commits.
   (use "git push" to publish your local commits)

 Changes to be committed:
	new file:   src/lufus/browse_freely.py
	modified:   src/lufus/gui/dialogs.py
	modified:   src/lufus/gui/gui.py
 Please enter the commit message for your changes. Lines starting
 with '' will be ignored, and an empty message aborts the commit.

 On branch dev
 Your branch is ahead of 'origin/dev' by 4 commits.
   (use "git push" to publish your local commits)

 Changes to be committed:
	new file:   tests/test_browse_freely.py
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 14, 2026

Reviewer's Guide

Refactors browser opening to use a centralized helper that safely opens URLs as the non-root user, improves language/theme initialization and persistence across elevation, adds a pre-flash confirmation dialog, refines dialogs and localization, and updates project metadata, flashing behavior, and tests for the new behaviors.

Sequence diagram for open_url_non_root browser invocation

sequenceDiagram
    actor User
    participant App as GuiComponent
    participant Helper as open_url_non_root
    participant Runuser as subprocess.Popen
    participant Browser as webbrowser

    User->>App: trigger URL open
    App->>Helper: open_url_non_root(url)
    alt [effective UID is root and target_user resolved]
        Helper->>Runuser: Popen(["runuser","-u",target_user,"--","xdg-open",url], env)
        Runuser-->>Helper: process started
        Helper-->>App: return
    else [fallback]
        Helper->>Browser: open(url)
        Browser-->>Helper: browser launched
        Helper-->>App: return
    end
Loading

Sequence diagram for theme and language initialization with elevation

sequenceDiagram
    actor User
    participant Main as launch_gui_with_usb_data
    participant Theme as _load_initial_theme
    participant Lang as _load_initial_language
    participant Elevate as elevate_privileges

    User->>Main: launch_gui_with_usb_data()
    Main->>Theme: _load_initial_theme()
    Main->>Lang: _load_initial_language()
    Main->>Elevate: elevate_privileges()
    Elevate-->>Main: exits current process

    %% New elevated/root process
    User->>Main: launch_gui_with_usb_data() (root)
    Main->>Theme: _load_initial_theme()
    Main->>Lang: _load_initial_language()
    Main-->>User: GUI initialized with theme and language
Loading

Sequence diagram for pre-flash confirmation dialog in perform_flash

sequenceDiagram
    actor User
    participant MainWin as perform_flash
    participant Msg as QMessageBox

    User->>MainWin: perform_flash()
    MainWin->>Msg: create warning dialog
    MainWin->>Msg: exec()
    Msg-->>MainWin: clickedButton()
    alt [user clicked Cancel]
        MainWin->>MainWin: log_message("Flash aborted by user at warning prompt", "WARN")
        MainWin->>MainWin: reset buttons and progress bar
        MainWin-->>User: flash aborted
    else [user clicked OK]
        MainWin->>MainWin: continue with flash operation
    end
Loading

File-Level Changes

Change Details Files
Centralize and harden URL opening so browsers run under the original non-root user, and update call sites and tests accordingly.
  • Add open_url_non_root helper that, when running as root, resolves the original user via PKEXEC_UID or SUDO_USER and runs xdg-open as that user, falling back to webbrowser.open otherwise
  • Replace direct webbrowser/QDesktopServices calls in main GUI and About dialog with open_url_non_root, and update repository URLs to the new Hogjects org
  • Add unit tests covering open_url_non_root behavior for regular user, pkexec-root, and sudo-root scenarios
src/lufus/browse_freely.py
src/lufus/gui/gui.py
src/lufus/gui/dialogs.py
tests/test_browse_freely.py
Improve language detection, persistence, and propagation across GUI startup and privilege elevation.
  • Introduce detect_system_language in i18n, mapping common locales to internal language names and falling back to English
  • Load initial language on startup from LUFUS_LANGUAGE, then from an active_language config file, then by detecting the system language, and call this both before and after elevation
  • Persist language changes to an active_language config file when the user selects a language, and propagate LUFUS_LANGUAGE through elevate_privileges so settings survive pkexec/sudo
src/lufus/gui/i18n.py
src/lufus/gui/start_gui.py
src/lufus/gui/gui.py
src/lufus/utils.py
Add a destructive-operation confirmation dialog before flashing, and reset UI state when the user cancels at this prompt.
  • Show a localized warning QMessageBox in perform_flash that names the target device and uses OK/Cancel buttons, defaulting to Cancel
  • On Cancel, log the abort, re-enable Start, disable Cancel, clear the progress bar, and reset speed/ETA before returning
src/lufus/gui/gui.py
Refine About and Windows tweaks dialogs for better layout, typography, and localization.
  • Increase About dialog height, slightly reduce about text font size, and widen Discord/GitHub buttons with localized labels (including capitalizing GitHub)
  • Route About dialog links through open_url_non_root to avoid root-browser issues
  • Add a localized Close button to the log window and localize the Apply/Cancel buttons in the Windows tweaks dialog
src/lufus/gui/dialogs.py
Align flashing progress parsing with fixed-size chunk reads and ensure tests validate the behavior.
  • Change flash_usb stderr reading loop to use read(4096) instead of readline() for progress parsing
  • Adjust flash/USB tests to provide a FakePipe.read implementation, capture the requested chunk size, and assert that read(4096) is used
src/lufus/writing/flash_usb.py
tests/test_flash_usb_and_find_usb_fixes.py
Update project metadata and documentation links to the new Hogjects GitHub organization and bundle namespace.
  • Update Homepage, Repository, Issues, and Briefcase URL/bundle/author fields to point to the Hogjects/Lufus repo and com.github.hogjects bundle ID
  • Update in-app GitHub URLs and README license badge link to the new repository
pyproject.toml
src/lufus/gui/gui.py
src/lufus/gui/dialogs.py
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In launch_gui_with_usb_data, _load_initial_language() is called both before and after elevate_privileges(), which means the post-elevation call may read the root user’s config and overwrite the intended user language; consider only initializing language in the non-root context or guarding the second call appropriately.
  • In open_url_non_root, when only SUDO_USER is set you never derive a UID, so XDG_RUNTIME_DIR is left empty; consider resolving the UID for sudo_user (e.g. via pwd.getpwnam) to populate a more accurate environment for GUI apps.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `launch_gui_with_usb_data`, `_load_initial_language()` is called both before and after `elevate_privileges()`, which means the post-elevation call may read the root user’s config and overwrite the intended user language; consider only initializing language in the non-root context or guarding the second call appropriately.
- In `open_url_non_root`, when only `SUDO_USER` is set you never derive a UID, so `XDG_RUNTIME_DIR` is left empty; consider resolving the UID for `sudo_user` (e.g. via `pwd.getpwnam`) to populate a more accurate environment for GUI apps.

## Individual Comments

### Comment 1
<location path="src/lufus/browse_freely.py" line_range="39" />
<code_context>
+
+                # Method 1: Use runuser which is specifically designed for this
+                # We need to preserve the environment for the GUI session
+                env = {
+                    "DISPLAY": os.environ.get("DISPLAY", ":0"),
+                    "XAUTHORITY": os.environ.get("XAUTHORITY", ""),
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Environment for the spawned browser process does not set HOME, which may cause profile or permission issues.

Since many GUI apps depend on `HOME` for profiles and config, relying only on `DISPLAY`, `XAUTHORITY`, `XDG_RUNTIME_DIR`, `WAYLAND_DISPLAY`, and `PATH` risks using root’s home (or none) when running as another user, especially in the `sudo_user` case without `target_uid`. Please also set `HOME` to the target user’s home directory (e.g. `pwd.getpwnam(target_user).pw_dir`) and add it to `env` when available.

Suggested implementation:

```python
import os
import pwd

```

```python
        if target_user:
            try:
                log.info(f"Attempting to open URL as user {target_user} (UID {target_uid}): {url}")

                # Determine the target user's home directory so GUI apps use the correct profile/config
                home_dir = None
                try:
                    home_dir = pwd.getpwnam(target_user).pw_dir
                except KeyError:
                    log.warning("Could not determine home directory for user %s", target_user)

                # Method 1: Use runuser which is specifically designed for this
                # We need to preserve the environment for the GUI session
                env = {
                    "DISPLAY": os.environ.get("DISPLAY", ":0"),
                    "XAUTHORITY": os.environ.get("XAUTHORITY", ""),
                    "XDG_RUNTIME_DIR": os.environ.get(
                        "XDG_RUNTIME_DIR", f"/run/user/{target_uid}" if target_uid else ""
                    ),
                    "WAYLAND_DISPLAY": os.environ.get("WAYLAND_DISPLAY", ""),
                    "PATH": "/usr/local/bin:/usr/bin:/bin",
                    # Ensure HOME is set so GUI apps use the target user's profile and config
                    "HOME": home_dir or os.environ.get("HOME", ""),
                }

                # Filter out empty values
                env = {k: v for k, v in env.items() if v}

```

If `pwd` is already imported elsewhere in this file, adjust the import edit accordingly to avoid duplicate imports (e.g. by adding it to an existing import line instead of introducing a new one).
</issue_to_address>

### Comment 2
<location path="tests/test_browse_freely.py" line_range="11-20" />
<code_context>
+        self.assertEqual(env.get("DISPLAY"), ":0")
+        self.assertEqual(env.get("XDG_RUNTIME_DIR"), "/run/user/1000")
+
+    @patch("os.geteuid")
+    @patch("os.environ.get")
+    @patch("subprocess.Popen")
+    def test_open_url_as_root_via_sudo(self, mock_popen, mock_env_get, mock_geteuid):
+        # Simulate root (UID 0)
+        mock_geteuid.return_value = 0
</code_context>
<issue_to_address>
**suggestion (testing):** Consider using `patch.dict(os.environ, ...)` instead of patching `os.environ.get` to make the tests more realistic and resilient.

Patching `os.environ.get` with a `side_effect` intercepts every env lookup (e.g. `DISPLAY`, `XAUTHORITY`, `XDG_RUNTIME_DIR`), which couples the tests to the exact way `open_url_non_root` reads the environment. Instead, patching `os.environ` via `patch.dict(os.environ, {"PKEXEC_UID": "1000", ...}, clear=False)` (and similarly for the sudo case) more accurately reflects real usage and keeps the tests resilient to internal changes in environment access.

Suggested implementation:

```python
    @patch("os.geteuid")
    @patch("subprocess.Popen")
    @patch("pwd.getpwuid")
    def test_open_url_as_root_via_pkexec(self, mock_getpwuid, mock_popen, mock_geteuid):

```

```python
        # Mock environment variables
        env_overrides = {
            "PKEXEC_UID": "1000",
            "DISPLAY": ":0",
            "XDG_RUNTIME_DIR": "/run/user/1000",
        }

        with patch.dict(os.environ, env_overrides, clear=False):
            open_url_non_root(self.url)

        # Mock pwd info

```

1. Apply a similar refactor to the `test_open_url_as_root_via_sudo` test: remove any `@patch("os.environ.get")` decorator and associated `mock_env_get` parameter, and replace any `side_effect`-based environment mocking with a `with patch.dict(os.environ, {...}, clear=False):` block that sets the sudo-related variables your production code expects (e.g. `SUDO_USER`, `DISPLAY`, `XDG_RUNTIME_DIR`, etc.), wrapping the `open_url_non_root(self.url)` call in that context.
2. If there are other tests in this file that also patch `os.environ.get`, consider converting them to `patch.dict` in the same way to keep the test suite consistent and resilient to internal environment access changes.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lufus/browse_freely.py
Comment on lines +11 to +20
@patch("os.geteuid")
@patch("webbrowser.open")
def test_open_url_non_root_as_regular_user(self, mock_webbrowser, mock_geteuid):
# Simulate regular user (UID 1000)
mock_geteuid.return_value = 1000

open_url_non_root(self.url)

# Should fallback to standard webbrowser.open
mock_webbrowser.assert_called_once_with(self.url)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider using patch.dict(os.environ, ...) instead of patching os.environ.get to make the tests more realistic and resilient.

Patching os.environ.get with a side_effect intercepts every env lookup (e.g. DISPLAY, XAUTHORITY, XDG_RUNTIME_DIR), which couples the tests to the exact way open_url_non_root reads the environment. Instead, patching os.environ via patch.dict(os.environ, {"PKEXEC_UID": "1000", ...}, clear=False) (and similarly for the sudo case) more accurately reflects real usage and keeps the tests resilient to internal changes in environment access.

Suggested implementation:

    @patch("os.geteuid")
    @patch("subprocess.Popen")
    @patch("pwd.getpwuid")
    def test_open_url_as_root_via_pkexec(self, mock_getpwuid, mock_popen, mock_geteuid):
        # Mock environment variables
        env_overrides = {
            "PKEXEC_UID": "1000",
            "DISPLAY": ":0",
            "XDG_RUNTIME_DIR": "/run/user/1000",
        }

        with patch.dict(os.environ, env_overrides, clear=False):
            open_url_non_root(self.url)

        # Mock pwd info
  1. Apply a similar refactor to the test_open_url_as_root_via_sudo test: remove any @patch("os.environ.get") decorator and associated mock_env_get parameter, and replace any side_effect-based environment mocking with a with patch.dict(os.environ, {...}, clear=False): block that sets the sudo-related variables your production code expects (e.g. SUDO_USER, DISPLAY, XDG_RUNTIME_DIR, etc.), wrapping the open_url_non_root(self.url) call in that context.
  2. If there are other tests in this file that also patch os.environ.get, consider converting them to patch.dict in the same way to keep the test suite consistent and resilient to internal environment access changes.

@Radiump123
Copy link
Copy Markdown
Owner Author

@sourcery-ai review

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/lufus/gui/i18n.py" line_range="29-38" />
<code_context>
+    Falls back to English if detection fails or no match is found.
+    """
+    try:
+        loc = locale.getdefaultlocale()
+    except Exception:
+        loc = (None, None)
</code_context>
<issue_to_address>
**suggestion:** Using `locale.getdefaultlocale()` may be problematic going forward due to deprecation; consider an alternative approach.

`locale.getdefaultlocale()` is deprecated in recent Python versions and may be removed. Since only the language is needed, consider alternatives such as `locale.getlocale()[0]`, `os.environ.get("LANG")`, or `locale.setlocale(locale.LC_CTYPE, "")` followed by `locale.getlocale()` to avoid relying on a deprecated API.

```suggestion
def detect_system_language() -> str:
    """Detect the system locale and return the matching language name.

    Falls back to English if detection fails or no match is found.
    """
    try:
        # Ensure locale is initialized from the environment, then read current locale.
        locale.setlocale(locale.LC_CTYPE, "")
        loc = locale.getlocale()
    except Exception:
        loc = (None, None)

    lang_code = (loc[0] or "") or os.environ.get("LANG", "")
```
</issue_to_address>

### Comment 2
<location path="tests/test_flash_usb_and_find_usb_fixes.py" line_range="148-149" />
<code_context>
                 pass

         class FakePipe:
-            def readline(self):
+            def read(self, n=-1):
                 return b""

</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen the fake stderr pipe to assert that `read` is called with the expected chunk size (4096).

`FakePipe.read` currently ignores `n` and always returns `b""`, so the test doesn’t verify that `process.stderr.read(4096)` is actually called with the intended chunk size. Consider recording the passed-in `n` (e.g., `self.last_n = n`) and asserting it is `4096` (or at least `> 0`) after the call to catch regressions like switching back to `readline()` or changing the chunk size.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lufus/gui/i18n.py Outdated
Comment on lines 148 to +149
class FakePipe:
def readline(self):
def read(self, n=-1):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Strengthen the fake stderr pipe to assert that read is called with the expected chunk size (4096).

FakePipe.read currently ignores n and always returns b"", so the test doesn’t verify that process.stderr.read(4096) is actually called with the intended chunk size. Consider recording the passed-in n (e.g., self.last_n = n) and asserting it is 4096 (or at least > 0) after the call to catch regressions like switching back to readline() or changing the chunk size.

@Radiump123
Copy link
Copy Markdown
Owner Author

@sourcery-ai review

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/lufus/gui/i18n.py" line_range="34-41" />
<code_context>
+    Falls back to English if detection fails or no match is found.
+    """
+    try:
+        # Ensure locale is initialized from the environment, then read current locale.
+        locale.setlocale(locale.LC_CTYPE, "")
+        loc = locale.getlocale()
+    except Exception:
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Calling `locale.setlocale` here mutates global process state and may have unintended side effects.

`locale.setlocale(locale.LC_CTYPE, "")` here mutates the global locale and can unexpectedly impact formatting/parsing and libraries that depend on locale (e.g. Qt). If you only need to detect the system locale, prefer `locale.getdefaultlocale()` or environment variables (e.g. `$LANG`) without changing the active locale, or temporarily change it and immediately restore the original value.

```suggestion
    try:
        # Read the system locale without mutating global locale state.
        loc = locale.getdefaultlocale()
    except Exception:
        loc = (None, None)

    # Fallback to the process locale if the default locale could not be determined.
    if not loc or not loc[0]:
        try:
            loc = locale.getlocale()
        except Exception:
            loc = (None, None)

    lang_code = (loc[0] or "") or os.environ.get("LANG", "")
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lufus/gui/i18n.py
Comment on lines +34 to +41
try:
# Ensure locale is initialized from the environment, then read current locale.
locale.setlocale(locale.LC_CTYPE, "")
loc = locale.getlocale()
except Exception:
loc = (None, None)

lang_code = (loc[0] or "") or os.environ.get("LANG", "")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Calling locale.setlocale here mutates global process state and may have unintended side effects.

locale.setlocale(locale.LC_CTYPE, "") here mutates the global locale and can unexpectedly impact formatting/parsing and libraries that depend on locale (e.g. Qt). If you only need to detect the system locale, prefer locale.getdefaultlocale() or environment variables (e.g. $LANG) without changing the active locale, or temporarily change it and immediately restore the original value.

Suggested change
try:
# Ensure locale is initialized from the environment, then read current locale.
locale.setlocale(locale.LC_CTYPE, "")
loc = locale.getlocale()
except Exception:
loc = (None, None)
lang_code = (loc[0] or "") or os.environ.get("LANG", "")
try:
# Read the system locale without mutating global locale state.
loc = locale.getdefaultlocale()
except Exception:
loc = (None, None)
# Fallback to the process locale if the default locale could not be determined.
if not loc or not loc[0]:
try:
loc = locale.getlocale()
except Exception:
loc = (None, None)
lang_code = (loc[0] or "") or os.environ.get("LANG", "")

@Radiump123
Copy link
Copy Markdown
Owner Author

broke smth i think

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant