diff --git a/gnu/local.mk b/gnu/local.mk
index ee90d102ac..c93c4e1dc5 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1925,7 +1925,6 @@ dist_patch_DATA =						\
   %D%/packages/patches/tootle-reason-phrase.patch		\
   %D%/packages/patches/transcode-ffmpeg.patch	\
   %D%/packages/patches/transfig-gcc10-fno-common.patch		\
-  %D%/packages/patches/transmission-honor-localedir.patch	\
   %D%/packages/patches/trytond-add-egg-modules-to-path.patch	\
   %D%/packages/patches/trytond-add-guix_trytond_path.patch	\
   %D%/packages/patches/ttf2eot-cstddef.patch			\
diff --git a/gnu/packages/bittorrent.scm b/gnu/packages/bittorrent.scm
index bfe524366c..8e345f2de7 100644
--- a/gnu/packages/bittorrent.scm
+++ b/gnu/packages/bittorrent.scm
@@ -81,7 +81,7 @@ (define-module (gnu packages bittorrent)
 (define-public transmission
   (package
     (name "transmission")
-    (version "3.00")
+    (version "4.0.3")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://github.com/transmission/transmission"
@@ -89,51 +89,60 @@ (define-public transmission
                                   version ".tar.xz"))
               (sha256
                (base32
-                "1wjmn96zrvmk8j1yz2ysmqd7a2x6ilvnwwapcvfzgxs2wwpnai4i"))
-              (patches (search-patches "transmission-honor-localedir.patch"))))
-    (build-system glib-or-gtk-build-system)
+                "0njlmpcdsxwx8vwdk9dvsby51l6f6awks9d0mgvi9fs2ivaizc5n"))))
+    (build-system cmake-build-system)
     (outputs '("out"                      ; library and command-line interface
                "gui"))                    ; graphical user interface
     (arguments
-     '(#:configure-flags
-       (list (string-append "--localedir="
-                            (assoc-ref %outputs "gui")
-                            "/share/locale"))
-       ;; Some tests segfault when using libevent 2.12 without internet
-       ;; connection. This has been reported mainstream but not fixed yet:
-       ;; https://github.com/transmission/transmission/issues/1437.
-       #:tests? #f
-       #:glib-or-gtk-wrap-excluded-outputs '("out")
-       #:phases
-       (modify-phases %standard-phases
+      (list
+        #:imported-modules `((guix build glib-or-gtk-build-system)
+                             ,@%cmake-build-system-modules)
+        #:modules '(((guix build glib-or-gtk-build-system) #:prefix glib-or-gtk:)
+                    (guix build cmake-build-system)
+                    (guix build utils))
+        #:phases
+        #~(modify-phases %standard-phases
          ;; Avoid embedding kernel version for reproducible build
-         (add-after 'unpack 'remove-kernel-version
-           (lambda _
-             (substitute* "third-party/miniupnpc/updateminiupnpcstrings.sh"
-               (("OS_VERSION=`uname -r`") "OS_VERSION=Guix"))))
-         (add-after 'install 'move-gui
-           (lambda* (#:key outputs #:allow-other-keys)
-             ;; Move the GUI to its own output, so that "out" doesn't
-             ;; depend on GTK+.
-             (let ((out (assoc-ref outputs "out"))
-                   (gui (assoc-ref outputs "gui")))
-               (mkdir-p (string-append gui "/bin"))
-               (rename-file (string-append out "/bin/transmission-gtk")
-                            (string-append gui "/bin/transmission-gtk"))
-
+           (add-after 'unpack 'remove-kernel-version
+             (lambda _
+               (substitute* "third-party/miniupnpc/updateminiupnpcstrings.sh"
+                 (("OS_VERSION=`uname -r`") "OS_VERSION=Guix"))))
+           (replace 'check
+             (lambda* (#:key tests? parallel-tests? #:allow-other-keys)
+               (if tests?
+                   ;; XXX this test fails...
+                   (invoke "ctest" "-E" "usesBootstrapFile"
+                           "-j" (if parallel-tests?
+                                    (number->string (parallel-job-count))
+                                    "1"))
+                   (format #t "test suite not run~%"))))
+           (add-after 'install 'move-gui
+             (lambda* (#:key outputs #:allow-other-keys)
+               (mkdir-p (string-append #$output:gui "/bin"))
+               (mkdir-p (string-append #$output:gui "/share/man/man1"))
+               (rename-file (string-append #$output "/bin/transmission-gtk")
+                            (string-append #$output:gui "/bin/transmission-gtk"))
                (for-each
                 (lambda (dir)
-                  (rename-file (string-append out "/share/" dir)
-                               (string-append gui "/share/" dir)))
-                '("appdata" "applications" "icons" "pixmaps"))
-
-               (mkdir-p (string-append gui "/share/man/man1"))
-               (rename-file
-                (string-append out "/share/man/man1/transmission-gtk.1")
-                (string-append gui "/share/man/man1/transmission-gtk.1"))
-             #t))))))
-    (inputs
-     (list libevent curl openssl zlib gtk+ libappindicator))
+                  (rename-file (string-append #$output "/share/" dir)
+                               (string-append #$output:gui "/share/" dir)))
+                '("applications" "icons" "metainfo" "transmission"))
+              (rename-file
+               (string-append #$output "/share/man/man1/transmission-gtk.1")
+               (string-append #$output:gui "/share/man/man1/transmission-gtk.1"))))
+           (add-after 'move-gui 'glib-or-gtk-wrap
+             (lambda* (#:key outputs #:allow-other-keys #:rest args)
+               (apply (assoc-ref glib-or-gtk:%standard-phases 'glib-or-gtk-wrap)
+                      #:glib-or-gtk-wrap-excluded-outputs (list "out")
+                      args))))))
+    (inputs (list curl
+                  (list glib "bin")
+                  gtkmm
+                  libappindicator
+                  libevent
+                  openssl
+                  python
+                  zlib))
     (native-inputs
      (list intltool pkg-config))
     (home-page "https://transmissionbt.com/")
diff --git a/gnu/packages/patches/transmission-honor-localedir.patch b/gnu/packages/patches/transmission-honor-localedir.patch
deleted file mode 100644
index 70c66bfb2b..0000000000
--- a/gnu/packages/patches/transmission-honor-localedir.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-This patch modifies Transmission so it honors the "localedir" option
-passed to its configure script, allowing GTK-specific localization
-data to be placed in the package's "gui" output.
-
-Without this patch, localization of transmission-gtk can break as the
-application will expect to find this data in the package's default
-output (as a result of the call to bindtextdomain in gtk/main.c).
-
-diff --git a/configure b/configure
-index a29e24f..3ae8ef4 100755
---- a/configure
-+++ b/configure
-@@ -21305,7 +21305,7 @@ $as_echo "$LINGUAS" >&6; }
-    sed -e "/^#/d" -e "/^\$/d" -e "s,.*,	$posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
- 	< $srcdir/po/POTFILES.in > po/POTFILES
- 
--    transmissionlocaledir='${prefix}/${DATADIRNAME}/locale'
-+    transmissionlocaledir='${localedir}'
- 
- fi
- 
-diff --git a/configure.ac b/configure.ac
-index 57d3cae..ab62093 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -563,7 +563,7 @@ if test "x$enable_nls" = "xyes" ; then
-     AC_SUBST(GETTEXT_PACKAGE)
-     AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[Gettext package])
-     AM_GLIB_GNU_GETTEXT
--    transmissionlocaledir='${prefix}/${DATADIRNAME}/locale'
-+    transmissionlocaledir='${localedir}'
-     AC_SUBST(transmissionlocaledir)
- fi
- AC_SUBST(INTLLIBS)
