branch: elpa/flycheck
commit bf620f70e4a4e4bc6ade30089f95fd76d8071f98
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>

    [Fix #2170] Use LC_MESSAGES=C instead of LC_ALL=C for checkers
    
    Forcing LC_ALL=C (added to get English output for error patterns, #1859)
    also pins the character encoding to ASCII, which breaks checkers that
    read UTF-8 input, e.g. hledger on journals with unicode.  LC_MESSAGES=C
    gives English messages while leaving LC_CTYPE alone.
---
 CHANGES.rst                        |  3 +++
 flycheck.el                        |  8 ++++++--
 test/specs/test-command-checker.el | 15 ++++++++++++++-
 test/specs/test-helpers.el         | 20 ++++++++++++++++++++
 4 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index fc7e32ebcc..b3f222a3ff 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -8,6 +8,9 @@
   scripts.
 - [#2163]: Disable native compilation in the ``emacs-lisp`` checker subprocess
   so it no longer writes stray ``.eln`` files to the native-comp cache.
+- [#2170]: Force English checker output with ``LC_MESSAGES=C`` instead of
+  ``LC_ALL=C``, so the character encoding is left untouched.  ``LC_ALL=C``
+  broke checkers reading UTF-8 input, such as ``hledger``.
 
 36.0 (2026-02-19)
 ======================
diff --git a/flycheck.el b/flycheck.el
index 4894d5eff0..dddd3fa1fe 100644
--- a/flycheck.el
+++ b/flycheck.el
@@ -6267,8 +6267,12 @@ PROCESS, and terminates standard input with EOF."
                ;; can easily use pipes.
                (process-connection-type nil)
                ;; Force English messages from checker processes so that
-               ;; error patterns can match reliably.
-               (process-environment (cons "LC_ALL=C" process-environment)))
+               ;; error patterns can match reliably.  We set LC_MESSAGES
+               ;; rather than LC_ALL so that the character encoding
+               ;; (LC_CTYPE) is left untouched; using LC_ALL=C forces an
+               ;; ASCII locale that breaks checkers reading UTF-8 input,
+               ;; such as hledger (see #2170).
+               (process-environment (cons "LC_MESSAGES=C" 
process-environment)))
           ;; We do not associate the process with any buffer, by
           ;; passing nil for the BUFFER argument of `start-process'.
           ;; Instead, we just remember the buffer being checked in a
diff --git a/test/specs/test-command-checker.el 
b/test/specs/test-command-checker.el
index e45020164b..da48c10c25 100644
--- a/test/specs/test-command-checker.el
+++ b/test/specs/test-command-checker.el
@@ -126,6 +126,19 @@
           (truncated-stdin-mode)
           (insert (make-string 65537 ?\n))
           (expect (shut-up (flycheck-buttercup-should-syntax-check-in-buffer))
-                  :to-throw 'flycheck-buttercup-suspicious-checker))))))
+                  :to-throw 'flycheck-buttercup-suspicious-checker))))
+
+    (it "forces English messages without overriding the character set"
+      ;; LC_MESSAGES=C gives English output, while LC_ALL is left alone so
+      ;; that the subprocess keeps the user's LC_CTYPE (see #2170).
+      (assume (or (executable-find "python3") (executable-find "python")))
+      (cl-letf* ((flycheck-checker 'print-locale)
+                 ((symbol-plist 'print-locale) flycheck-test--print-locale))
+        (flycheck-buttercup-with-env '(("LC_MESSAGES" . nil) ("LC_ALL" . nil))
+          (flycheck-buttercup-with-temp-buffer
+            (print-locale-mode)
+            (insert "dummy\n")
+            (flycheck-buttercup-should-syntax-check-in-buffer
+             '(1 1 error "LC_MESSAGES=C LC_ALL=" :checker print-locale))))))))
 
 ;;; test-command-checker.el ends here
diff --git a/test/specs/test-helpers.el b/test/specs/test-helpers.el
index 1de0d7471e..9ac1424247 100644
--- a/test/specs/test-helpers.el
+++ b/test/specs/test-helpers.el
@@ -161,6 +161,26 @@ The manifest path is relative to
 (setf (symbol-plist 'truncated-stdin) nil)
 
 
+;;; Locale test helpers (for command-checker tests)
+
+(define-derived-mode print-locale-mode prog-mode "locale")
+
+(flycheck-define-command-checker 'print-locale
+  "Report the LC_MESSAGES and LC_ALL the subprocess inherits."
+  :command `(,(or (executable-find "python3") "python")
+             "-c" ,(concat "import os; print('locale:1:1:LC_MESSAGES=%s 
LC_ALL=%s'"
+                           " % (os.environ.get('LC_MESSAGES', ''),"
+                           " os.environ.get('LC_ALL', '')))"))
+  :error-patterns '((error bol "locale" ":" line ":" column ":" (message)))
+  :modes '(print-locale-mode))
+
+(defconst flycheck-test--print-locale
+  (symbol-plist 'print-locale)
+  "Saved plist for the print-locale checker.")
+
+(setf (symbol-plist 'print-locale) nil)
+
+
 ;;; Custom error level for error-level tests
 
 (flycheck-define-error-level 'test-level

Reply via email to