diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn
index 428d94f293aba115904c8c4ad7171d47262eba7b..e71f1c344b135976afa22386821e1c2e7776c356 100644
--- a/.clj-kondo/config.edn
+++ b/.clj-kondo/config.edn
@@ -18,7 +18,14 @@
   :use                          {:level :warning}
   :warn-on-reflection           {:level :warning}
 
-  :metabase/defsetting-must-specify-export {:level :warning}
+  :metabase/defsetting-must-specify-export                             {:level :warning}
+  :metabase/i-like-making-cams-eyes-bleed-with-horrifically-long-tests {:level :warning}
+  :metabase/mbql-query-first-arg                                       {:level :warning}
+  :metabase/missing-test-expr-requires-in-cljs                         {:level :warning}
+  :metabase/test-helpers-use-non-thread-safe-functions                 {:level :warning}
+  :metabase/validate-deftest                                           {:level :warning}
+  :metabase/validate-logging                                           {:level :warning}
+  :metabase/warn-about-schema=                                         {:level :warning}
 
   ;;
   ;; disabled linters
@@ -34,6 +41,7 @@
   ;; :docstring-leading-trailing-whitespace {:level :warning}
   ;; :docstring-no-summary                  {:level :warning}
   ;; :shadowed-var                          {:level :warning}
+  ;; :def-fn                                {:level :warning}
 
   :unresolved-symbol
   {:exclude
@@ -402,12 +410,7 @@
     ring.adapter.jetty9.servlet                                   servlet
     saml20-clj.core                                               saml
     toucan.db                                                     db
-    toucan.models                                                 models}}
-
-  :metabase/validate-deftest                                           {:level :warning}
-  :metabase/missing-test-expr-requires-in-cljs                         {:level :warning}
-  :metabase/i-like-making-cams-eyes-bleed-with-horrifically-long-tests {:level :warning}
-  :metabase/warn-about-schema=                                         {:level :warning}}
+    toucan.models                                                 models}}}
 
  :lint-as
  {clojure.core.logic/defne                                                             clj-kondo.lint-as/def-catch-all
@@ -571,6 +574,19 @@
    metabase.test/with-temp                                                                                                   hooks.toucan2.tools.with-temp/with-temp
    metabase.test/with-temp-file                                                                                              hooks.metabase.test.util/with-temp-file
    metabase.test/with-temporary-setting-values                                                                               hooks.metabase.test.util/with-temporary-setting-values
+   metabase.util/format-color                                                                                                hooks.metabase.util/format-color
+   metabase.util.log/trace                                                                                                   hooks.metabase.util.log/info
+   metabase.util.log/tracef                                                                                                  hooks.metabase.util.log/infof
+   metabase.util.log/debug                                                                                                   hooks.metabase.util.log/info
+   metabase.util.log/debugf                                                                                                  hooks.metabase.util.log/infof
+   metabase.util.log/info                                                                                                    hooks.metabase.util.log/info
+   metabase.util.log/infof                                                                                                   hooks.metabase.util.log/infof
+   metabase.util.log/warn                                                                                                    hooks.metabase.util.log/info
+   metabase.util.log/warnf                                                                                                   hooks.metabase.util.log/infof
+   metabase.util.log/error                                                                                                   hooks.metabase.util.log/info
+   metabase.util.log/errorf                                                                                                  hooks.metabase.util.log/infof
+   metabase.util.log/fatal                                                                                                   hooks.metabase.util.log/info
+   metabase.util.log/fatalf                                                                                                  hooks.metabase.util.log/infof
    metabase.util.malli.registry/def                                                                                          hooks.metabase.util.malli.registry/def}
 
   :macroexpand
@@ -643,12 +659,10 @@
  :config-in-ns
  {test-namespaces
   {:linters
-   {:inline-def                                          {:level :off}
-    :missing-docstring                                   {:level :off}
-    :private-call                                        {:level :off}
-    :metabase/defsetting-must-specify-export             {:level :off}
-    :hooks.metabase.test.data/mbql-query-first-arg       {:level :error}
-    :metabase/test-helpers-use-non-thread-safe-functions {:level :warning}}
+   {:inline-def                              {:level :off}
+    :missing-docstring                       {:level :off}
+    :private-call                            {:level :off}
+    :metabase/defsetting-must-specify-export {:level :off}}
    :hooks
    {:analyze-call
     {clojure.core/defmacro hooks.clojure.core/non-thread-safe-form-should-end-with-exclamation
diff --git a/.clj-kondo/hooks/clojure/test.clj b/.clj-kondo/hooks/clojure/test.clj
index f0b0d2e91bcf9d1cb2e8fee1ff16af72def2dfe8..b5516798af4f38741e034f34d0eeba427233b4f0 100644
--- a/.clj-kondo/hooks/clojure/test.clj
+++ b/.clj-kondo/hooks/clojure/test.clj
@@ -1,6 +1,8 @@
 (ns hooks.clojure.test
-  (:require [clj-kondo.hooks-api :as hooks]
-            [clojure.string :as str]))
+  (:require
+   [clj-kondo.hooks-api :as hooks]
+   [clojure.string :as str]
+   [hooks.common]))
 
 (def ^:private disallowed-parallel-forms
   "Things you should not be allowed to use inside parallel tests. Besides these, anything ending in `!` not whitelisted
@@ -109,24 +111,13 @@
      metabase.query-processor.store/store-database!
      next.jdbc/execute!})
 
-(defn- node->qualified-symbol [node]
-  (try
-    (when (hooks/token-node? node)
-      (let [sexpr (hooks/sexpr node)]
-        (when (symbol? sexpr)
-          (when-let [resolved (hooks/resolve {:name sexpr})]
-            (symbol (name (:ns resolved)) (name (:name resolved)))))))
-    ;; some symbols like `*count/Integer` aren't resolvable.
-    (catch Exception _
-      nil)))
-
 (defn- warn-about-disallowed-parallel-forms [form]
   (letfn [(error! [form message]
             (hooks/reg-finding! (assoc (meta form)
                                        :message message
                                        :type :metabase/validate-deftest)))
           (f [form]
-            (when-let [qualified-symbol (node->qualified-symbol form)]
+            (when-let [qualified-symbol (hooks.common/node->qualified-symbol form)]
               (cond
                 (disallowed-parallel-forms qualified-symbol)
                 (error! form (format "%s is not allowed inside a ^:parallel test or test fixture" qualified-symbol))
diff --git a/.clj-kondo/hooks/common.clj b/.clj-kondo/hooks/common.clj
index 5a01d48f74126928449ddaa40a6a7730140aeeb8..6b054c931c1f9690e5adeec45ce6340505de396d 100644
--- a/.clj-kondo/hooks/common.clj
+++ b/.clj-kondo/hooks/common.clj
@@ -1,6 +1,7 @@
 (ns hooks.common
-  (:require [clj-kondo.hooks-api :as hooks]
-            [clojure.pprint]))
+  (:require
+   [clj-kondo.hooks-api :as hooks]
+   [clojure.pprint]))
 
 (defn with-macro-meta
   "When introducing internal nodes (let, defn, etc) it is important to provide a meta of an existing token
@@ -369,3 +370,33 @@
                                       arg])
                   body))]
     {:node node*}))
+
+(defn node->qualified-symbol [node]
+  (try
+    (when (hooks/token-node? node)
+      (let [sexpr (hooks/sexpr node)]
+        (when (symbol? sexpr)
+          (when-let [resolved (hooks/resolve {:name sexpr})]
+            (symbol (name (:ns resolved)) (name (:name resolved)))))))
+    ;; some symbols like `*count/Integer` aren't resolvable.
+    (catch Exception _
+      nil)))
+
+(defn format-string-specifier-count
+  "Number of things like `%s` in a format string, not counting newlines (`%n`) or escaped percent signs (`%%`). For
+  checking the number of args to something that takes a format string."
+  [format-string]
+  (count (re-seq #"(?<!%)%(?![%n])" format-string)))
+
+(comment
+  ;; should be 1
+  (format-string-specifier-count "%s %%")
+
+  ;; should be 2
+  (format-string-specifier-count "%s %%%n%s")
+
+  ;; should be 0
+  (format-string-specifier-count "%n%%%%")
+
+  ;; should be 1
+  (format-string-specifier-count "%-02d"))
diff --git a/.clj-kondo/hooks/metabase/test/data.clj b/.clj-kondo/hooks/metabase/test/data.clj
index bf4249cece79874a490aeecddc169489c384fc78..b865350393745ff04227db0425f71b4c90f40c21 100644
--- a/.clj-kondo/hooks/metabase/test/data.clj
+++ b/.clj-kondo/hooks/metabase/test/data.clj
@@ -139,7 +139,7 @@
     (when-not ((some-fn symbol? nil?) (hooks/sexpr table))
       (hooks/reg-finding! (assoc (meta table)
                                  :message "First arg to mbql-query should be either a table name symbol or nil."
-                                 :type ::mbql-query-first-arg)))
+                                 :type :metabase/mbql-query-first-arg)))
     (let [result (replace-$id-special-tokens query)
           ;; HACK I'm not sure WHY it works but I ran into https://github.com/clj-kondo/clj-kondo/issues/1773 when
           ;; trying to get this working -- for some magical reason wrapping the whole thing in a `do` form seems to fix
diff --git a/.clj-kondo/hooks/metabase/util.clj b/.clj-kondo/hooks/metabase/util.clj
new file mode 100644
index 0000000000000000000000000000000000000000..176a98a85ade94c1c214dbd6ad769f5b0eb96bec
--- /dev/null
+++ b/.clj-kondo/hooks/metabase/util.clj
@@ -0,0 +1,17 @@
+(ns hooks.metabase.util
+  (:require
+   [clj-kondo.hooks-api :as api]
+   [hooks.common]))
+
+(defn format-color [{:keys [node], :as x}]
+  (let [[_format-color _color format-string-node & args] (:children node)]
+    (when (api/string-node? format-string-node)
+      (let [expected-arg-count (hooks.common/format-string-specifier-count (api/sexpr format-string-node))
+            actual-arg-count   (count args)]
+        (when-not (= expected-arg-count actual-arg-count)
+          (api/reg-finding! (assoc (meta node)
+                                   :message (format "metabase.util/format-color format string expects %d arguments instead of %d."
+                                                    expected-arg-count
+                                                    actual-arg-count)
+                                   :type :format))))))
+  x)
diff --git a/.clj-kondo/hooks/metabase/util/log.clj b/.clj-kondo/hooks/metabase/util/log.clj
new file mode 100644
index 0000000000000000000000000000000000000000..b2098601783239bd3c6eae687aff382e44dd0d4a
--- /dev/null
+++ b/.clj-kondo/hooks/metabase/util/log.clj
@@ -0,0 +1,157 @@
+(ns hooks.metabase.util.log
+  (:require
+   [clj-kondo.hooks-api :as api]
+   [clojure.string :as str]
+   [clojure.walk :as walk]
+   [hooks.common]))
+
+;;;; Checks for both log + logf
+
+(defn- disallow-i18n [node]
+  (walk/postwalk
+   (fn [x]
+     (when-let [qualified-symbol (hooks.common/node->qualified-symbol x)]
+       (when (and (= (namespace qualified-symbol) "metabase.util.i18n")
+                  (or (str/includes? (name qualified-symbol) "tru")
+                      (str/includes? (name qualified-symbol) "trs")))
+         (api/reg-finding! (assoc (meta x)
+                                  :message "do not i18n the logs!"
+                                  :type :metabase/validate-logging)))))
+   node))
+
+(defn- check-position-of-exception-arg
+  "Tell people to do (info e \"whatever\") instead of (info \"whatever\" e)."
+  [node]
+  (let [[f _first-arg & args] (:children node)]
+    (doseq [arg args]
+      (when (and (api/token-node? arg)
+                 (= (api/sexpr arg) 'e))
+        (api/reg-finding! (assoc (meta arg)
+                                 :message (format "pass exceptions as the first arg to %s" (api/sexpr f))
+                                 :type :metabase/validate-logging))))))
+
+(defn- common-checks [node]
+  (check-position-of-exception-arg node)
+  (disallow-i18n node))
+
+(defn- check-for-i18n-format-specifiers
+  "Make sure people aren't using things like {0} in their log messages."
+  [node string-node]
+  (when (re-find #"\{\d+\}" (api/sexpr string-node))
+    (api/reg-finding! (assoc (meta node)
+                             :message "this looks like an i18n format string. Don't use identifiers like {0} in logging."
+                             :type :metabase/validate-logging))))
+
+;;; log only
+
+(defn- check-not-format-string
+  "Make sure we're not using something like log/trace with a format string."
+  [{[f] :children, :as node} string-node]
+  (when (pos? (hooks.common/format-string-specifier-count (api/sexpr string-node)))
+    (api/reg-finding! (assoc (meta node)
+                             :message (format "%s used with a format string, use %s instead."
+                                              (api/sexpr f)
+                                              (str (api/sexpr f) "f"))
+                             :type :metabase/validate-logging))))
+
+(defn- warn-against-log+format-instead-of-logf
+  "Tell people to use things like infof instead of info + format."
+  [{[f] :children, :as node} [x :as args]]
+  (when (and (= (count args) 1)
+             (api/list-node? x))
+    (let [[y] (:children x)]
+      (when (and (api/token-node? y)
+                 (= (hooks.common/node->qualified-symbol y) 'clojure.core/format))
+        (api/reg-finding! (assoc (meta node)
+                                 :message (format "Use %s instead of %s + format"
+                                                  (str (api/sexpr f) "f")
+                                                  (api/sexpr f))
+                                 :type :metabase/validate-logging))))))
+
+(defn info
+  "Valid log, debug, etc."
+  [{:keys [node], :as x}]
+  (common-checks node)
+  (let [[_f & args]         (:children node)
+        [_e & [x :as args]] (if (and (api/token-node? (first args))
+                                     (api/string-node? (second args)))
+                              args
+                              (cons nil args))]
+    (when (api/string-node? x)
+      (check-for-i18n-format-specifiers node x)
+      (check-not-format-string node x))
+    (warn-against-log+format-instead-of-logf node args))
+  x)
+
+;;;; logf only
+
+(defn- check-format-string-arg-count
+  "Make sure the number of args passed to something like tracef match the number of format string specifiers."
+  [{[f] :children, :as node} format-string args]
+  (let [expected-arg-count (hooks.common/format-string-specifier-count (api/sexpr format-string))
+        actual-arg-count   (count args)]
+    (when (zero? expected-arg-count)
+      (api/reg-finding! (assoc (meta node)
+                               :message (format "Don't use %s with no format string arguments, use %s instead."
+                                                (api/sexpr f)
+                                                (str/replace (str (api/sexpr f)) #"f$" ""))
+                               :type :metabase/validate-logging)))
+    (when-not (= expected-arg-count actual-arg-count)
+      (api/reg-finding! (assoc (meta node)
+                               :message (format "log format string expects %d arguments instead of %d."
+                                                expected-arg-count
+                                                actual-arg-count)
+                               :type :metabase/validate-logging)))))
+
+
+
+(defn infof
+  "Valid logf, debugf, etc."
+  [{:keys [node], :as x}]
+  (common-checks node)
+  (let [[_f & args]               (:children node)
+        [_e format-string & args] (if (api/string-node? (first args))
+                                    (cons nil args)
+                                    args)]
+    ;; TODO -- maybe we can error if you did not pass a format string, e.g. (log/infof 1 2) is obviously incorrect.
+    (when (api/string-node? format-string)
+      (check-for-i18n-format-specifiers node format-string)
+      (check-format-string-arg-count node format-string args)))
+  x)
+
+(comment
+  ;; should fail, missing a format arg
+  (infof
+   {:node (api/parse-string
+           (str '(log/warnf "Migration lock was acquired after %d retries.")))})
+
+  (infof
+   {:node (api/parse-string
+           (str '(log/warnf e "Migration lock was acquired after %d retries.")))})
+
+  ;; should fail, too many format args
+  (infof
+   {:node (api/parse-string
+           (str '(log/warnf "Migration lock was acquired after %d retries." 1 2)))})
+
+  (infof
+   {:node (api/parse-string
+           (str '(log/warnf e "Migration lock was acquired after %d retries." 1 2)))})
+
+  (infof
+   {:node (api/parse-string
+           (str '(log/warnf "Migration lock was acquired after {0} retries." 1)))})
+
+  ;; should fail, has format args but is warn rather than warnf
+  (info
+   {:node (api/parse-string
+           (str '(log/warn e "Migration lock was acquired after %d retries." 1 2)))})
+
+  ;; should fail -- should not use i18n/tru or i18n/trs
+  (infof
+   {:node (api/parse-string
+           (str '(log/warnf (metabase.util.i18n/tru "Migration lock was acquired after {0} retries." 1))))})
+
+  (info
+   {:node (api/parse-string
+           (str '(log/warn (metabase.util.i18n/trs "Migration lock was acquired after {0} retries." 1))))}))
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj
index 7ce177b49a7132661b6a1361ce7be1dff2884d7f..cb8ccd2cac848137523600017316ff2d09374b89 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj
@@ -160,11 +160,11 @@
   (let [path* (or (some-> (get *env* :mb-config-file-path) u.files/get-path)
                   (u.files/get-path (System/getProperty "user.dir") "config.yml"))]
     (if (u.files/exists? path*)
-      (log/info (u/colorize :magenta
-                            (trs "Found config file at path {0}; Metabase will be initialized with values from this file"
-                                 (pr-str (str path*))))
+      (log/info (u/format-color :magenta
+                                "Found config file at path %s; Metabase will be initialized with values from this file"
+                                (pr-str (str path*)))
                 (u/emoji "🗄️"))
-      (log/info (u/colorize :yellow (trs "No config file found at path {0}" (pr-str (str path*))))))
+      (log/info (u/format-color :yellow "No config file found at path %s" (pr-str (str path*)))))
     path*))
 
 (def ^:private ^:dynamic *config*
@@ -260,7 +260,7 @@
         (when-not (premium-features/enable-config-text-file?)
           (throw (ex-info (tru "Metabase config files require a Premium token with the :config-text-file feature.")
                           {}))))
-      (log/info (u/colorize :magenta (trs "Initializing {0} from config file..." section-name)) (u/emoji "🗄️"))
+      (log/info (u/format-color :magenta "Initializing %s from config file..." section-name) (u/emoji "🗄️"))
       (advanced-config.file.i/initialize-section! section-name section-config))
-    (log/info (u/colorize :magenta (trs "Done initializing from file.")) (u/emoji "🗄️")))
+    (log/info (u/colorize :magenta "Done initializing from file.") (u/emoji "🗄️")))
   :ok)
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/file/databases.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/file/databases.clj
index e6ce618863da5606d54c65bfadf249e3d40ce40b..3bd01e3cc5acce78c8dcdb9c63406e5915889f2e 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/file/databases.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/file/databases.clj
@@ -6,7 +6,6 @@
    [metabase.models.database :refer [Database]]
    [metabase.models.setting :refer [defsetting]]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]))
 
@@ -42,14 +41,14 @@
   (driver.u/can-connect-with-details? (keyword (:engine database)) (:details database) :throw-exceptions)
   (if-let [existing-database-id (t2/select-one-pk Database :engine (:engine database), :name (:name database))]
     (do
-      (log/info (u/colorize :blue (trs "Updating Database {0} {1}" (:engine database) (pr-str (:name database)))))
+      (log/info (u/format-color :blue "Updating Database %s %s" (:engine database) (pr-str (:name database))))
       (t2/update! Database existing-database-id database))
     (do
-      (log/info (u/colorize :green (trs "Creating new {0} Database {1}" (:engine database) (pr-str (:name database)))))
+      (log/info (u/format-color :green "Creating new %s Database %s" (:engine database) (pr-str (:name database))))
       (let [db (first (t2/insert-returning-instances! Database database))]
         (if (config-from-file-sync-databases)
           ((requiring-resolve 'metabase.sync/sync-database!) db)
-          (log/info (trs "Sync on database creation when initializing from file is disabled. Skipping sync.")))))))
+          (log/info "Sync on database creation when initializing from file is disabled. Skipping sync."))))))
 
 (defmethod advanced-config.file.i/initialize-section! :databases
   [_section-name databases]
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/file/interface.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/file/interface.clj
index a57c0b45727c5db40d355f33948e43e91b590fd3..9c1e4918ba4687733a5c1407bcb2a5d5847cfecf 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/file/interface.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/file/interface.clj
@@ -1,7 +1,6 @@
 (ns metabase-enterprise.advanced-config.file.interface
   (:require
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (defmulti section-spec
@@ -34,4 +33,4 @@
 ;;; forward-compatible and handle sections that might be unknown in a particular version of Metabase.
 (defmethod initialize-section! :default
   [section-name _section-config]
-  (log/warn (u/colorize :yellow (trs "Ignoring unknown config section {0}." (pr-str section-name)))))
+  (log/warn (u/format-color :yellow "Ignoring unknown config section %s." (pr-str section-name))))
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/file/settings.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/file/settings.clj
index 7949a86902813c2b6034550c6d617709a060af9d..eacb4207748522f54ba0e9597a1dbcdb4a4119cd 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/file/settings.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/file/settings.clj
@@ -3,7 +3,6 @@
    [clojure.spec.alpha :as s]
    [metabase-enterprise.advanced-config.file.interface :as advanced-config.file.i]
    [metabase.models.setting :as setting]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (defmethod advanced-config.file.i/section-spec :settings
@@ -12,7 +11,7 @@
 
 (defmethod advanced-config.file.i/initialize-section! :settings
   [_section-name settings]
-  (log/info (trs "Setting setting values from config file"))
+  (log/info "Setting setting values from config file")
   (doseq [[setting-name setting-value] settings]
-    (log/info (trs "Setting value for Setting {0}" setting-name))
+    (log/infof "Setting value for Setting %s" setting-name)
     (setting/set! setting-name setting-value)))
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/file/users.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/file/users.clj
index ce989d7003484cf54b7f066486072841ef372373..d631b69436dc8be3e6a719a848f7e202bf7619e2 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/file/users.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/file/users.clj
@@ -4,7 +4,6 @@
    [metabase-enterprise.advanced-config.file.interface :as advanced-config.file.i]
    [metabase.models.user :refer [User]]
    [metabase.util :as u]
-   [metabase.util.i18n :as i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]))
 
@@ -42,15 +41,16 @@
   ;; TODO -- if this is the FIRST user, we should probably make them a superuser, right?
   (if-let [existing-user-id (t2/select-one-pk User :email (:email user))]
     (do
-      (log/info (u/colorize :blue (trs "Updating User with email {0}" (pr-str (:email user)))))
+      (log/info (u/format-color :blue "Updating User with email %s" (pr-str (:email user))))
       (t2/update! User existing-user-id user))
     ;; create a new user. If they are the first User, force them to be an admin.
     (let [user (cond-> user
                  (init-from-config-file-is-first-user?) (assoc :is_superuser true))]
-      (log/info (u/colorize :green (trs "Creating the first User for this instance. The first user is always created as an admin.")))
-      (log/info (u/colorize :green (trs "Creating new User {0} with email {1}"
-                                        (pr-str (str (:first_name user) \space (:last_name user)))
-                                        (pr-str (:email user)))))
+      (log/info (u/colorize :green "Creating the first User for this instance. The first user is always created as an admin."))
+      (log/info (u/format-color :green
+                                "Creating new User %s with email %s"
+                                (pr-str (str (:first_name user) \space (:last_name user)))
+                                (pr-str (:email user))))
       (t2/insert! User user))))
 
 (defmethod advanced-config.file.i/initialize-section! :users
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj b/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj
index fe2f46c87655507d4bd67c9d858813f1ed980622..f81c500989aac38525dbb96b91dbe061679a2327 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj
@@ -104,5 +104,5 @@
           ;; in case impersonation used to be enabled and the connection still uses an impersonated role.
           (driver/set-role! driver conn role)))
       (catch Throwable e
-        (log/debug e (tru "Error setting role on connection"))
+        (log/debug e "Error setting role on connection")
         (throw e)))))
diff --git a/enterprise/backend/src/metabase_enterprise/audit_db.clj b/enterprise/backend/src/metabase_enterprise/audit_db.clj
index 2d34ba0a7ed42ece087fbb04c72ad619ac94d08f..4cffc8b6dff380ce2b4c2b2caba4e16155c8eb28 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_db.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_db.clj
@@ -143,7 +143,7 @@
                      :from [(t2/table-name :model/Table)]
                      :where [:= :db_id audit-db-id]}]}
                   {:name [:lower :name]}))
-    (log/infof "Adjusted Audit DB for loading Analytics Content")))
+    (log/info "Adjusted Audit DB for loading Analytics Content")))
 
 (defn- adjust-audit-db-to-host!
   [{audit-db-id :id :keys [engine]}]
diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/column_level_perms_check.clj b/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/column_level_perms_check.clj
index d69350006ff9b145ecef776218c2c2cdfe6f061d..2253a8be6e8a77f0f39a2afb3e8ad86187548e6f 100644
--- a/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/column_level_perms_check.clj
+++ b/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/column_level_perms_check.clj
@@ -4,7 +4,7 @@
    [metabase.api.common :refer [*current-user-id*]]
    [metabase.lib.util.match :as lib.util.match]
    [metabase.public-settings.premium-features :refer [defenterprise]]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]))
 
 (defn- field-ids [form]
@@ -25,8 +25,8 @@
     (when (seq restricted-field-ids)
       (let [fields-ids-in-query (field-ids (m/dissoc-in query [:query :source-query]))]
         (when-not (every? restricted-field-ids fields-ids-in-query)
-          (log/warn (trs "User ''{0}'' attempted to access an inaccessible field. Accessible fields {1}, fields in query {2}"
-                         *current-user-id* (pr-str restricted-field-ids) (pr-str fields-ids-in-query)))
+          (log/warnf "User '%s' attempted to access an inaccessible field. Accessible fields %s, fields in query %s"
+                     *current-user-id* (pr-str restricted-field-ids) (pr-str fields-ids-in-query))
           (throw (ex-info (str (tru "User not able to query field")) {:status 403})))))))
 
 (defenterprise maybe-apply-column-level-perms-check
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/cmd.clj b/enterprise/backend/src/metabase_enterprise/serialization/cmd.clj
index 52af46ad2d14899e4e25b94eacb999a82148fcce..cf9dcee152af85200fb3607322fbda8c60ef0c4e 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/cmd.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/cmd.clj
@@ -60,24 +60,24 @@
   (mdb/setup-db!)
   (check-premium-token!)
   (when-not (load/compatible? path)
-    (log/warn (trs "Dump was produced using a different version of Metabase. Things may break!")))
+    (log/warn "Dump was produced using a different version of Metabase. Things may break!"))
   (let [context (merge {:mode     :skip
                         :on-error :continue}
                        context)]
     (try
-      (log/info (trs "BEGIN LOAD from {0} with context {1}" path context))
+      (log/infof "BEGIN LOAD from %s with context %s" path context)
       (let [all-res    [(load/load! (str path "/users") context)
                         (load/load! (str path "/databases") context)
                         (load/load! (str path "/collections") context)
                         (load/load-settings! path context)]
             reload-fns (filter fn? all-res)]
         (when (seq reload-fns)
-          (log/info (trs "Finished first pass of load; now performing second pass"))
+          (log/info "Finished first pass of load; now performing second pass")
           (doseq [reload-fn reload-fns]
             (reload-fn)))
-        (log/info (trs "END LOAD from {0} with context {1}" path context)))
+        (log/infof "END LOAD from %s with context %s" path context))
       (catch Throwable e
-        (log/error e (trs "ERROR LOAD from {0}: {1}" path (.getMessage e)))
+        (log/errorf e "ERROR LOAD from %s: %s" path (.getMessage e))
         (throw e)))))
 
 (mu/defn v2-load-internal!
@@ -96,7 +96,7 @@
     (check-premium-token!))
   ; TODO This should be restored, but there's no manifest or other meta file written by v2 dumps.
   ;(when-not (load/compatible? path)
-  ;  (log/warn (trs "Dump was produced using a different version of Metabase. Things may break!")))
+  ;  (log/warn "Dump was produced using a different version of Metabase. Things may break!"))
   (log/infof "Loading serialized Metabase files from %s" path)
   (serdes/with-cache
     (v2.load/load-metabase! (v2.ingest/ingest-yaml path) opts)))
@@ -183,7 +183,7 @@
 (defn v1-dump!
   "Legacy Metabase app data dump"
   [path {:keys [state user include-entity-id] :or {state :active} :as opts}]
-  (log/info (trs "BEGIN DUMP to {0} via user {1}" path user))
+  (log/infof "BEGIN DUMP to %s via user %s" path user)
   (mdb/setup-db!)
   (check-premium-token!)
   (t2/select User) ;; TODO -- why??? [editor's note: this comment originally from Cam]
@@ -222,12 +222,12 @@
                   users)))
   (dump/dump-settings! path)
   (dump/dump-dimensions! path)
-  (log/info (trs "END DUMP to {0} via user {1}" path user)))
+  (log/infof "END DUMP to %s via user %s" path user))
 
 (defn v2-dump!
   "Exports Metabase app data to directory at path"
   [path {:keys [collection-ids] :as opts}]
-  (log/info (trs "Exporting Metabase to {0}" path) (u/emoji "🏭 🚛💨"))
+  (log/infof "Exporting Metabase to %s" path)
   (mdb/setup-db!)
   (check-premium-token!)
   (t2/select User) ;; TODO -- why??? [editor's note: this comment originally from Cam]
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/dump.clj b/enterprise/backend/src/metabase_enterprise/serialization/dump.clj
index 1f14d7219dfe53aa56d3607a0c2b8a94d14b457d..81d8ce158c8d194946678fcda4d64695d52d3188 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/dump.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/dump.clj
@@ -3,8 +3,7 @@
   (:require
    [clojure.edn :as edn]
    [clojure.java.io :as io]
-   [metabase-enterprise.serialization.names
-    :refer [fully-qualified-name name-for-logging safe-name]]
+   [metabase-enterprise.serialization.names :refer [fully-qualified-name name-for-logging safe-name]]
    [metabase-enterprise.serialization.serialize :as serialize]
    [metabase.config :as config]
    [metabase.models.dashboard :refer [Dashboard]]
@@ -18,7 +17,6 @@
    [metabase.models.setting :as setting]
    [metabase.models.table :refer [Table]]
    [metabase.models.user :refer [User]]
-   [metabase.util.i18n :as i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.yaml :as yaml]
    [toucan2.core :as t2]))
@@ -94,7 +92,7 @@
     (try
       (spit-entity! path entity)
       (catch Throwable e
-        (log/error e (trs "Error dumping {0}" (name-for-logging entity))))))
+        (log/errorf e "Error dumping %s" (name-for-logging entity)))))
   (spit-yaml! (str path "/manifest.yaml")
              {:serialization-version serialize/serialization-protocol-version
               :metabase-version      config/mb-version-info}))
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/load.clj b/enterprise/backend/src/metabase_enterprise/serialization/load.clj
index 2ee25a43066ef206a90e61baaf1e97a237c6db6d..5f08fbfeb25a7931908a32cad4907c3a490cfe33 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/load.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/load.clj
@@ -597,14 +597,14 @@
   (try
     (-> (fully-qualified-name->context fully-qualified-name) :card)
     (catch Throwable e
-      (log/warn e (trs "Could not find context for fully qualified card name {0}" fully-qualified-name)))))
+      (log/warnf e "Could not find context for fully qualified card name %s" fully-qualified-name))))
 
 (defn- resolve-snippet
   [fully-qualified-name]
   (try
     (-> (fully-qualified-name->context fully-qualified-name) :snippet)
     (catch Throwable e
-      (log/debug e (trs "Could not find context for fully qualified snippet name {0}" fully-qualified-name)))))
+      (log/debugf e "Could not find context for fully qualified snippet name %s" fully-qualified-name))))
 
 (defn- resolve-native
   [card]
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/names.clj b/enterprise/backend/src/metabase_enterprise/serialization/names.clj
index b5ad63bdfa3177bce41ae7eb274f71fdf8e7acc5..dcff336c574a2288a23586fe55489c1d4a6d0ac0 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/names.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/names.clj
@@ -17,7 +17,6 @@
    [metabase.models.segment :refer [Segment]]
    [metabase.models.table :refer [Table]]
    [metabase.models.user :refer [User]]
-   [metabase.util.i18n :as i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli.schema :as ms]
    [ring.util.codec :as codec]
@@ -309,7 +308,7 @@
   [fully-qualified-name]
   (when fully-qualified-name
     (let [components (->> (str/split fully-qualified-name separator-pattern)
-                          rest ; we start with a /
+                          rest          ; we start with a /
                           partition-name-components
                           (map (fn [[model-name & entity-parts]]
                                  (cond-> {::model-name model-name ::entity-name (last entity-parts)}
@@ -318,7 +317,7 @@
                                                           first ; ns is first/only item after "collections"
                                                           rest  ; strip the starting :
                                                           (apply str)))))))
-          context (loop [acc-context                   {}
+          context (loop [acc-context {}
                          [{::keys [model-name entity-name] :as model-map} & more] components]
                     (let [model-attrs (dissoc model-map ::model-name ::entity-name)
                           new-context (path->context acc-context model-name model-attrs (unescape-name entity-name))]
@@ -329,9 +328,9 @@
            (not (mc/validate [:maybe Context] context))
            (not *suppress-log-name-lookup-exception*))
         (log/warn
-         (ex-info (trs "Can''t resolve {0} in fully qualified name {1}"
-                       (str/join ", " (map name (keys context)))
-                       fully-qualified-name)
+         (ex-info (format "Can't resolve %s in fully qualified name %s"
+                          (str/join ", " (map name (keys context)))
+                          fully-qualified-name)
                   {:fully-qualified-name fully-qualified-name
                    :resolve-name-failed? true
                    :context              context}))
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/upsert.clj b/enterprise/backend/src/metabase_enterprise/serialization/upsert.clj
index 45a424e7ddd0388a1cbbd3cb08e98148e916d3b1..9ce8597770385a6136fadf163f6912bd3612c5dd 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/upsert.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/upsert.clj
@@ -132,13 +132,13 @@
    entities]
   (let [{:keys [update insert skip]} (group-by-action context model entities)]
     (doseq [[_ entity _] insert]
-      (log/info (trs "Inserting {0}" (name-for-logging (name model) entity))))
+      (log/infof "Inserting %s" (name-for-logging (name model) entity)))
     (doseq [[_ _ existing] skip]
       (if (= mode :skip)
-        (log/info (trs "{0} already exists -- skipping"  (name-for-logging (name model) existing)))
-        (log/info (trs "Skipping {0} (nothing to update)" (name-for-logging (name model) existing)))))
+        (log/infof "%s already exists -- skipping" (name-for-logging (name model) existing))
+        (log/infof "Skipping %s (nothing to update)" (name-for-logging (name model) existing))))
     (doseq [[_ _ existing] update]
-      (log/info (trs "Updating {0}" (name-for-logging (name model) existing))))
+      (log/infof "Updating %s" (name-for-logging (name model) existing)))
     (->> (concat (for [[position _ existing] skip]
                    [(u/the-id existing) position])
                  (map vector (map post-insert-fn
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/v2/backfill_ids.clj b/enterprise/backend/src/metabase_enterprise/serialization/v2/backfill_ids.clj
index 863df2b5c22f6817f681da09c47ed14dd0c8bff5..7475b3d0d145c67d0b91fd3096c0fdd7ec79f159 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/v2/backfill_ids.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/v2/backfill_ids.clj
@@ -9,7 +9,6 @@
    [metabase.models.interface :as mi]
    [metabase.models.serialization :as serdes]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]
    [toucan2.model :as t2.model]))
@@ -20,7 +19,7 @@
   (let [missing (t2/select model :entity_id nil)
         pk      (first (t2/primary-keys model))]
     (when (seq missing)
-      (log/info (trs "Backfilling entity_id for {0} rows of {1}" (pr-str (count missing)) (name model)))
+      (log/infof "Backfilling entity_id for %s rows of %s" (pr-str (count missing)) (name model))
       (doseq [entity missing
               :let [hashed (serdes/identity-hash entity)
                     eid    (u/generate-nano-id hashed)]]
diff --git a/enterprise/backend/src/metabase_enterprise/sso/api/sso.clj b/enterprise/backend/src/metabase_enterprise/sso/api/sso.clj
index c8282f2c810208b2c2fe865a39e12ee1fa4941cc..ab60d07e026d0c849496921e93cd21cf98ac0a6b 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/api/sso.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/api/sso.clj
@@ -12,7 +12,6 @@
    [metabase.api.common :as api]
    [metabase.server.middleware.session :as mw.session]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -35,7 +34,7 @@
   (try
     (sso.i/sso-get req)
     (catch Throwable e
-      (log/error #_e (trs "Error returning SSO entry point"))
+      (log/error #_e "Error returning SSO entry point")
       (throw e))))
 
 (mu/defn ^:private sso-error-page
@@ -57,7 +56,7 @@
   (try
     (sso.i/sso-post req)
     (catch Throwable e
-      (log/error e (trs "Error logging in"))
+      (log/error e "Error logging in")
       (sso-error-page e "in"))))
 
 
@@ -99,7 +98,7 @@
   (try
     (sso.i/sso-handle-slo req)
     (catch Throwable e
-      (log/error e (trs "Error handling SLO"))
+      (log/error e "Error handling SLO")
       (sso-error-page e "out"))))
 
 (api/define-routes)
diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/saml.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/saml.clj
index 103d5c9a29ebc4fdf306ca936ed6701655d56292..1fc783d622181dc8ffbf6888b34d44d09e1156bc 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/integrations/saml.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/saml.clj
@@ -143,7 +143,7 @@
   (let [redirect (get-in req [:params :redirect])
         redirect-url (if (nil? redirect)
                        (do
-                         (log/warn (trs "Warning: expected `redirect` param, but none is present"))
+                         (log/warn "Warning: expected `redirect` param, but none is present")
                          (public-settings/site-url))
                        (if (has-host? redirect)
                          redirect
@@ -173,7 +173,7 @@
       (saml/validate response idp-cert (sp-cert-keystore-details) {:acs-url (acs-url)
                                                                    :issuer  (sso-settings/saml-identity-provider-issuer)})
       (catch Throwable e
-        (log/error e (trs "SAML response validation failed"))
+        (log/error e "SAML response validation failed")
         (throw (ex-info (tru "Unable to log in: SAML response validation failed")
                         {:status-code 401}
                         e))))))
diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
index 16b9312e6f4082353f896185b5c9e52d91eb4513..d725cbfc7f84a6dfcfcdb282448d2d3222c1b871 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
@@ -8,7 +8,7 @@
    [metabase.models.setting :as setting :refer [defsetting]]
    [metabase.models.setting.multi-setting :refer [define-multi-setting-impl]]
    [metabase.public-settings :as public-settings]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -57,7 +57,7 @@ using, this usually looks like https://your-org-name.example.com or https://exam
   (try
     (instance? java.security.cert.X509Certificate (saml/->X509Certificate idp-cert-str))
     (catch Throwable e
-      (log/error e (trs "Error parsing SAML identity provider certificate"))
+      (log/error e "Error parsing SAML identity provider certificate")
       (throw
        (Exception. (tru "Invalid identity provider certificate. Certificate should be a base-64 encoded string."))))))
 
diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj
index f471e8a7e2f9280473857e43960dcc254fa2729b..c9caffd3dbedb56518a6582f76365597a529ebbc 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj
@@ -60,7 +60,7 @@
   [user :- UserAttributes]
   (try
     (u/prog1 (first (t2/insert-returning-instances! User (merge user {:password (str (random-uuid))})))
-      (log/info (trs "New SSO user created: {0} ({1})" (:common_name <>) (:email <>)))
+      (log/infof "New SSO user created: %s (%s)" (:common_name <>) (:email <>))
       ;; publish user-invited event for audit logging
       (events/publish-event! :event/user-invited {:object (assoc <> :sso_source (:sso_source user))})
       ;; send an email to everyone including the site admin if that's set
diff --git a/modules/drivers/athena/src/metabase/driver/athena.clj b/modules/drivers/athena/src/metabase/driver/athena.clj
index 0489e3b144c7dc72cab8115c6a6774501ea60c1f..56284630aa780f2cb5351ab8e1280569eb2f3aa7 100644
--- a/modules/drivers/athena/src/metabase/driver/athena.clj
+++ b/modules/drivers/athena/src/metabase/driver/athena.clj
@@ -19,7 +19,6 @@
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (java.sql Connection DatabaseMetaData)
@@ -132,7 +131,7 @@
           (u.date/parse s)
           ;; better to catch and log the error here than to barf completely, right?
           (catch Throwable e
-            (log/error e (trs "Error parsing timestamp with time zone string {0}: {1}" (pr-str s) (ex-message e)))
+            (log/errorf e "Error parsing timestamp with time zone string %s: %s" (pr-str s) (ex-message e))
             nil))))
 
     ((get-method sql-jdbc.execute/read-column-thunk [:sql-jdbc java.sql.Types/VARCHAR]) driver rs rsmeta i)))
@@ -290,8 +289,8 @@
   "Given a `database-type` (e.g. `VARCHAR`) return the mapped Metabase type (e.g. `:type/Text`)."
   [driver database-type]
   (or (sql-jdbc.sync/database-type->base-type driver (keyword database-type))
-      (do (log/warn (format "Don't know how to map column type '%s' to a Field base_type, falling back to :type/*."
-                            database-type))
+      (do (log/warnf "Don't know how to map column type '%s' to a Field base_type, falling back to :type/*."
+                     database-type)
           :type/*)))
 
 (defn- run-query
@@ -357,7 +356,7 @@
           (describe-table-fields-with-nested-fields database schema table-name)
           (describe-table-fields-without-nested-fields driver columns))))
     (catch Throwable e
-      (log/error e (trs "Error retreiving fields for DB {0}.{1}" schema table-name))
+      (log/errorf e "Error retreiving fields for DB %s.%s" schema table-name)
       (throw e))))
 
 ;; Becuse describe-table-fields might fail, we catch the error here and return an empty set of columns
diff --git a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj
index 978cc425ca15258b10ebf0137641f137ba313a0b..a64333af88140346b021e98e26c69f81a9d70d4c 100644
--- a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj
+++ b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj
@@ -21,7 +21,7 @@
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.query-processor.util :as qp.util]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -93,7 +93,7 @@
   ;; check whether we can connect by seeing whether listing datasets succeeds
   (let [[success? datasets] (try [true (list-datasets details)]
                                  (catch Exception e
-                                   (log/errorf e (trs "Exception caught in :bigquery-cloud-sdk can-connect?"))
+                                   (log/error e "Exception caught in :bigquery-cloud-sdk can-connect?")
                                    [false nil]))]
     (cond
       (not success?)
@@ -242,9 +242,8 @@
                        method      (get-method bigquery.qp/parse-result-of-type column-type)]
                    (when (= method default-parser)
                      (let [column-name (.getName field)]
-                       (log/warn (trs "Warning: missing type mapping for parsing BigQuery results column {0} of type {1}."
-                                      column-name
-                                      column-type))))
+                       (log/warnf "Warning: missing type mapping for parsing BigQuery results column %s of type %s."
+                                  column-name column-type)))
                    (partial method column-type column-mode bigquery.common/*bigquery-timezone-id*))))
           (.getFields schema))))
 
@@ -344,7 +343,7 @@
       (when cancel-chan
         (future                       ; this needs to run in a separate thread, because the <!! operation blocks forever
           (when (a/<!! cancel-chan)
-            (log/debugf "Received a message on the cancel channel; attempting to stop the BigQuery query execution")
+            (log/debug "Received a message on the cancel channel; attempting to stop the BigQuery query execution")
             (reset! cancel-requested? true) ; signal the page iteration fn to stop
             (if-not (or (future-cancelled? res-fut) (future-done? res-fut))
               ;; somehow, even the FIRST page hasn't come back yet (i.e. the .query call above), so cancel the future to
@@ -492,8 +491,8 @@
   Returns the passed `database` parameter with the aformentioned changes having been made and persisted."
   [database dataset-id]
   (let [db-id (u/the-id database)]
-    (log/infof (trs "DB {0} had hardcoded dataset-id; changing to an inclusion pattern and updating table schemas"
-                    (pr-str db-id)))
+    (log/infof "DB %s had hardcoded dataset-id; changing to an inclusion pattern and updating table schemas"
+               (pr-str db-id))
     (try
       (t2/query-one {:update (t2/table-name :model/Table)
                      :set    {:schema dataset-id}
diff --git a/modules/drivers/druid/src/metabase/driver/druid/client.clj b/modules/drivers/druid/src/metabase/driver/druid/client.clj
index 67e09a91557c60768e735be0257300851743b1c8..8ccf0128b5c9e492b03e852465c1319b8be76550 100644
--- a/modules/drivers/druid/src/metabase/driver/druid/client.clj
+++ b/modules/drivers/druid/src/metabase/driver/druid/client.clj
@@ -1,13 +1,14 @@
 (ns metabase.driver.druid.client
-  (:require [cheshire.core :as json]
-            [clj-http.client :as http]
-            [clojure.core.async :as a]
-            [metabase.models.secret :as secret]
-            [metabase.query-processor.error-type :as qp.error-type]
-            [metabase.util :as u]
-            [metabase.util.i18n :refer [trs tru]]
-            [metabase.util.log :as log]
-            [metabase.util.ssh :as ssh]))
+  (:require
+   [cheshire.core :as json]
+   [clj-http.client :as http]
+   [clojure.core.async :as a]
+   [metabase.models.secret :as secret]
+   [metabase.query-processor.error-type :as qp.error-type]
+   [metabase.util :as u]
+   [metabase.util.i18n :refer [tru]]
+   [metabase.util.log :as log]
+   [metabase.util.ssh :as ssh]))
 
 (set! *warn-on-reflection* true)
 
@@ -81,17 +82,17 @@
                           {:type  qp.error-type/db
                            :query query}
                           e)]
-          (log/error e' (trs "Error running query"))
+          (log/error e' "Error running query")
           ;; Re-throw a new exception with `message` set to the extracted message
           (throw e'))))))
 
 (defn- cancel-query-with-id! [details query-id]
   (if-not query-id
-    (log/warn (trs "Client closed connection, no queryId found, can't cancel query"))
+    (log/warn "Client closed connection, no queryId found, can't cancel query")
     (ssh/with-ssh-tunnel [details-with-tunnel details]
-      (log/warn (trs "Client closed connection, canceling Druid queryId {0}" query-id))
+      (log/warnf "Client closed connection, canceling Druid queryId %s" query-id)
       (try
-        (log/debug (trs "Canceling Druid query with ID {0}" query-id))
+        (log/debugf "Canceling Druid query with ID %s" query-id)
         (DELETE (details->url details-with-tunnel (format "/druid/v2/%s" query-id))
           :auth-enabled     (:auth-enabled details)
           :auth-username    (:auth-username details)
@@ -99,7 +100,7 @@
                                 (secret/db-details-prop->secret-map "auth-token")
                                 secret/value->string))
         (catch Exception cancel-e
-          (log/warn cancel-e (trs "Failed to cancel Druid query with queryId {0}" query-id)))))))
+          (log/warnf cancel-e "Failed to cancel Druid query with queryId %s" query-id))))))
 
 (defn do-query-with-cancellation
   "Run a Druid `query`, canceling it if `canceled-chan` gets a message."
diff --git a/modules/drivers/druid/src/metabase/driver/druid/query_processor.clj b/modules/drivers/druid/src/metabase/driver/druid/query_processor.clj
index 17ed4dae12ca4c8448e150863f878a54b3965698..12de5d5a34edc93386b131c910c6d6af804ec8e4 100644
--- a/modules/drivers/druid/src/metabase/driver/druid/query_processor.clj
+++ b/modules/drivers/druid/src/metabase/driver/druid/query_processor.clj
@@ -16,7 +16,7 @@
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
@@ -420,9 +420,8 @@
     ;; log a warning about all the intervals we filtered out above
     (doseq [intervals subclause-intervals
             :when     (> (count intervals) 1)]
-      (log/warn (tru "WARNING: Don't know how to combine these intervals into a single interval.")
-                "\n"
-                (tru "Ignoring intervals: {0}" intervals)))
+      (log/warnf "WARNING: Don't know how to combine these intervals into a single interval.\nIgnoring intervals: %s"
+                 intervals))
     (reduce
      (fn [[acc] interval]
        [(combine-intervals acc interval)])
@@ -1000,11 +999,11 @@
 (defmethod handle-order-by ::query
   [_ _ druid-query]
   (log/warn
-   (u/format-color 'red
-       (tru "Sorting with Druid is only allowed in queries that have one or more breakout columns. Ignoring :order-by clause.")))
+   (u/format-color
+    'red
+    "Sorting with Druid is only allowed in queries that have one or more breakout columns. Ignoring :order-by clause."))
   druid-query)
 
-
 (defmethod handle-order-by ::topN
   [_ {[ag] :aggregation, [breakout-field] :breakout, [[direction field]] :order-by} druid-query]
   (let [field             (->rvalue field)
@@ -1054,7 +1053,7 @@
   [_ {[[direction field]] :order-by} druid-query]
   (let [can-sort? (if (temporal-field? field)
                     true
-                    (log/warn (trs "grouped timeseries queries can only be sorted by the ''timestamp'' column.")))]
+                    (log/warn "grouped timeseries queries can only be sorted by the 'timestamp' column."))]
     (cond-> druid-query
       can-sort? (assoc-in [:query :descending] (= direction :desc)))))
 
@@ -1062,10 +1061,10 @@
   [_ {[[direction field]] :order-by, fields :fields} druid-query]
   (let [can-sort? (cond
                     (not (some temporal-field? fields))
-                    (log/warn (trs "scan queries can only be sorted if they include the ''timestamp'' column."))
+                    (log/warn "scan queries can only be sorted if they include the 'timestamp' column.")
 
                     (not (temporal-field? field))
-                    (log/warn (trs "scan queries can only be sorted by the ''timestamp'' column."))
+                    (log/warn "scan queries can only be sorted by the 'timestamp' column.")
 
                     :else
                     true)]
@@ -1087,7 +1086,7 @@
     (log/warn
      (u/format-color 'red
          ;; TODO - this is not really true, is it
-         (tru "WARNING: It only makes sense to specify :fields for a query with no aggregation. Ignoring the clause."))))
+         "WARNING: It only makes sense to specify :fields for a query with no aggregation. Ignoring the clause.")))
   druid-query)
 
 (defmethod handle-fields ::scan
@@ -1138,8 +1137,7 @@
   [_ {limit :limit} druid-query]
   (when limit
     (log/warn
-     (u/format-color 'red
-         (tru "WARNING: Druid does not allow limitSpec in time series queries. Ignoring the LIMIT clause."))))
+     (u/format-color 'red "WARNING: Druid does not allow limitSpec in time series queries. Ignoring the LIMIT clause.")))
   druid-query)
 
 (defmethod handle-limit ::topN
diff --git a/modules/drivers/googleanalytics/src/metabase/driver/google.clj b/modules/drivers/googleanalytics/src/metabase/driver/google.clj
index bfdcaa8d0f1eb93e068657cc8bfb89f856c9f4f6..1bee36ba8bb616ab1d51944fa858adc99fe81494 100644
--- a/modules/drivers/googleanalytics/src/metabase/driver/google.clj
+++ b/modules/drivers/googleanalytics/src/metabase/driver/google.clj
@@ -7,7 +7,6 @@
    [metabase.query-processor.error-type :as qp.error-type]
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [ring.util.codec :as codec]
    #_{:clj-kondo/ignore [:discouraged-namespace]}
@@ -74,8 +73,7 @@
 (defn- fetch-access-and-refresh-tokens* [scopes, ^String client-id, ^String client-secret, ^String auth-code]
   {:pre  [(seq client-id) (seq client-secret) (seq auth-code)]
    :post [(seq (:access-token %)) (seq (:refresh-token %))]}
-
-  (log/info (u/format-color 'magenta (trs "Fetching Google access/refresh tokens with auth-code {0}..." (pr-str auth-code))))
+  (log/info (u/format-color :magenta "Fetching Google access/refresh tokens with auth-code %s..." (pr-str auth-code)))
   (let [^GoogleAuthorizationCodeFlow flow
         (.build (doto (GoogleAuthorizationCodeFlow$Builder. http-transport json-factory client-id client-secret scopes)
                   (.setAccessType "offline")))
diff --git a/modules/drivers/mongo/src/metabase/driver/mongo/parameters.clj b/modules/drivers/mongo/src/metabase/driver/mongo/parameters.clj
index f98f502bf05e77df00507c7de1f0c92f54b68bf0..c63485ba9d87c9aaee502c0a05c8f4d363ea784b 100644
--- a/modules/drivers/mongo/src/metabase/driver/mongo/parameters.clj
+++ b/modules/drivers/mongo/src/metabase/driver/mongo/parameters.clj
@@ -208,7 +208,7 @@
     x
     (u/prog1 (substitute param->value (params.parse/parse x false))
       (when-not (= x <>)
-        (log/debug (tru "Substituted {0} -> {1}" (pr-str x) (pr-str <>)))))))
+        (log/debugf "Substituted %s -> %s" (pr-str x) (pr-str <>))))))
 
 (defn substitute-native-parameters
   "Implementation of [[metabase.driver/substitute-native-parameters]] for MongoDB."
diff --git a/modules/drivers/oracle/src/metabase/driver/oracle.clj b/modules/drivers/oracle/src/metabase/driver/oracle.clj
index 1af1a51028c068532e4a4031168397b18c244d41..65288a6c80e9bfe1c89f9c2fd7dfe12ab12f19f9 100644
--- a/modules/drivers/oracle/src/metabase/driver/oracle.clj
+++ b/modules/drivers/oracle/src/metabase/driver/oracle.clj
@@ -24,7 +24,6 @@
    [metabase.models.secret :as secret]
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.ssh :as ssh])
   (:import
@@ -572,7 +571,7 @@
       (try
         (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
         (catch Throwable e
-          (log/debug e (trs "Error setting result set fetch direction to FETCH_FORWARD"))))
+          (log/debug e "Error setting result set fetch direction to FETCH_FORWARD")))
       (sql-jdbc.execute/set-parameters! driver stmt params)
       stmt
       (catch Throwable e
@@ -589,7 +588,7 @@
       (try
         (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
         (catch Throwable e
-          (log/debug e (trs "Error setting result set fetch direction to FETCH_FORWARD"))))
+          (log/debug e "Error setting result set fetch direction to FETCH_FORWARD")))
       stmt
       (catch Throwable e
         (.close stmt)
diff --git a/modules/drivers/presto-jdbc/src/metabase/driver/presto_jdbc.clj b/modules/drivers/presto-jdbc/src/metabase/driver/presto_jdbc.clj
index 036ba5ceb517e6367fbf90b6105637de96367693..4582c1d71d6186f752621a8f67fbb2a233ac363a 100644
--- a/modules/drivers/presto-jdbc/src/metabase/driver/presto_jdbc.clj
+++ b/modules/drivers/presto-jdbc/src/metabase/driver/presto_jdbc.clj
@@ -564,7 +564,7 @@
   implementation."
   [driver conn catalog schema]
   (let [sql (describe-schema-sql driver catalog schema)]
-    (log/trace (trs "Running statement in describe-schema: {0}" sql))
+    (log/tracef "Running statement in describe-schema: %s" sql)
     (into #{} (comp (filter (fn [{table-name :table}]
                                 (have-select-privilege? driver conn schema table-name)))
                     (map (fn [{table-name :table}]
@@ -577,7 +577,7 @@
   implementation."
   [driver conn catalog]
   (let [sql (describe-catalog-sql driver catalog)]
-    (log/trace (trs "Running statement in all-schemas: {0}" sql))
+    (log/tracef "Running statement in all-schemas: %s" sql)
     (into []
           (map (fn [{:keys [schema]}]
                  (when-not (contains? excluded-schemas schema)
@@ -603,7 +603,7 @@
    nil
    (fn [^Connection conn]
      (let [sql (describe-table-sql driver catalog schema table-name)]
-       (log/trace (trs "Running statement in describe-table: {0}" sql))
+       (log/tracef "Running statement in describe-table: %s" sql)
        {:schema schema
         :name   table-name
         :fields (into
@@ -646,7 +646,7 @@
          (try
            (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
            (catch Throwable e
-             (log/debug e (trs "Error setting prepared statement fetch direction to FETCH_FORWARD"))))
+             (log/debug e "Error setting prepared statement fetch direction to FETCH_FORWARD")))
          (sql-jdbc.execute/set-parameters! driver stmt params)
          stmt
          (catch Throwable e
@@ -663,7 +663,7 @@
     (try
       (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
       (catch Throwable e
-        (log/debug e (trs "Error setting statement fetch direction to FETCH_FORWARD"))))
+        (log/debug e "Error setting statement fetch direction to FETCH_FORWARD")))
     stmt))
 
 (defn- pooled-conn->presto-conn
@@ -689,7 +689,7 @@
       (try
         (.setReadOnly conn read-only?)
         (catch Throwable e
-          (log/debug e (trs "Error setting connection read-only to {0}" (pr-str read-only?))))))))
+          (log/debugf e "Error setting connection read-only to %s" (pr-str read-only?)))))))
 
 (defmethod sql-jdbc.execute/do-with-connection-with-options :presto-jdbc
   [driver db-or-id-or-spec options f]
diff --git a/modules/drivers/redshift/src/metabase/driver/redshift.clj b/modules/drivers/redshift/src/metabase/driver/redshift.clj
index 4dbcbfa9e4bef298480e8ad2477de1542349041c..370140b4b2f5e2d36a60fe31bbc8ef4e491d49f5 100644
--- a/modules/drivers/redshift/src/metabase/driver/redshift.clj
+++ b/modules/drivers/redshift/src/metabase/driver/redshift.clj
@@ -23,7 +23,6 @@
    [metabase.upload :as upload]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (com.amazon.redshift.util RedshiftInterval)
@@ -182,7 +181,7 @@
        (try
          (.setHoldability conn ResultSet/CLOSE_CURSORS_AT_COMMIT)
          (catch Throwable e
-           (log/debug e (trs "Error setting default holdability for connection")))))
+           (log/debug e "Error setting default holdability for connection"))))
      (f conn))))
 
 (defn- prepare-statement ^PreparedStatement [^Connection conn sql]
@@ -394,7 +393,7 @@
                           (or has-perm?
                               (log/tracef "Ignoring schema %s because no USAGE privilege on it" table-schema))))
                       (catch Throwable e
-                        (log/error e (trs "Error checking schema permissions"))
+                        (log/error e "Error checking schema permissions")
                         false))))
           reducible))))))
 
diff --git a/modules/drivers/redshift/test/metabase/test/data/redshift.clj b/modules/drivers/redshift/test/metabase/test/data/redshift.clj
index b74044ec0772ac1c70120a26c8079bcbf4f4f72b..d8c836a2baca882e70ac2e5324d0131e5a3b422a 100644
--- a/modules/drivers/redshift/test/metabase/test/data/redshift.clj
+++ b/modules/drivers/redshift/test/metabase/test/data/redshift.clj
@@ -134,10 +134,10 @@
                              (catch com.amazon.redshift.util.RedshiftException e
                                (if (re-find #"relation .* does not exist" (or (ex-message e) ""))
                                  :old-style-cache
-                                 (do (log/error "Error classifying cache schema" e)
+                                 (do (log/error e "Error classifying cache schema")
                                      :unknown-error)))
                              (catch Exception e
-                               (log/error "Error classifying cache schema" e)
+                               (log/error e "Error classifying cache schema")
                                :unknown-error)))]
 
         (group-by classify! schemas)))))
diff --git a/modules/drivers/snowflake/src/metabase/driver/snowflake.clj b/modules/drivers/snowflake/src/metabase/driver/snowflake.clj
index db268d25beda07bdca1dee009e6388f5764f1c72..2e906d68873d4634b7865ba2e649cef3dff27225 100644
--- a/modules/drivers/snowflake/src/metabase/driver/snowflake.clj
+++ b/modules/drivers/snowflake/src/metabase/driver/snowflake.clj
@@ -36,7 +36,7 @@
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [ring.util.codec :as codec])
   (:import
@@ -125,7 +125,8 @@
 (defmethod sql-jdbc.conn/connection-details->spec :snowflake
   [_ {:keys [account additional-options host use-hostname], :as details}]
   (when (get "week_start" (sql-jdbc.common/additional-options->map additional-options :url))
-    (log/warn (trs "You should not set WEEK_START in Snowflake connection options; this might lead to incorrect results. Set the Start of Week Setting instead.")))
+    (log/warn (str "You should not set WEEK_START in Snowflake connection options; this might lead to incorrect "
+                   "results. Set the Start of Week Setting instead.")))
   (let [upcase-not-nil (fn [s] (when s (u/upper-case-en s)))]
     ;; it appears to be the case that their JDBC driver ignores `db` -- see my bug report at
     ;; https://support.snowflake.net/s/question/0D50Z00008WTOMCSA5/
@@ -133,10 +134,10 @@
                 :subprotocol                                "snowflake"
                 ;; see https://github.com/metabase/metabase/issues/22133
                 :subname                                    (let [base-url (if (and use-hostname (string? host) (not (str/blank? host)))
-                                                                              (cond-> host
-                                                                                (not= (last host) \/) (str "/"))
-                                                                              (str account ".snowflakecomputing.com/"))]
-                                                              (str "//" base-url ))
+                                                                             (cond-> host
+                                                                               (not= (last host) \/) (str "/"))
+                                                                             (str account ".snowflakecomputing.com/"))]
+                                                              (str "//" base-url))
                 :client_metadata_request_use_connection_ctx true
                 :ssl                                        true
                 ;; keep open connections open indefinitely instead of closing them. See #9674 and
diff --git a/modules/drivers/sqlserver/src/metabase/driver/sqlserver.clj b/modules/drivers/sqlserver/src/metabase/driver/sqlserver.clj
index 4ef3e1ae557ffd035e31b60b708e688c91977db2..ffd39807700a2b4ce3bc40f8e4a8f75b1b6c7c51 100644
--- a/modules/drivers/sqlserver/src/metabase/driver/sqlserver.clj
+++ b/modules/drivers/sqlserver/src/metabase/driver/sqlserver.clj
@@ -22,7 +22,6 @@
    [metabase.query-processor.interface :as qp.i]
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (java.sql Connection ResultSet Time)
@@ -46,7 +45,7 @@
   [_ _ db]
   (let [major-version (get-in db [:dbms_version :semantic-version 0] 0)]
     (when (zero? major-version)
-      (log/warn (trs "Unable to determine sqlserver's dbms major version. Fallback to 0.")))
+      (log/warn "Unable to determine sqlserver's dbms major version. Fallback to 0."))
     (>= major-version 16)))
 
 (defmethod driver/db-start-of-week :sqlserver
@@ -714,7 +713,7 @@
       (try
         (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
         (catch Throwable e
-          (log/debug e (trs "Error setting statement fetch direction to FETCH_FORWARD"))))
+          (log/debug e "Error setting statement fetch direction to FETCH_FORWARD")))
       stmt
       (catch Throwable e
         (.close stmt)
diff --git a/modules/drivers/vertica/src/metabase/driver/vertica.clj b/modules/drivers/vertica/src/metabase/driver/vertica.clj
index 787213d763176bbb636b138f1c69e49479f4329f..b2e5cc444aad457688653b83a1fec69850a926b2 100644
--- a/modules/drivers/vertica/src/metabase/driver/vertica.clj
+++ b/modules/drivers/vertica/src/metabase/driver/vertica.clj
@@ -17,7 +17,6 @@
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (java.sql ResultSet ResultSetMetaData Types)))
@@ -244,7 +243,7 @@
   (try (set (jdbc/query (sql-jdbc.conn/db->pooled-connection-spec database)
                         ["SELECT TABLE_SCHEMA AS \"schema\", TABLE_NAME AS \"name\" FROM V_CATALOG.VIEWS;"]))
        (catch Throwable e
-         (log/error e (trs "Failed to fetch materialized views for this database")))))
+         (log/error e "Failed to fetch materialized views for this database"))))
 
 (defmethod driver/describe-database :vertica
   [driver database]
diff --git a/src/metabase/analytics/prometheus.clj b/src/metabase/analytics/prometheus.clj
index a66c56822f866a5404c44d034e7ffc8766f22051..99c63447d18b3feef0377eebad1942efa56205da 100644
--- a/src/metabase/analytics/prometheus.clj
+++ b/src/metabase/analytics/prometheus.clj
@@ -42,8 +42,7 @@
                 (let [parse (fn [raw-value]
                               (if-let [parsed (parse-long raw-value)]
                                 parsed
-                                (log/warn (trs "MB_PROMETHEUS_SERVER_PORT value of ''{0}'' is not parseable as an integer."
-                                               raw-value))))]
+                                (log/warnf "MB_PROMETHEUS_SERVER_PORT value of '%s' is not parseable as an integer." raw-value)))]
                   (setting/get-raw-value :prometheus-server-port integer? parse))))
 
 (p.types/defprotocol+ PrometheusActions
@@ -140,8 +139,7 @@
           (doseq [m measurements]
             (.addMetric gauge (List/of (:label m)) (:value m)))
           (.add arr gauge))
-        (log/warn (trs "Unrecognized measurement {0} in prometheus stats"
-                       raw-label))))
+        (log/warnf "Unrecognized measurement %s in prometheus stats" raw-label)))
     arr))
 
 (defn- conn-pool-bean-diag-info [acc ^ObjectName jmx-bean]
@@ -199,7 +197,7 @@
   "Instrument the application. Conditionally done when some setting is set. If [[prometheus-server-port]] is not set it
   will throw."
   [registry-name]
-  (log/info (trs "Starting prometheus metrics collector"))
+  (log/info "Starting prometheus metrics collector")
   (let [registry (prometheus/collector-registry registry-name)]
     (apply prometheus/register registry
            (concat (jvm-collectors)
@@ -214,7 +212,7 @@
 (defn- start-web-server!
   "Start the prometheus web-server. If [[prometheus-server-port]] is not set it will throw."
   [port registry]
-  (log/info (trs "Starting prometheus metrics web-server on port {0}" (str port)))
+  (log/infof "Starting prometheus metrics web-server on port %s" (str port))
   (when-not port
     (throw (ex-info (trs "Attempting to set up prometheus metrics web-server with no web-server port provided")
                     {})))
@@ -248,9 +246,9 @@
         (try (stop-web-server system)
              (prometheus/clear (.-registry system))
              (alter-var-root #'system (constantly nil))
-             (log/info (trs "Prometheus web-server shut down"))
+             (log/info "Prometheus web-server shut down")
              (catch Exception e
-               (log/warn e (trs "Error stopping prometheus web-server"))))))))
+               (log/warn e "Error stopping prometheus web-server")))))))
 
 (defn inc
   "Call iapetos.core/inc on the metric in the global registry,
diff --git a/src/metabase/analytics/snowplow.clj b/src/metabase/analytics/snowplow.clj
index 10916a20bb465aa16024df8c1af5ded2adf88564..c1bb56ecd44e2906a648cf885b2fc6c262143f67 100644
--- a/src/metabase/analytics/snowplow.clj
+++ b/src/metabase/analytics/snowplow.clj
@@ -9,7 +9,7 @@
    [metabase.models.user :refer [User]]
    [metabase.public-settings :as public-settings]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :refer [deferred-tru trs]]
+   [metabase.util.i18n :refer [deferred-tru]]
    [metabase.util.log :as log]
    [toucan2.core :as t2])
   (:import
@@ -249,4 +249,4 @@
             ^SelfDescribing event (.build builder)]
         (track-event-impl! (tracker) event))
       (catch Throwable e
-        (log/error e (trs "Error sending Snowplow analytics event {0}" event-kw))))))
+        (log/errorf e "Error sending Snowplow analytics event %s" event-kw)))))
diff --git a/src/metabase/analytics/stats.clj b/src/metabase/analytics/stats.clj
index 8c3a870910bdf506200ea1f50c3fa8a11e2ec09e..447a3087f2e1f7fa33844b8eb5b0c7151a90b27d 100644
--- a/src/metabase/analytics/stats.clj
+++ b/src/metabase/analytics/stats.clj
@@ -22,7 +22,6 @@
    [metabase.public-settings :as public-settings]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]))
 
@@ -437,7 +436,7 @@
   (try
      (http/post metabase-usage-url {:form-params stats, :content-type :json, :throw-entire-message? true})
      (catch Throwable e
-       (log/error e (trs "Sending usage stats FAILED")))))
+       (log/error e "Sending usage stats FAILED"))))
 
 
 (defn phone-home-stats!
diff --git a/src/metabase/api/card.clj b/src/metabase/api/card.clj
index 741514fd9718c8585e0927abfbacea91cde786de..f40cbfd956baa4b26c3de7045b559d2340354765 100644
--- a/src/metabase/api/card.clj
+++ b/src/metabase/api/card.clj
@@ -549,7 +549,7 @@
                    hydrate-card-details
                    (assoc :last-edit-info (last-edit/edit-information-for-user @api/*current-user*)))
         (when timed-out?
-          (log/info (trs "Metadata not available soon enough. Saving card {0} and asynchronously updating metadata" id))
+          (log/infof "Metadata not available soon enough. Saving card %s and asynchronously updating metadata" id)
           (card/schedule-metadata-saving result-metadata-chan <>))))))
 
 
diff --git a/src/metabase/api/database.clj b/src/metabase/api/database.clj
index e453de52dfec22676c6a767ec45ead47f6146612..42e7123251ac5eeaae1e779df84ac8d70c9e18d8 100644
--- a/src/metabase/api/database.clj
+++ b/src/metabase/api/database.clj
@@ -146,7 +146,7 @@
                    (when-let [db (t2/select-one Database :id db-id)]
                      (driver/database-supports? (:engine db) :nested-queries db))
                    (catch Throwable e
-                     (log/error e (tru "Error determining whether Database supports nested queries")))))
+                     (log/error e "Error determining whether Database supports nested queries"))))
                (t2/select-pks-set Database))))
 
 (mu/defn ^:private source-query-cards
@@ -654,7 +654,7 @@
                 substring (autocomplete-suggestions id (str "%" substring "%"))
                 prefix    (autocomplete-suggestions id (str prefix "%")))}
     (catch Throwable e
-      (log/warn e (trs "Error with autocomplete: {0}" (ex-message e))))))
+      (log/warnf e "Error with autocomplete: %s" (ex-message e)))))
 
 (api/defendpoint GET "/:id/card_autocomplete_suggestions"
   "Return a list of `Card` autocomplete suggestions for a given `query` in a given `Database`.
@@ -669,7 +669,7 @@
          (filter mi/can-read?)
          (map #(select-keys % [:id :name :type :collection_name])))
     (catch Throwable e
-      (log/warn e (trs "Error with autocomplete: {0}" (ex-message e))))))
+      (log/warnf e "Error with autocomplete: %s" (ex-message e)))))
 
 
 ;;; ------------------------------------------ GET /api/database/:id/fields ------------------------------------------
@@ -740,7 +740,7 @@
         {:message (tru "Unable to connect to database.")})
       (catch Throwable e
         (when (and log-exception (not (some->> e ex-cause ex-data ::driver/can-connect-message?)))
-          (log/error e (trs "Cannot connect to Database")))
+          (log/error e "Cannot connect to Database"))
         (if (-> e ex-data :message)
           (ex-data e)
           {:message (.getMessage e)})))))
diff --git a/src/metabase/api/dataset.clj b/src/metabase/api/dataset.clj
index 3cfcb37d942382500eeeabaaa68ffef843c65607..b017098364aff92b77fdb0af7bb743d2d95de56c 100644
--- a/src/metabase/api/dataset.clj
+++ b/src/metabase/api/dataset.clj
@@ -27,7 +27,7 @@
    [metabase.query-processor.util :as qp.util]
    [metabase.shared.models.visualization-settings :as mb.viz]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -43,7 +43,7 @@
   well."
   [outer-query]
   (when-let [source-card-id (qp.util/query->source-card-id outer-query)]
-    (log/info (trs "Source query for this query is Card {0}" (pr-str source-card-id)))
+    (log/infof "Source query for this query is Card %s" (pr-str source-card-id))
     (api/read-check Card source-card-id)
     source-card-id))
 
diff --git a/src/metabase/api/field.clj b/src/metabase/api/field.clj
index 330f15b8831b2227f5a4eab9384197ba512945c3..2fb1fcede7ec25d21ecf757bb7c1acedf5212929 100644
--- a/src/metabase/api/field.clj
+++ b/src/metabase/api/field.clj
@@ -21,7 +21,6 @@
    [metabase.sync.concurrent :as sync.concurrent]
    [metabase.types :as types]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -381,7 +380,7 @@
           limit        (or maybe-limit default-max-field-search-limit)]
       (metadata-queries/search-values-query field search-field value limit))
     (catch Throwable e
-      (log/error e (trs "Error searching field values"))
+      (log/error e "Error searching field values")
       []))))
 
 (api/defendpoint GET "/:id/search/:search-id"
@@ -423,7 +422,7 @@
       (first (get-in results [:data :rows])))
     ;; as with fn above this error can usually be safely ignored which is why log level is log/debug
     (catch Throwable e
-      (log/debug e (trs "Error searching for remapping"))
+      (log/debug e "Error searching for remapping")
       nil)))
 
 (defn parse-query-param-value-for-field
diff --git a/src/metabase/api/metric.clj b/src/metabase/api/metric.clj
index 3b223da01004f380f42025b55a5f0e14e70785c9..ab8c635b1d2683e2713a6a78a291722738ad3005 100644
--- a/src/metabase/api/metric.clj
+++ b/src/metabase/api/metric.clj
@@ -11,7 +11,6 @@
    [metabase.models.revision :as revision]
    [metabase.related :as related]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -128,8 +127,7 @@
   [id revision_message]
   {id               ms/PositiveInt
    revision_message ms/NonBlankString}
-  (log/warn
-   (trs "DELETE /api/legacy-metric/:id is deprecated. Instead, change its `archived` value via PUT /api/legacy-metric/:id."))
+  (log/warn "DELETE /api/legacy-metric/:id is deprecated. Instead, change its `archived` value via PUT /api/legacy-metric/:id.")
   (write-check-and-update-metric! id {:archived true, :revision_message revision_message})
   api/generic-204-no-content)
 
diff --git a/src/metabase/api/persist.clj b/src/metabase/api/persist.clj
index 20cd3e02b46eee32c25ecedf7682f623f715fa5a..618025a33b9060e96a135fc077e6a25673760347 100644
--- a/src/metabase/api/persist.clj
+++ b/src/metabase/api/persist.clj
@@ -119,7 +119,7 @@
   "Enable global setting to allow databases to persist models."
   []
   (validation/check-has-application-permission :setting)
-  (log/info (tru "Enabling model persistence"))
+  (log/info "Enabling model persistence")
   (public-settings/persisted-models-enabled! true)
   (task.persist-refresh/enable-persisting!)
   api/generic-204-no-content)
@@ -132,7 +132,7 @@
   []
   (let [id->db      (m/index-by :id (t2/select Database))
         enabled-dbs (filter (comp :persist-models-enabled :settings) (vals id->db))]
-    (log/info (tru "Disabling model persistence"))
+    (log/info "Disabling model persistence")
     (doseq [db enabled-dbs]
       (t2/update! Database (u/the-id db)
                   {:settings (not-empty (dissoc (:settings db) :persist-models-enabled))}))
diff --git a/src/metabase/api/segment.clj b/src/metabase/api/segment.clj
index 68890f5e8b0f181ba3fd3bd45cb692fd0c225da2..b52e9223c714eff4606f0115b394f62ed7867555 100644
--- a/src/metabase/api/segment.clj
+++ b/src/metabase/api/segment.clj
@@ -10,7 +10,6 @@
    [metabase.models.segment :as segment :refer [Segment]]
    [metabase.related :as related]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -94,8 +93,7 @@
   [id revision_message]
   {id               ms/PositiveInt
    revision_message ms/NonBlankString}
-  (log/warn
-   (trs "DELETE /api/segment/:id is deprecated. Instead, change its `archived` value via PUT /api/segment/:id."))
+  (log/warn "DELETE /api/segment/:id is deprecated. Instead, change its `archived` value via PUT /api/segment/:id.")
   (write-check-and-update-segment! id {:archived true, :revision_message revision_message})
   api/generic-204-no-content)
 
diff --git a/src/metabase/api/session.clj b/src/metabase/api/session.clj
index ac718252a35d28878c7ca5793e446cb44a7b02cd..d64b3d60876fe5ae09b5ac365717f9f70c1fc568 100644
--- a/src/metabase/api/session.clj
+++ b/src/metabase/api/session.clj
@@ -21,7 +21,7 @@
    [metabase.server.middleware.session :as mw.session]
    [metabase.server.request.util :as req.util]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -124,7 +124,7 @@
                             {:status-code 401
                              :errors      {:_error disabled-account-snippet}})))))
       (catch LDAPSDKException e
-        (log/error e (trs "Problem connecting to LDAP server, will fall back to local authentication"))))))
+        (log/error e "Problem connecting to LDAP server, will fall back to local authentication")))))
 
 (mu/defn ^:private email-login :- [:maybe [:map [:id uuid?]]]
   "Find a matching `User` if one exists and return a new Session for them, or `nil` if they couldn't be authenticated."
@@ -341,7 +341,7 @@
     (try
       (handler request respond raise)
       (catch Throwable e
-        (log/error e (trs "Authentication endpoint error"))
+        (log/error e "Authentication endpoint error")
         (throw e)))))
 
 ;;; ----------------------------------------------------- Unsubscribe non-users from pulses -----------------------------------------------
diff --git a/src/metabase/api/setup.clj b/src/metabase/api/setup.clj
index dd15c4f39823f80fd4ee17333af0758ebee7652d..0998eb47823d8275b2f6bf6a710a377dd9b751f3 100644
--- a/src/metabase/api/setup.clj
+++ b/src/metabase/api/setup.clj
@@ -25,7 +25,7 @@
    [metabase.server.middleware.session :as mw.session]
    [metabase.setup :as setup]
    [metabase.util :as u]
-   [metabase.util.i18n :as i18n :refer [trs tru]]
+   [metabase.util.i18n :as i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -76,7 +76,7 @@
 (defn- setup-maybe-create-and-invite-user! [{:keys [email] :as user}, invitor]
   (when email
     (if-not (email/email-configured?)
-      (log/error (trs "Could not invite user because email is not configured."))
+      (log/error "Could not invite user because email is not configured.")
       (u/prog1 (user/create-and-invite-user! user invitor true)
         (user/set-permissions-groups! <> [(perms-group/all-users) (perms-group/admin)])
         (events/publish-event! :event/user-invited {:object (assoc <> :invite_method "email")})
diff --git a/src/metabase/api/table.clj b/src/metabase/api/table.clj
index 4ff244a92e6b6c47d69352c98c9ef26d0e22597a..f3c02c213015cae6d3f15d55311ab74cc499ac6d 100644
--- a/src/metabase/api/table.clj
+++ b/src/metabase/api/table.clj
@@ -25,7 +25,7 @@
    [metabase.types :as types]
    [metabase.upload :as upload]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -88,10 +88,10 @@
          (if (binding [h2/*allow-testing-h2-connections* true]
                (driver.u/can-connect-with-details? (:engine database) (:details database)))
            (doseq [table newly-unhidden]
-             (log/info (u/format-color 'green (trs "Table ''{0}'' is now visible. Resyncing." (:name table))))
+             (log/info (u/format-color :green "Table '%s' is now visible. Resyncing." (:name table)))
              (sync/sync-table! table))
-           (log/warn (u/format-color 'red (trs "Cannot connect to database ''{0}'' in order to sync unhidden tables"
-                                               (:name database))))))))))
+           (log/warn (u/format-color :red "Cannot connect to database '%s' in order to sync unhidden tables"
+                                     (:name database)))))))))
 
 (defn- update-tables!
   [ids {:keys [visibility_type] :as body}]
diff --git a/src/metabase/async/streaming_response.clj b/src/metabase/async/streaming_response.clj
index 6946bbb014aa35d97d682dd05f54b241c1d785dc..faaf131f697504ba115767565a7dd195de41d19c 100644
--- a/src/metabase/async/streaming_response.clj
+++ b/src/metabase/async/streaming_response.clj
@@ -7,7 +7,6 @@
    [metabase.async.util :as async.u]
    [metabase.server.protocols :as server.protocols]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [potemkin.types :as p.types]
    [pretty.core :as pretty]
@@ -62,7 +61,7 @@
           (json/generate-stream obj writer))
         (catch EofException _)
         (catch Throwable e
-          (log/error e (trs "Error writing error to output stream") obj))))))
+          (log/error e "Error writing error to output stream" obj))))))
 
 (defn- do-f* [f ^OutputStream os _finished-chan canceled-chan]
   (try
@@ -74,7 +73,7 @@
       (a/>!! canceled-chan ::thread-interrupted)
       nil)
     (catch Throwable e
-      (log/error e (trs "Caught unexpected Exception in streaming response body"))
+      (log/error e "Caught unexpected Exception in streaming response body")
       (write-error! os e)
       nil)))
 
@@ -87,7 +86,7 @@
                (try
                  (do-f* f os finished-chan canceled-chan)
                  (catch Throwable e
-                   (log/error e (trs "bound-fn caught unexpected Exception"))
+                   (log/error e "bound-fn caught unexpected Exception")
                    (a/>!! finished-chan :unexpected-error))
                  (finally
                    (a/>!! finished-chan (if (a/poll! canceled-chan)
@@ -149,7 +148,7 @@
     (catch ClosedChannelException _
       true)
     (catch Throwable e
-      (log/error e (trs "Error determining whether HTTP request was canceled"))
+      (log/error e "Error determining whether HTTP request was canceled")
       false)))
 
 (def ^:private async-cancellation-poll-timeout-ms
@@ -173,8 +172,8 @@
           ;; was completed) then close `canceled-status-chan` which will kill the underlying thread
           (a/close! canceled-status-chan)
           (when (= port status-timeout-chan)
-            (log/debug (trs "Check cancelation status timed out after {0}"
-                            (u/format-milliseconds async-cancellation-poll-timeout-ms))))
+            (log/debugf "Check cancelation status timed out after %s"
+                        (u/format-milliseconds async-cancellation-poll-timeout-ms)))
           (when (not= port finished-chan)
             (if canceled?
               (a/>! canceled-chan ::request-canceled)
@@ -195,11 +194,11 @@
           (start-async-cancel-loop! request finished-chan canceled-chan)
           (do-f-async async-context f delay-os finished-chan canceled-chan)))
       (catch Throwable e
-        (log/error e (trs "Unexpected exception in do-f-async"))
+        (log/error e "Unexpected exception in do-f-async")
         (try
           (.sendError response 500 (.getMessage e))
           (catch Throwable e
-            (log/error e (trs "Unexpected exception writing error response"))))
+            (log/error e "Unexpected exception writing error response")))
         (a/>!! finished-chan :unexpected-error)
         (a/close! finished-chan)
         (a/close! canceled-chan)
diff --git a/src/metabase/automagic_dashboards/populate.clj b/src/metabase/automagic_dashboards/populate.clj
index b8770bc7ef86dd1fb077d49cd846e9aa32f21451..5df8872fbedb2fb142bc579bc9179a2aea504eb3 100644
--- a/src/metabase/automagic_dashboards/populate.clj
+++ b/src/metabase/automagic_dashboards/populate.clj
@@ -10,7 +10,6 @@
    [metabase.models.collection :as collection]
    [metabase.public-settings :as public-settings]
    [metabase.query-processor.util :as qp.util]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]))
 
@@ -323,10 +322,10 @@
                                      ;; Height doesn't need to be precise, just some
                                      ;; safe upper bound.
                                      (make-grid grid-width (* n grid-width))]))]
-     (log/debug (trs "Adding {0} cards to dashboard {1}:\n{2}"
-                     (count cards)
-                     title
-                     (str/join "; " (map :title cards))))
+     (log/debugf "Adding %s cards to dashboard %s:\n%s"
+                 (count cards)
+                 title
+                 (str/join "; " (map :title cards)))
      (cond-> (update dashboard :dashcards (partial sort-by (juxt :row :col)))
        (not-empty filters) (filters/add-filters filters max-filters)))))
 
diff --git a/src/metabase/automagic_dashboards/util.clj b/src/metabase/automagic_dashboards/util.clj
index 53a672091a09ba813ba62319f1bc073af646425e..483446edadbeb84c3f6f959e3c444cc4947cc9bc 100644
--- a/src/metabase/automagic_dashboards/util.clj
+++ b/src/metabase/automagic_dashboards/util.clj
@@ -12,7 +12,6 @@
    [metabase.models.interface :as mi]
    [metabase.sync.analyze.classify :as classify]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -83,7 +82,7 @@
      ;; handle field string names. Only if we have result metadata. (Not sure why)
      (when (string? id-or-name)
        (when-not result-metadata
-         (log/warn (trs "Warning: Automagic analysis context is missing result metadata. Unable to resolve Fields by name.")))
+         (log/warn "Warning: Automagic analysis context is missing result metadata. Unable to resolve Fields by name."))
        (when-let [field (m/find-first #(= (:name %) id-or-name)
                                       result-metadata)]
          (as-> field field
@@ -92,6 +91,4 @@
            (mi/instance Field field)
            (classify/run-classifiers field {}))))
      ;; otherwise this isn't returning something, and that's probably an error. Log it.
-     (log/warn (str (trs "Cannot resolve Field {0} in automagic analysis context" field-id-or-name-or-clause)
-                    \newline
-                    (u/pprint-to-str root))))))
+     (log/warnf "Cannot resolve Field %s in automagic analysis context\n%s" field-id-or-name-or-clause (u/pprint-to-str root)))))
diff --git a/src/metabase/cmd.clj b/src/metabase/cmd.clj
index c91ca1008fe607568336d3f98ce0a5acf3ea1948..d97c8eeaf4bbe8bfcc1e41647dc457c01fcce865 100644
--- a/src/metabase/cmd.clj
+++ b/src/metabase/cmd.clj
@@ -182,7 +182,7 @@
                :parse-fn     mbql.u/normalize-token
                :validate     [#{:continue :abort} "Must be 'continue' or 'abort'"]]]}
   [path & options]
-  (log/warn (u/colorize :red (trs "''load'' is deprecated and will be removed in a future release. Please migrate to ''import''.")))
+  (log/warn (u/colorize :red "'load' is deprecated and will be removed in a future release. Please migrate to 'import'."))
   (call-enterprise 'metabase-enterprise.serialization.cmd/v1-load! path (get-parsed-options #'load options)))
 
 (defn ^:command import
@@ -201,7 +201,7 @@
                :validate     [#{:active :all} "Must be 'active' or 'all'"]]
               [nil "--include-entity-id"   "Include entity_id property in all dumped entities. Default: false."]]}
   [path & options]
-  (log/warn (u/colorize :red (trs "''dump'' is deprecated and will be removed in a future release. Please migrate to ''export''.")))
+  (log/warn (u/colorize :red "'dump' is deprecated and will be removed in a future release. Please migrate to 'export'."))
   (call-enterprise 'metabase-enterprise.serialization.cmd/v1-dump! path (get-parsed-options #'dump options)))
 
 (defn ^:command export
diff --git a/src/metabase/cmd/copy.clj b/src/metabase/cmd/copy.clj
index 19acc2a5c83bf8a557d8a486fe528a901b5853ae..9ffbfe76c69c7bde6270edc609d0afe974ce70f8 100644
--- a/src/metabase/cmd/copy.clj
+++ b/src/metabase/cmd/copy.clj
@@ -180,11 +180,11 @@
        (fn
          ([cnt]
           (when (pos? cnt)
-            (log/info (str " " (u/colorize 'green (trs "copied {0} instances." cnt))))))
+            (log/info (str " " (u/format-color :green "copied %s instances." cnt)))))
          ([cnt chunkk]
           (when (seq chunkk)
             (when (zero? cnt)
-              (log/info (u/colorize 'blue (trs "Copying instances of {0}..." (name model)))))
+              (log/info (u/format-color :blue "Copying instances of %s..." (name model))))
             (try
               (insert-chunk! target-db-type target-db-conn-spec table-name chunkk)
               (catch Throwable e
diff --git a/src/metabase/cmd/copy/h2.clj b/src/metabase/cmd/copy/h2.clj
index 994ff14dd9b6615bea39ba0cf0e21844051b128f..e2eea7f4a23bd4d0dd2e6a46752b14104480e77f 100644
--- a/src/metabase/cmd/copy/h2.clj
+++ b/src/metabase/cmd/copy/h2.clj
@@ -5,7 +5,6 @@
    [clojure.string :as str]
    [metabase.db.data-source :as mdb.data-source]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (set! *warn-on-reflection* true)
@@ -35,4 +34,4 @@
                     (str h2-filename ".mv.db")]]
     (when (.exists (io/file filename))
       (io/delete-file filename)
-      (log/warn (u/format-color 'red (trs "Output H2 database already exists: %s, removing.") filename)))))
+      (log/warn (u/format-color :red "Output H2 database already exists: %s, removing." filename)))))
diff --git a/src/metabase/cmd/rotate_encryption_key.clj b/src/metabase/cmd/rotate_encryption_key.clj
index 13ccc6ddf52dd8e532a517d6f9f130fd93e93855..c8c1b489a6ca37e78c7be4983ede5efc1aaf7461 100644
--- a/src/metabase/cmd/rotate_encryption_key.clj
+++ b/src/metabase/cmd/rotate_encryption_key.clj
@@ -15,7 +15,7 @@
   (when-not (mdb/db-is-set-up?)
     (log/warnf "Database not found. Metabase will create a new database at %s and proceeed encrypting." "2")
     (mdb/setup-db!))
-  (log/infof "%s: %s | %s" (trs "Connected to") (mdb/db-type) (mdb/db-file))
+  (log/infof "Connected to: %s | %s" (mdb/db-type) (mdb/db-file))
   (let [make-encrypt-fn  (fn [maybe-encrypt-fn]
                            (if to-key
                              (partial maybe-encrypt-fn (encryption/validate-and-hash-secret-key to-key))
diff --git a/src/metabase/core.clj b/src/metabase/core.clj
index f26846ffb4c4590e9e7fa2327bbdd7fddd953648..9fb524da14bbf56d6f42bc00afcdd98c59d5c816 100644
--- a/src/metabase/core.clj
+++ b/src/metabase/core.clj
@@ -27,7 +27,6 @@
    [metabase.task :as task]
    [metabase.troubleshooting :as troubleshooting]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [deferred-trs trs]]
    [metabase.util.log :as log])
   (:import
    (java.lang.management ManagementFactory)))
@@ -45,17 +44,14 @@
 ;; don't i18n this, it's legalese
 (log/info
  (format "\nMetabase %s" config/mb-version-string)
-
  (format "\n\nCopyright © %d Metabase, Inc." (.getYear (java.time.LocalDate/now)))
-
  (str "\n\n"
       (if config/ee-available?
-        (str (deferred-trs "Metabase Enterprise Edition extensions are PRESENT.")
+        (str "Metabase Enterprise Edition extensions are PRESENT."
              "\n\n"
-             (deferred-trs "Usage of Metabase Enterprise Edition features are subject to the Metabase Commercial License.")
-             " "
-             (deferred-trs "See {0} for details." "https://www.metabase.com/license/commercial/"))
-        (deferred-trs "Metabase Enterprise Edition extensions are NOT PRESENT."))))
+             "Usage of Metabase Enterprise Edition features are subject to the Metabase Commercial License."
+             "See https://www.metabase.com/license/commercial/ for details.")
+        "Metabase Enterprise Edition extensions are NOT PRESENT.")))
 
 ;;; --------------------------------------------------- Lifecycle ----------------------------------------------------
 
@@ -70,7 +66,7 @@
                            (when-not (= 80 port) (str ":" port))))
         setup-url (str site-url "/setup/")]
     (log/info (u/format-color 'green
-                              (str (deferred-trs "Please use the following URL to setup your Metabase installation:")
+                              (str "Please use the following URL to setup your Metabase installation:"
                                    "\n\n"
                                    setup-url
                                    "\n\n")))))
@@ -84,11 +80,11 @@
 (defn- destroy!
   "General application shutdown function which should be called once at application shutdown."
   []
-  (log/info (trs "Metabase Shutting Down ..."))
+  (log/info "Metabase Shutting Down ...")
   (task/stop-scheduler!)
   (server/stop-web-server!)
   (prometheus/shutdown!)
-  (log/info (trs "Metabase Shutdown COMPLETE")))
+  (log/info "Metabase Shutdown COMPLETE"))
 
 (defenterprise ensure-audit-db-installed!
   "OSS implementation of `audit-db/ensure-db-installed!`, which is an enterprise feature, so does nothing in the OSS
@@ -98,8 +94,8 @@
 (defn- init!*
   "General application initialization function which should be run once at application startup."
   []
-  (log/info (trs "Starting Metabase version {0} ..." config/mb-version-string))
-  (log/info (trs "System info:\n {0}" (u/pprint-to-str (troubleshooting/system-info))))
+  (log/infof "Starting Metabase version %s ..." config/mb-version-string)
+  (log/infof "System info:\n %s" (u/pprint-to-str (troubleshooting/system-info)))
   (init-status/set-progress! 0.1)
   ;; First of all, lets register a shutdown hook that will tidy things up for us on app exit
   (.addShutdownHook (Runtime/getRuntime) (Thread. ^Runnable destroy!))
@@ -109,12 +105,12 @@
   (init-status/set-progress! 0.3)
   (settings/validate-settings-formatting!)
   ;; startup database.  validates connection & runs any necessary migrations
-  (log/info (trs "Setting up and migrating Metabase DB. Please sit tight, this may take a minute..."))
+  (log/info "Setting up and migrating Metabase DB. Please sit tight, this may take a minute...")
   (mdb/setup-db!)
   (init-status/set-progress! 0.5)
   ;; Set up Prometheus
   (when (prometheus/prometheus-server-port)
-    (log/info (trs "Setting up prometheus metrics"))
+    (log/info "Setting up prometheus metrics")
     (prometheus/setup!)
     (init-status/set-progress! 0.6))
 
@@ -127,7 +123,7 @@
     (config-from-file/init-from-file-if-code-available!)
     (init-status/set-progress! 0.7)
     (when new-install?
-      (log/info (trs "Looks like this is a new installation ... preparing setup wizard"))
+      (log/info "Looks like this is a new installation ... preparing setup wizard")
       ;; create setup token
       (create-setup-token-and-log-setup-url!)
       ;; publish install event
@@ -149,7 +145,7 @@
   (init-status/set-complete!)
   (let [start-time (.getStartTime (ManagementFactory/getRuntimeMXBean))
         duration   (- (System/currentTimeMillis) start-time)]
-    (log/info (trs "Metabase Initialization COMPLETE in {0}" (u/format-milliseconds duration)))))
+    (log/infof "Metabase Initialization COMPLETE in %s" (u/format-milliseconds duration))))
 
 (defn init!
   "General application initialization function which should be run once at application startup. Calls `[[init!*]] and
@@ -163,7 +159,7 @@
 ;;; -------------------------------------------------- Normal Start --------------------------------------------------
 
 (defn- start-normally []
-  (log/info (trs "Starting Metabase in STANDALONE mode"))
+  (log/info "Starting Metabase in STANDALONE mode")
   (try
     ;; launch embedded webserver async
     (server/start-web-server! handler/app)
@@ -173,7 +169,7 @@
     (when (config/config-bool :mb-jetty-join)
       (.join (server/instance)))
     (catch Throwable e
-      (log/error e (trs "Metabase Initialization FAILED"))
+      (log/error e "Metabase Initialization FAILED")
       (System/exit 1))))
 
 (defn- run-cmd [cmd args]
@@ -186,7 +182,7 @@
   []
   (let [mb-trace-str (config/config-str :mb-ns-trace)]
     (when (not-empty mb-trace-str)
-      (log/warn (trs "WARNING: You have enabled namespace tracing, which could log sensitive information like db passwords."))
+      (log/warn "WARNING: You have enabled namespace tracing, which could log sensitive information like db passwords.")
       (doseq [namespace (map symbol (str/split mb-trace-str #",\s*"))]
         (try (require namespace)
              (catch Throwable _
diff --git a/src/metabase/db/liquibase.clj b/src/metabase/db/liquibase.clj
index 5bc2df394b6440c3165f74aee1f99e872311dff4..54061c325ddedffd6883cd52c2434d88696cafce 100644
--- a/src/metabase/db/liquibase.clj
+++ b/src/metabase/db/liquibase.clj
@@ -198,7 +198,7 @@
     (try
       (force-release-locks! liquibase)
       (catch Exception e
-        (log/error e (trs "Unable to release the Liquibase lock after a migration failure"))))))
+        (log/error e "Unable to release the Liquibase lock after a migration failure")))))
 
 (defn- lock-service ^LockService [^Liquibase liquibase]
   (.getLockService (LockServiceFactory/getInstance) (.getDatabase liquibase)))
@@ -278,10 +278,10 @@
 (defn migrate-up-if-needed!
   "Run any unrun `liquibase` migrations, if needed."
   [^Liquibase liquibase ^DataSource data-source]
-  (log/info (trs "Checking if Database has unrun migrations..."))
+  (log/info "Checking if Database has unrun migrations...")
   (if (seq (unrun-migrations data-source))
     (do
-     (log/info (trs "Database has unrun migrations. Checking if migration lock is taken..."))
+     (log/info "Database has unrun migrations. Checking if migration lock is taken...")
      (with-scope-locked liquibase
       ;; while we were waiting for the lock, it was possible that another instance finished the migration(s), so make
       ;; sure something still needs to be done...
@@ -290,14 +290,13 @@
         (if (pos? unrun-migrations-count)
           (let [^Contexts contexts nil
                 start-time         (System/currentTimeMillis)]
-            (log/info (trs "Running {0} migrations ..." unrun-migrations-count))
+            (log/infof "Running %s migrations ..." unrun-migrations-count)
             (doseq [^ChangeSet change to-run-migrations]
               (log/tracef "To run migration %s" (.getId change)))
             (.update liquibase contexts)
-            (log/info (trs "Migration complete in {0}" (u/format-milliseconds (- (System/currentTimeMillis) start-time)))))
-          (log/info
-           (trs "Migration lock cleared, but nothing to do here! Migrations were finished by another instance."))))))
-    (log/info (trs "No unrun migrations found."))))
+            (log/infof "Migration complete in %s" (u/format-milliseconds (- (System/currentTimeMillis) start-time))))
+          (log/info "Migration lock cleared, but nothing to do here! Migrations were finished by another instance.")))))
+    (log/info "No unrun migrations found.")))
 
 (defn update-with-change-log
   "Run update with the change log instances in `liquibase`. Must be called within a scope holding the liquibase lock."
@@ -340,7 +339,7 @@
             exec-listener  (proxy [AbstractChangeExecListener] []
                              (willRun [^ChangeSet change-set _database-change-log _database _run-status]
                                (when (instance? ChangeSet change-set)
-                                 (log/info (format "Start executing migration with id %s" (.getId change-set)))))
+                                 (log/infof "Start executing migration with id %s" (.getId change-set))))
 
                              (runFailed [^ChangeSet _change-set _database-change-log _database ^Exception e]
                                (log/error (u/format-color 'red "[ERROR] %s" (.getMessage e))))
@@ -354,7 +353,7 @@
                                    ChangeSet$ExecType/FAILED
                                    (log/error (u/format-color 'red "[ERROR]"))
 
-                                   (log/info (format "[%s]" (.name exec-type)))))))]
+                                   (log/infof "[%s]" (.name exec-type))))))]
         (try
           (doseq [^ChangeSet change-set (.getChangeSets change-log)]
             (.setFailOnError change-set false))
diff --git a/src/metabase/db/setup.clj b/src/metabase/db/setup.clj
index 9acd4e2cf3692d291458b44fd560f9c655145497..315ebd491abc5e7763e86699efe2c1550380bfa7 100644
--- a/src/metabase/db/setup.clj
+++ b/src/metabase/db/setup.clj
@@ -40,15 +40,15 @@
   short circuit the setup process and make it clear we can't proceed."
   [liquibase data-source]
   (when (seq (liquibase/unrun-migrations data-source))
-    (log/info (str (trs "Database Upgrade Required")
+    (log/info (str "Database Upgrade Required"
                    "\n\n"
-                   (trs "NOTICE: Your database requires updates to work with this version of Metabase.")
+                   "NOTICE: Your database requires updates to work with this version of Metabase."
                    "\n"
-                   (trs "Please execute the following sql commands on your database before proceeding.")
+                   "Please execute the following sql commands on your database before proceeding."
                    "\n\n"
                    (liquibase/migrations-sql liquibase)
                    "\n\n"
-                   (trs "Once your database is updated try running the application again.")
+                   "Once your database is updated try running the application again."
                    "\n"))
     (throw (Exception. (trs "Database requires manual upgrade.")))))
 
@@ -70,7 +70,7 @@
   (with-open [conn (.getConnection ^javax.sql.DataSource data-source)]
     (.setAutoCommit conn false)
     ;; Set up liquibase and let it do its thing
-    (log/info (trs "Setting up Liquibase..."))
+    (log/info "Setting up Liquibase...")
     (liquibase/with-liquibase [liquibase conn]
       (try
         ;; Consolidating the changeset requires the lock, so we may need to release it first.
@@ -80,7 +80,7 @@
        (when-not (= :release-locks direction)
          (liquibase/consolidate-liquibase-changesets! conn liquibase))
 
-       (log/info (trs "Liquibase is ready."))
+       (log/info "Liquibase is ready.")
        (case direction
          :up            (liquibase/migrate-up-if-needed! liquibase data-source)
          :force         (liquibase/force-migrate-up-if-needed! liquibase data-source)
@@ -110,7 +110,7 @@
   connecting."
   [db-type     :- :keyword
    data-source :- (ms/InstanceOfClass javax.sql.DataSource)]
-  (log/info (u/format-color 'cyan (trs "Verifying {0} Database Connection ..." (name db-type))))
+  (log/info (u/format-color 'cyan "Verifying %s Database Connection ..." (name db-type)))
   (classloader/require 'metabase.driver.sql-jdbc.connection)
   (let [error-msg (trs "Unable to connect to Metabase {0} DB." (name db-type))]
     (try (assert ((requiring-resolve 'metabase.driver.sql-jdbc.connection/can-connect-with-spec?) {:datasource data-source}) error-msg)
@@ -118,13 +118,12 @@
            (throw (ex-info error-msg {} e)))))
   (with-open [conn (.getConnection ^javax.sql.DataSource data-source)]
     (let [metadata (.getMetaData conn)]
-      (log/info (trs "Successfully verified {0} {1} application database connection."
-                     (.getDatabaseProductName metadata) (.getDatabaseProductVersion metadata))
-                (u/emoji "✅")))))
+      (log/infof "Successfully verified %s %s application database connection. %s"
+                 (.getDatabaseProductName metadata) (.getDatabaseProductVersion metadata) (u/emoji "✅")))))
 
 (mu/defn ^:private error-if-downgrade-required!
   [data-source :- (ms/InstanceOfClass javax.sql.DataSource)]
-  (log/info (u/format-color 'cyan (trs "Checking if a database downgrade is required...")))
+  (log/info (u/format-color 'cyan "Checking if a database downgrade is required..."))
   (with-open [conn (.getConnection ^javax.sql.DataSource data-source)]
     (liquibase/with-liquibase [liquibase conn]
       (let [latest-available (liquibase/latest-available-major-version liquibase)
@@ -148,9 +147,9 @@
   [db-type       :- :keyword
    data-source   :- (ms/InstanceOfClass javax.sql.DataSource)
    auto-migrate? :- [:maybe :boolean]]
-  (log/info (trs "Running Database Migrations..."))
+  (log/info "Running Database Migrations...")
   (migrate! db-type data-source (if auto-migrate? :up :print))
-  (log/info (trs "Database Migrations Current ... ") (u/emoji "✅")))
+  (log/info "Database Migrations Current ..." (u/emoji "✅")))
 
 ;; TODO -- consider renaming to something like `verify-connection-and-migrate!`
 ;;
diff --git a/src/metabase/db/update_h2.clj b/src/metabase/db/update_h2.clj
index 5ee5c8e5f58283e4a80b672df99c379d53537178..5dada64084c2785b76e1b199827148f772be971b 100644
--- a/src/metabase/db/update_h2.clj
+++ b/src/metabase/db/update_h2.clj
@@ -103,5 +103,5 @@
         (try
          (update! jdbc-url)
          (catch Exception e
-           (log/error "Failed to update H2 database:" e)
+           (log/error e "Failed to update H2 database:")
            (throw e)))))))
diff --git a/src/metabase/driver.clj b/src/metabase/driver.clj
index 0ff65be7d1f5b3a3255a9ba3937f18229b4ddc38..fcd3544db2c321d2a2adc922ee15870c6a5786bc 100644
--- a/src/metabase/driver.clj
+++ b/src/metabase/driver.clj
@@ -14,7 +14,7 @@
    [metabase.models.setting :as setting :refer [defsetting]]
    [metabase.plugins.classloader :as classloader]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [potemkin :as p]
    [toucan2.core :as t2]))
@@ -35,7 +35,7 @@
     (try
       (notify-database-updated driver database)
       (catch Throwable e
-        (log/error e (trs "Failed to notify {0} Database {1} updated" driver id))))))
+        (log/errorf e "Failed to notify %s Database %s updated" driver id)))))
 
 (defn- short-timezone-name [timezone-id]
   (let [^java.time.ZoneId zone (if (seq timezone-id)
diff --git a/src/metabase/driver/common.clj b/src/metabase/driver/common.clj
index 92ae93aacfb330d797d463a3b08bb2d5633568f4..03a0f53b1a00c1bfae4a62d54e55dac6f4e039fd 100644
--- a/src/metabase/driver/common.clj
+++ b/src/metabase/driver/common.clj
@@ -5,7 +5,7 @@
    [metabase.driver :as driver]
    [metabase.models.setting :as setting]
    [metabase.public-settings :as public-settings]
-   [metabase.util.i18n :refer [deferred-tru trs]]
+   [metabase.util.i18n :refer [deferred-tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu])
   (:import
@@ -271,7 +271,7 @@
     ;; all-NULL columns in DBs like Mongo w/o explicit types
     nil                            :type/*
     (do
-      (log/warn (trs "Don''t know how to map class ''{0}'' to a Field base_type, falling back to :type/*." klass))
+      (log/warnf "Don't know how to map class '%s' to a Field base_type, falling back to :type/*." klass)
       :type/*)))
 
 (def ^:private column-info-sample-size
diff --git a/src/metabase/driver/h2.clj b/src/metabase/driver/h2.clj
index 6a03cf100a2ce839116296769a38d91ba32a2602..ce2bd4d4c0ee95153909b20befb5e7bb584f1760 100644
--- a/src/metabase/driver/h2.clj
+++ b/src/metabase/driver/h2.clj
@@ -557,7 +557,7 @@
       (let [details (ssh/include-ssh-tunnel! db-details)
             db      (:db details)]
         (assoc details :db (str/replace-first db (str (:orig-port details)) (str (:tunnel-entrance-port details)))))
-      (do (log/error (tru "SSH tunnel can only be established for H2 connections using the TCP protocol"))
+      (do (log/error "SSH tunnel can only be established for H2 connections using the TCP protocol")
           db-details))
     db-details))
 
diff --git a/src/metabase/driver/impl.clj b/src/metabase/driver/impl.clj
index 90d9e6546e52eff8c4425e771cbb85ca6e2c0002..da1337dec5a39dcb76c359df2688359c1e42ada9 100644
--- a/src/metabase/driver/impl.clj
+++ b/src/metabase/driver/impl.clj
@@ -73,12 +73,11 @@
   "`require` a driver's 'expected' namespace."
   [driver & require-options]
   (let [expected-ns (driver->expected-namespace driver)]
-    (log/debug
-     (trs "Loading driver {0} {1}" (u/format-color 'blue driver) (apply list 'require expected-ns require-options)))
+    (log/debugf "Loading driver %s %s" (u/format-color 'blue driver) (apply list 'require expected-ns require-options))
     (try
       (apply classloader/require expected-ns require-options)
       (catch Throwable e
-        (log/error e (tru "Error loading driver namespace"))
+        (log/error e "Error loading driver namespace")
         (throw (Exception. (tru "Could not load {0} driver." driver) e))))))
 
 (defn load-driver-namespace-if-needed!
@@ -153,7 +152,7 @@
         (doseq [parent parents
                 :when  (concrete? parent)]
           (throw (ex-info (trs "Abstract drivers cannot derive from concrete parent drivers.")
-                   {:driver driver, :parent parent}))))
+                          {:driver driver, :parent parent}))))
       ;; validate that the registration isn't stomping on things
       (check-abstractness-hasnt-changed driver abstract?)
       ;; ok, if that was successful we can derive the driver from `:metabase.driver/driver`/`::concrete` and parent(s)
@@ -166,11 +165,12 @@
       ;; ok, log our great success
       (log/info
        (u/format-color 'blue
-           (if (metabase.driver.impl/abstract? driver)
-             (trs "Registered abstract driver {0}" driver)
-             (trs "Registered driver {0}" driver)))
+                       (format (if (metabase.driver.impl/abstract? driver)
+                                 "Registered abstract driver %s"
+                                 "Registered driver %s")
+                               driver))
        (if (seq parents)
-         (trs "(parents: {0})" (vec parents))
+         (format "(parents: %s)" (vec parents))
          "")
        (u/emoji "🚚")))))
 
@@ -208,8 +208,8 @@
         ;; and once we acquire the lock, check one more time to make sure the driver didn't get initialized by
         ;; whatever thread(s) we were waiting on.
         (when-not (initialized? driver)
-          (log/info (u/format-color 'yellow (trs "Initializing driver {0}..." driver)))
-          (log/debug (trs "Reason:") (u/pprint-to-str 'blue (drop 5 (u/filtered-stacktrace (Thread/currentThread)))))
+          (log/info (u/format-color :yellow "Initializing driver %s..." driver))
+          (log/debug "Reason:" (u/pprint-to-str :blue (drop 5 (u/filtered-stacktrace (Thread/currentThread)))))
           (init-fn driver)
           (swap! initialized-drivers conj driver))))))
 
diff --git a/src/metabase/driver/mysql.clj b/src/metabase/driver/mysql.clj
index 10b9487e1982bd55c772198faa53b4964efa7236..65c9654ebae82b6313009f500d1140638c844c49 100644
--- a/src/metabase/driver/mysql.clj
+++ b/src/metabase/driver/mysql.clj
@@ -31,7 +31,7 @@
    [metabase.upload :as upload]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [deferred-tru trs]]
+   [metabase.util.i18n :refer [deferred-tru]]
    [metabase.util.log :as log])
   (:import
    (java.io File)
@@ -121,15 +121,15 @@
      (fn [^java.sql.Connection conn]
        (when (unsupported-version? (.getMetaData conn))
          (log/warn
-          (u/format-color 'red
-                          (str
-                           "\n\n********************************************************************************\n"
-                           (trs "WARNING: Metabase only officially supports MySQL {0}/MariaDB {1} and above."
+          (u/format-color :red
+                          (str "\n\n********************************************************************************\n"
+                               (format
+                                "WARNING: Metabase only officially supports MySQL %s/MariaDB %s and above."
                                 min-supported-mysql-version
                                 min-supported-mariadb-version)
-                           "\n"
-                           (trs "All Metabase features may not work properly when using an unsupported version.")
-                           "\n********************************************************************************\n"))))))))
+                               "\n"
+                               "All Metabase features may not work properly when using an unsupported version."
+                               "\n********************************************************************************\n"))))))))
 
 (defmethod driver/can-connect? :mysql
   [driver details]
@@ -543,7 +543,7 @@
         ssl?          (or ssl? (= "true" (get addl-opts-map "useSSL")))
         ssl-cert?     (and ssl? (some? ssl-cert))]
     (when (and ssl? (not (contains? addl-opts-map "trustServerCertificate")))
-      (log/info (trs "You may need to add 'trustServerCertificate=true' to the additional connection options to connect with SSL.")))
+      (log/info "You may need to add 'trustServerCertificate=true' to the additional connection options to connect with SSL."))
     (merge
      default-connection-args
      ;; newer versions of MySQL will complain if you don't specify this when not using SSL
diff --git a/src/metabase/driver/mysql/actions.clj b/src/metabase/driver/mysql/actions.clj
index 5d5a517978a90a1024f2e246b4617247839445bd..66319a00dfc15c3c3851a8bd45f3e042c8529484 100644
--- a/src/metabase/driver/mysql/actions.clj
+++ b/src/metabase/driver/mysql/actions.clj
@@ -42,7 +42,7 @@
         (if (and (or (nil? catalog) (= table_catalog catalog))
                  (or (nil? schema) (= table_schema schema)))
           [(conj columns column_name) table_catalog table_schema]
-          (do (log/warnf "Ambiguous catalog/schema for constraint %s in table %s"
+          (do (log/warnf "Ambiguous catalog/schema for constraint %s in table"
                          constraint-name)
               (reduced nil))))
       [[] nil nil]
diff --git a/src/metabase/driver/mysql/ddl.clj b/src/metabase/driver/mysql/ddl.clj
index 65828a4b8ccba4f8538ae3e9714b36ea1cf84349..598903090761bdfacdc8c65fa2dcb05587865c54 100644
--- a/src/metabase/driver/mysql/ddl.clj
+++ b/src/metabase/driver/mysql/ddl.clj
@@ -158,18 +158,16 @@
        (loop [[[step stepfn undofn] & remaining] steps
               undo-steps []]
          (let [result (try (stepfn conn)
-                           (log/info (trs "Step {0} was successful for db {1}"
-                                          step (:name database)))
+                           (log/infof "Step %s was successful for db %s" step (:name database))
                            ::valid
                            (catch Exception e
-                             (log/warn (trs "Error in `{0}` while checking for model persistence permissions." step))
-                             (log/warn e)
+                             (log/warnf e "Error in `%s` while checking for model persistence permissions." step)
                              (try
                                (doseq [[undo-step undofn] (reverse undo-steps)]
-                                 (log/warn (trs "Undoing step `{0}` for db {1}" undo-step (:name database)))
+                                 (log/warnf "Undoing step `%s` for db %s" undo-step (:name database))
                                  (undofn conn))
                                (catch Exception _e
-                                 (log/warn (trs "Unable to rollback database check for model persistence"))))
+                                 (log/warn "Unable to rollback database check for model persistence")))
                              step))]
            (cond (and (= result ::valid) remaining)
                  (recur remaining (conj undo-steps [step undofn]))
diff --git a/src/metabase/driver/postgres/ddl.clj b/src/metabase/driver/postgres/ddl.clj
index cefb999ce5a892f3076282872465b3194b22e056..95acfa08c98b0b58c2bf7822b1ee04ba5055db13 100644
--- a/src/metabase/driver/postgres/ddl.clj
+++ b/src/metabase/driver/postgres/ddl.clj
@@ -8,7 +8,6 @@
    [metabase.driver.sql.ddl :as sql.ddl]
    [metabase.public-settings :as public-settings]
    [metabase.query-processor.compile :as qp.compile]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (set! *warn-on-reflection* true)
@@ -112,12 +111,10 @@
          (set-statement-timeout! tx)
          (loop [[[step stepfn] & remaining] steps]
            (let [result (try (stepfn tx)
-                             (log/info (trs "Step {0} was successful for db {1}"
-                                            step (:name database)))
+                             (log/infof "Step %s was successful for db %s" step (:name database))
                              ::valid
                              (catch Exception e
-                               (log/warn (trs "Error in `{0}` while checking for model persistence permissions." step))
-                               (log/warn e)
+                               (log/warnf e "Error in `%s` while checking for model persistence permissions." step)
                                step))]
              (cond (and (= result ::valid) remaining)
                    (recur remaining)
diff --git a/src/metabase/driver/sql/query_processor.clj b/src/metabase/driver/sql/query_processor.clj
index 627548d3010123323666c7853a7c51b5edf92421..4e7caf061ed6153c8c5a97d1c11f5ab4a98fef4b 100644
--- a/src/metabase/driver/sql/query_processor.clj
+++ b/src/metabase/driver/sql/query_processor.clj
@@ -21,7 +21,7 @@
    [metabase.query-processor.util.nest-query :as nest-query]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [deferred-tru tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
@@ -1348,11 +1348,9 @@
      (format-honeysql-2 dialect honeysql-form)
      (catch Throwable e
        (try
-         (log/error e
-                    (u/format-color 'red
-                                    (str (deferred-tru "Invalid HoneySQL form: {0}" (ex-message e))
-                                         "\n"
-                                         (u/pprint-to-str honeysql-form))))
+         (log/error e (u/format-color :red
+                                      "Invalid HoneySQL form: %s\n%s"
+                                      (ex-message e) (u/pprint-to-str honeysql-form)))
          (finally
            (throw (ex-info (tru "Error compiling HoneySQL form: {0}" (ex-message e))
                            {:dialect dialect
diff --git a/src/metabase/driver/sql/query_processor/deprecated.clj b/src/metabase/driver/sql/query_processor/deprecated.clj
index 70ee663004e74b3706bf1fc9c753bf836584deac..dc780999ce88a2fd5b25255790f51f6c2228386a 100644
--- a/src/metabase/driver/sql/query_processor/deprecated.clj
+++ b/src/metabase/driver/sql/query_processor/deprecated.clj
@@ -8,7 +8,6 @@
   (:require
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 ;;; This is unused at this moment in time but we can leave it around in case we want to use it again in the
@@ -21,10 +20,10 @@
     (log-deprecation-warning driver 'my.namespace/method \"v0.42.0\")"
   [driver method-name deprecated-version]
   (letfn [(thunk []
-            (log/warn
-             (u/colorize 'red
-                         (trs "Warning: Driver {0} is using {1}. This method was deprecated in {2} and will be removed in a future release."
-                              driver method-name deprecated-version))))]
+            (log/warn (u/format-color :red
+                                      (str "Warning: Driver %s is using %s. This method was deprecated in %s and will"
+                                           " be removed in a future release.")
+                                      driver method-name deprecated-version)))]
     ;; only log each individual message once for the current QP store; by 'caching' the value with the key it is
     ;; effectively memoized for the rest of the QP run for the current query. The goal here is to avoid blasting the
     ;; logs with warnings about deprecated method calls, but still remind people regularly enough that it gets fixed
diff --git a/src/metabase/driver/sql/util/unprepare.clj b/src/metabase/driver/sql/util/unprepare.clj
index cf1de78eb5dc568cd5ecdab1237f3f61a7ccc695..061d50b39917617dc621b75d4e21af44594e09f1 100644
--- a/src/metabase/driver/sql/util/unprepare.clj
+++ b/src/metabase/driver/sql/util/unprepare.clj
@@ -10,7 +10,6 @@
    [metabase.driver :as driver]
    [metabase.driver.sql.util :as sql.u]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (java.time Instant LocalDate LocalDateTime LocalTime OffsetDateTime OffsetTime ZonedDateTime)))
@@ -29,7 +28,7 @@
   [_ value]
   ;; it's better return a slightly broken SQL query with a probably incorrect string representation of the value than
   ;; to have the entire QP run fail because of an unknown type.
-  (log/warn (trs "Don''t know how to unprepare values of class {0}" (.getName (class value))))
+  (log/warnf "Don't know how to unprepare values of class %s" (.getName (class value)))
   (str value))
 
 (defmethod unprepare-value [:sql nil]
diff --git a/src/metabase/driver/sql_jdbc/actions.clj b/src/metabase/driver/sql_jdbc/actions.clj
index 652571c982948e882fb86fe7100ac7205c0e183d..f5c91df8614219945f226756679853ad7f533d4f 100644
--- a/src/metabase/driver/sql_jdbc/actions.clj
+++ b/src/metabase/driver/sql_jdbc/actions.clj
@@ -19,7 +19,7 @@
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.registry :as mr])
@@ -62,7 +62,7 @@
      ;; Catch errors in parse-sql-error and log them so more errors in the future don't break the entire action.
      ;; We'll still get the original unparsed error message.
      (catch Throwable new-e
-       (log/error new-e (trs "Error parsing SQL error message {0}: {1}" (pr-str (ex-message e)) (ex-message new-e)))
+       (log/errorf new-e "Error parsing SQL error message %s: %s" (pr-str (ex-message e)) (ex-message new-e))
        nil))))
 
 (defn- do-with-auto-parse-sql-error
diff --git a/src/metabase/driver/sql_jdbc/connection.clj b/src/metabase/driver/sql_jdbc/connection.clj
index 6337dde4f9007eba70b5a33c1ac190564fe9bb14..1ac2e25791ba2c48498339f1dcd04369881c301c 100644
--- a/src/metabase/driver/sql_jdbc/connection.clj
+++ b/src/metabase/driver/sql_jdbc/connection.clj
@@ -13,7 +13,7 @@
    [metabase.query-processor.pipeline :as qp.pipeline]
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.ssh :as ssh]
@@ -161,7 +161,7 @@
   "Create a new C3P0 `ComboPooledDataSource` for connecting to the given `database`."
   [{:keys [id details], driver :engine, :as database}]
   {:pre [(map? database)]}
-  (log/debug (u/format-color 'cyan (trs "Creating new connection pool for {0} database {1} ..." driver id)))
+  (log/debug (u/format-color :cyan "Creating new connection pool for %s database %s ..." driver id))
   (let [details-with-tunnel (driver/incorporate-ssh-tunnel-details  ;; If the tunnel is disabled this returned unchanged
                              driver
                              (update details :port #(or % (default-ssh-tunnel-target-port driver))))
@@ -173,7 +173,7 @@
       (select-keys spec [:tunnel-enabled :tunnel-session :tunnel-tracker :tunnel-entrance-port :tunnel-entrance-host]))))
 
 (defn- destroy-pool! [database-id pool-spec]
-  (log/debug (u/format-color 'red (trs "Closing old connection pool for database {0} ..." database-id)))
+  (log/debug (u/format-color :red "Closing old connection pool for database %s ..." database-id))
   (connection-pool/destroy-connection-pool! pool-spec)
   (ssh/close-tunnel! pool-spec))
 
@@ -216,13 +216,11 @@
   (set-pool! (u/the-id database) nil nil))
 
 (defn- log-ssh-tunnel-reconnect-msg! [db-id]
-  (log/warn (u/format-color 'red (trs "ssh tunnel for database {0} looks closed; marking pool invalid to reopen it"
-                                      db-id)))
+  (log/warn (u/format-color :red "ssh tunnel for database %s looks closed; marking pool invalid to reopen it" db-id))
   nil)
 
 (defn- log-jdbc-spec-hash-change-msg! [db-id]
-  (log/warn (u/format-color 'yellow (trs "Hash of database {0} details changed; marking pool invalid to reopen it"
-                                          db-id)))
+  (log/warn (u/format-color :yellow "Hash of database %s details changed; marking pool invalid to reopen it" db-id))
   nil)
 
 (defn db->pooled-connection-spec
diff --git a/src/metabase/driver/sql_jdbc/execute.clj b/src/metabase/driver/sql_jdbc/execute.clj
index 9061888aef6a4eab8888b8d95b0bb907d72382c9..96f2b4d606f2f451bf913af552385a0b35b5a31b 100644
--- a/src/metabase/driver/sql_jdbc/execute.clj
+++ b/src/metabase/driver/sql_jdbc/execute.clj
@@ -29,7 +29,7 @@
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.query-processor.util :as qp.util]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [potemkin :as p])
@@ -214,16 +214,16 @@
     (when-let [format-string (sql-jdbc.execute.old/set-timezone-sql driver)]
       (try
         (let [sql (format format-string (str \' timezone-id \'))]
-          (log/debug (trs "Setting {0} database timezone with statement: {1}" driver (pr-str sql)))
+          (log/debugf "Setting %s database timezone with statement: %s" driver (pr-str sql))
           (try
             (.setReadOnly conn false)
             (catch Throwable e
-              (log/debug e (trs "Error setting connection to readwrite"))))
+              (log/debug e "Error setting connection to readwrite")))
           (with-open [stmt (.createStatement conn)]
             (.execute stmt sql)
             (log/tracef "Successfully set timezone for %s database to %s" driver timezone-id)))
         (catch Throwable e
-          (log/error e (trs "Failed to set timezone ''{0}'' for {1} database" timezone-id driver)))))))
+          (log/errorf e "Failed to set timezone '%s' for %s database" timezone-id driver))))))
 
 (defenterprise set-role-if-supported!
   "OSS no-op implementation of `set-role-if-supported!`."
@@ -247,7 +247,7 @@
           (try
             (.setTransactionIsolation conn level)
             (catch Throwable e
-              (log/debug e (trs "Error setting transaction isolation level for {0} database to {1}" (name driver) level-name)))))
+              (log/debugf e "Error setting transaction isolation level for %s database to %s" (name driver) level-name))))
 
         (seq more)
         (recur more)))))
@@ -281,10 +281,10 @@
                               driver)]
       ;; use the deprecated impl for `connection-with-timezone` if one exists.
       (do
-        (log/warn (trs "{0} is deprecated in Metabase 0.47.0. Implement {1} instead."
-                       #_{:clj-kondo/ignore [:deprecated-var]}
-                       `connection-with-timezone
-                       `do-with-connection-with-options))
+        (log/warnf "%s is deprecated in Metabase 0.47.0. Implement %s instead."
+                   #_{:clj-kondo/ignore [:deprecated-var]}
+                   'connection-with-timezone
+                   'do-with-connection-with-options)
         ;; for compatibility, make sure we pass it an actual Database instance.
         (let [database (if (integer? db-or-id-or-spec)
                          (qp.store/with-metadata-provider db-or-id-or-spec
@@ -374,7 +374,7 @@
       (log/trace (pr-str '(.setHoldability conn ResultSet/CLOSE_CURSORS_AT_COMMIT)))
       (.setHoldability conn ResultSet/CLOSE_CURSORS_AT_COMMIT)
       (catch Throwable e
-        (log/debug e (trs "Error setting default holdability for connection"))))))
+        (log/debug e "Error setting default holdability for connection")))))
 
 (defmethod do-with-connection-with-options :sql-jdbc
   [driver db-or-id-or-spec options f]
@@ -474,12 +474,12 @@
       (try
         (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
         (catch Throwable e
-          (log/debug e (trs "Error setting prepared statement fetch direction to FETCH_FORWARD"))))
+          (log/debug e "Error setting prepared statement fetch direction to FETCH_FORWARD")))
       (try
         (when (zero? (.getFetchSize stmt))
           (.setFetchSize stmt (sql-jdbc-fetch-size)))
         (catch Throwable e
-          (log/debug e (trs "Error setting prepared statement fetch size to fetch-size"))))
+          (log/debug e "Error setting prepared statement fetch size to fetch-size")))
       (set-parameters! driver stmt params)
       stmt
       (catch Throwable e
@@ -501,12 +501,12 @@
       (try
         (.setFetchDirection stmt ResultSet/FETCH_FORWARD)
         (catch Throwable e
-          (log/debug e (trs "Error setting statement fetch direction to FETCH_FORWARD"))))
+          (log/debug e "Error setting statement fetch direction to FETCH_FORWARD")))
       (try
         (when (zero? (.getFetchSize stmt))
           (.setFetchSize stmt (sql-jdbc-fetch-size)))
         (catch Throwable e
-          (log/debug e (trs "Error setting statement fetch size to fetch-size"))))
+          (log/debug e "Error setting statement fetch size to fetch-size")))
       stmt
       (catch Throwable e
         (.close stmt)
@@ -518,7 +518,7 @@
   (when canceled-chan
     (a/go
       (when (a/<! canceled-chan)
-        (log/debug (trs "Query canceled, calling Statement.cancel()"))
+        (log/debug "Query canceled, calling Statement.cancel()")
         (u/ignore-exceptions
           (.cancel stmt))))))
 
diff --git a/src/metabase/driver/sql_jdbc/sync/describe_table.clj b/src/metabase/driver/sql_jdbc/sync/describe_table.clj
index 249c2aea43eaaeef7e442bb43c62f9b3936a31ed..f3f44ca6fe64519bf646c376a28f3e48bb65d6b9 100644
--- a/src/metabase/driver/sql_jdbc/sync/describe_table.clj
+++ b/src/metabase/driver/sql_jdbc/sync/describe_table.clj
@@ -54,8 +54,8 @@
   "Given a `database-type` (e.g. `VARCHAR`) return the mapped Metabase type (e.g. `:type/Text`)."
   [driver database-type]
   (or (sql-jdbc.sync.interface/database-type->base-type driver (keyword database-type))
-      (do (log/warn (format "Don't know how to map column type '%s' to a Field base_type, falling back to :type/*."
-                            database-type))
+      (do (log/warnf "Don't know how to map column type '%s' to a Field base_type, falling back to :type/*."
+                     database-type)
           :type/*)))
 
 (defn- calculated-semantic-type
@@ -554,10 +554,8 @@
         fields           (field-types->fields field-types)]
     (if (> (count fields) max-nested-field-columns)
       (do
-        (log/warn
-         (format
-          "More nested field columns detected than maximum. Limiting the number of nested field columns to %d."
-          max-nested-field-columns))
+        (log/warnf "More nested field columns detected than maximum. Limiting the number of nested field columns to %d."
+                   max-nested-field-columns)
         (set (take max-nested-field-columns fields)))
       fields)))
 
diff --git a/src/metabase/driver/util.clj b/src/metabase/driver/util.clj
index abfb1cf911236338b9fbee9ad0ee35040f099eeb..c210333f24fde95da3375786829217621727f492 100644
--- a/src/metabase/driver/util.clj
+++ b/src/metabase/driver/util.clj
@@ -148,7 +148,7 @@
       ;; actually if we are going to `throw-exceptions` we'll rethrow the original but attempt to humanize the message
       ;; first
       (catch Throwable e
-        (log/errorf e "Failed to connect to Database")
+        (log/error e "Failed to connect to Database")
         (throw (if-let [humanized-message (some->> (.getMessage e)
                                                    (driver/humanize-connection-error-message driver))]
                  (let [error-data (cond
@@ -165,7 +165,7 @@
     (try
       (can-connect-with-details? driver details-map :throw-exceptions)
       (catch Throwable e
-        (log/error e (trs "Failed to connect to database"))
+        (log/error e "Failed to connect to database")
         false))))
 
 ;;; +----------------------------------------------------------------------------------------------------------------+
@@ -296,8 +296,7 @@
   (let [content (or placeholder
                     (try (getter)
                          (catch Throwable e
-                           (log/error e (trs "Error invoking getter for connection property {0}"
-                                             (:name conn-prop))))))]
+                           (log/errorf e "Error invoking getter for connection property %s" (:name conn-prop)))))]
     (when (string? content)
       (-> conn-prop
           (assoc :placeholder content)
@@ -503,7 +502,7 @@
                                  (->> (driver/connection-properties driver)
                                       (connection-props-server->client driver))
                                  (catch Throwable e
-                                   (log/error e (trs "Unable to determine connection properties for driver {0}" driver))))]
+                                   (log/errorf e "Unable to determine connection properties for driver %s" driver)))]
                  :when  props]
              ;; TODO - maybe we should rename `details-fields` -> `connection-properties` on the FE as well?
              [driver {:source {:type (driver-source (name driver))
diff --git a/src/metabase/email.clj b/src/metabase/email.clj
index a03202b3dcbb57556cafc83065f76ae4201173a6..244170bb0cf8d6b2fd4349f6be99f40974b44824 100644
--- a/src/metabase/email.clj
+++ b/src/metabase/email.clj
@@ -3,7 +3,7 @@
    [malli.core :as mc]
    [metabase.analytics.prometheus :as prometheus]
    [metabase.models.setting :as setting :refer [defsetting]]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -202,7 +202,7 @@
   (try
     (send-email-retrying! msg-args)
     (catch Throwable e
-      (log/warn e (trs "Failed to send email"))
+      (log/warn e "Failed to send email")
       {::error e})))
 
 (def ^:private SMTPSettings
@@ -235,7 +235,7 @@
         (.connect transport host port user pass)))
     {::error nil}
     (catch Throwable e
-      (log/error e (trs "Error testing SMTP connection"))
+      (log/error e "Error testing SMTP connection")
       {::error e})))
 
 (def ^:private email-security-order [:tls :starttls :ssl])
diff --git a/src/metabase/events.clj b/src/metabase/events.clj
index 3d768ef171626f518e630a2aacfcef30045fd8c5..a8641b32db5b19e80ddb32a7b173f3d6c0f7155d 100644
--- a/src/metabase/events.clj
+++ b/src/metabase/events.clj
@@ -40,7 +40,7 @@
   []
   (doseq [ns-symb u/metabase-namespace-symbols
           :when   (.startsWith (name ns-symb) "metabase.events.")]
-    (log/info (i18n/trs "Loading events namespace:") (u/format-color 'blue ns-symb) (u/emoji "👂"))
+    (log/info "Loading events namespace:" (u/format-color :blue ns-symb) (u/emoji "👂"))
     (classloader/require ns-symb)))
 
 (defn- initialize-events!
diff --git a/src/metabase/events/sync_database.clj b/src/metabase/events/sync_database.clj
index 33739a126d9a84c218b61b773358f0cb4f7d9446..29b9df8e468668d8692a9866c64510a2ee62c086 100644
--- a/src/metabase/events/sync_database.clj
+++ b/src/metabase/events/sync_database.clj
@@ -4,7 +4,6 @@
    [metabase.sync :as sync]
    [metabase.sync.sync-metadata :as sync-metadata]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [methodical.core :as methodical]))
 
@@ -24,6 +23,6 @@
          (sync/sync-database! database)
          (sync-metadata/sync-db-metadata! database))
        (catch Throwable e
-         (log/error e (trs "Error syncing Database {0}" (u/the-id database)))))))
+         (log/errorf e "Error syncing Database %s" (u/the-id database))))))
    (catch Throwable e
      (log/warnf e "Failed to process sync-database event: %s" topic))))
diff --git a/src/metabase/integrations/common.clj b/src/metabase/integrations/common.clj
index e017190f1eb711571e34e83a02383daafd71f249..3faf2f374bda7abab06aaaacb51a954f98933649 100644
--- a/src/metabase/integrations/common.clj
+++ b/src/metabase/integrations/common.clj
@@ -11,8 +11,7 @@
                                                   define-multi-setting-impl]]
    [metabase.public-settings.premium-features :as premium-features]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [deferred-tru
-                               trs]]
+   [metabase.util.i18n :refer [deferred-tru]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]))
 
@@ -56,7 +55,7 @@
       (try
         (t2/insert! PermissionsGroupMembership :group_id id, :user_id user-id)
         (catch Throwable e
-          (log/error e (trs "Error adding User {0} to Group {1}" user-id id)))))))
+          (log/errorf e "Error adding User %s to Group %s" user-id id))))))
 
 (define-multi-setting send-new-sso-user-admin-email?
   (deferred-tru "Should new email notifications be sent to admins, for all new SSO users?")
diff --git a/src/metabase/integrations/google.clj b/src/metabase/integrations/google.clj
index 57e4a1066b5fa3634359f7a1262cc34e90aa94aa..75b76019d11e9c2c238928b9ef06e575e1b14815 100644
--- a/src/metabase/integrations/google.clj
+++ b/src/metabase/integrations/google.clj
@@ -13,7 +13,7 @@
    [metabase.models.user :as user :refer [User]]
    [metabase.plugins.classloader :as classloader]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [toucan2.core :as t2]))
@@ -138,5 +138,5 @@
   [{{:keys [token]} :body, :as _request}]
   (let [token-info-response                    (http/post (format google-auth-token-info-url token))
         {:keys [given_name family_name email]} (google-auth-token-info token-info-response)]
-    (log/info (trs "Successfully authenticated Google Sign-In token for: {0} {1}" given_name family_name))
+    (log/infof "Successfully authenticated Google Sign-In token for: %s %s" given_name family_name)
     (api/check-500 (google-auth-fetch-or-create-user! given_name family_name email))))
diff --git a/src/metabase/integrations/ldap.clj b/src/metabase/integrations/ldap.clj
index a0d7bfd64b0d95de820328ce8f60569ce9201d38..36271668c1c8ce196742056544bd063d73861373 100644
--- a/src/metabase/integrations/ldap.clj
+++ b/src/metabase/integrations/ldap.clj
@@ -213,10 +213,10 @@
        (log/debug "LDAP connection test successful")
        {:status :SUCCESS}))
     (catch LDAPException e
-       (log/debugf "LDAP connection test failed: " (.getMessage e))
+       (log/debug "LDAP connection test failed: " (.getMessage e))
       {:status :ERROR, :message (.getMessage e), :code (.getResultCode e)})
     (catch Exception e
-      (log/debugf "LDAP connection test failed: " (.getMessage e))
+      (log/debug "LDAP connection test failed: " (.getMessage e))
       {:status :ERROR, :message (.getMessage e)})))
 
 (defn test-current-ldap-details
diff --git a/src/metabase/integrations/slack.clj b/src/metabase/integrations/slack.clj
index 2ccbfb6af5a1f5d4cdd0ca953bcb0f3ba5cc7fb5..8dd8349fbbe44e70034df6200587b1a403a9224d 100644
--- a/src/metabase/integrations/slack.clj
+++ b/src/metabase/integrations/slack.clj
@@ -116,7 +116,8 @@
       (when (slack-token-valid?) (messages/send-slack-token-error-emails!))
       (slack-token-valid?! false))
     (when invalid-token?
-      (log/warn (u/pprint-to-str 'red (trs "🔒 Your Slack authorization token is invalid or has been revoked. Please update your integration in Admin Settings -> Slack."))))
+      (log/warn (u/colorize :red (str "🔒 Your Slack authorization token is invalid or has been revoked. Please"
+                                      " update your integration in Admin Settings -> Slack."))))
     (throw (ex-info message error))))
 
 (defn- handle-response [{:keys [status body]}]
@@ -133,7 +134,7 @@
                   (slack-token))]
     (when token
       (let [url     (str "https://slack.com/api/" (name endpoint))
-            _       (log/trace "Slack API request: %s %s" (pr-str url) (pr-str request))
+            _       (log/tracef "Slack API request: %s %s" (pr-str url) (pr-str request))
             request (m/deep-merge
                      {:headers        {:authorization (str "Bearer\n" token)}
                       :as             :stream
@@ -338,7 +339,7 @@
                            (POST "files.upload" request))
                        (throw e))))]
     (u/prog1 (get-in response [:file :url_private])
-      (log/debug (trs "Uploaded image") <>))))
+      (log/debug "Uploaded image" <>))))
 
 (mu/defn post-chat-message!
   "Calls Slack API `chat.postMessage` endpoint and posts a message to a channel. `attachments` should be serialized
diff --git a/src/metabase/legacy_mbql/normalize.cljc b/src/metabase/legacy_mbql/normalize.cljc
index 7b55520c9174beba8452d7d132fbaf895dc56043..229e5c69bbf345b4cba6b3ea736a3878f92327a0 100644
--- a/src/metabase/legacy_mbql/normalize.cljc
+++ b/src/metabase/legacy_mbql/normalize.cljc
@@ -679,7 +679,7 @@
           (try
             (canonicalize-mbql-clause form)
             (catch #?(:clj Throwable :cljs js/Error) e
-              (log/error (i18n/tru "Invalid clause:") form)
+              (log/error "Invalid clause:" form)
               (throw (ex-info (i18n/tru "Invalid MBQL clause: {0}" (ex-message e))
                               {:clause form}
                               e))))]
diff --git a/src/metabase/legacy_mbql/util.cljc b/src/metabase/legacy_mbql/util.cljc
index 1959a1be4195e9544e2f7c653ac46f3d663dd56d..20418f7c3eddf9ae94ae324d0ed1bd16e60b469a 100644
--- a/src/metabase/legacy_mbql/util.cljc
+++ b/src/metabase/legacy_mbql/util.cljc
@@ -734,8 +734,7 @@
           (mbql.s/valid-temporal-unit-for-base-type? base-type unit))
     (assoc-field-options clause :temporal-unit unit)
     (do
-      (log/warn (i18n/tru "{0} is not a valid temporal unit for {1}; not adding to clause {2}"
-                          unit base-type (pr-str clause)))
+      (log/warnf "%s is not a valid temporal unit for %s; not adding to clause %s" unit base-type (pr-str clause))
       clause)))
 
 (defn remove-namespaced-options
diff --git a/src/metabase/lib/field.cljc b/src/metabase/lib/field.cljc
index 1a7a1a2a9e61c03c656d295a7ca9a5e62a25d932..d4e01edaa2c02eff924c343ce540279f3363a8f2 100644
--- a/src/metabase/lib/field.cljc
+++ b/src/metabase/lib/field.cljc
@@ -41,9 +41,9 @@
                             column-metadatas))
             [:lib/desired-column-alias :name])
       (do
-        (log/warn (i18n/tru "Invalid :field clause: column {0} does not exist. Found: {1}"
-                            (pr-str column-name)
-                            (pr-str (mapv :lib/desired-column-alias column-metadatas))))
+        (log/warnf "Invalid :field clause: column %s does not exist. Found: %s"
+                   (pr-str column-name)
+                   (pr-str (mapv :lib/desired-column-alias column-metadatas)))
         nil)))
 
 (def ^:private ^:dynamic *recursive-column-resolution-by-name*
@@ -71,8 +71,8 @@
                                                 (:expressions  stage)
                                                 (:fields       stage))
                                         (lib.metadata.calculation/visible-columns query stage-number stage))
-                                      (log/warn (i18n/tru "Cannot resolve column {0}: stage has no metadata"
-                                                          (pr-str column-name))))]
+                                      (log/warnf "Cannot resolve column %s: stage has no metadata"
+                                                 (pr-str column-name)))]
         (when-let [column (and (seq stage-columns)
                                (resolve-column-name-in-metadata column-name stage-columns))]
           (cond-> column
@@ -648,7 +648,7 @@
           ;; Default case - do nothing if we don't know about the incoming value.
           ;; Generates a warning, as we should aim to capture all the :source/* values here.
           (do
-            (log/warn (i18n/tru "Cannot add-field with unknown source {0}" (pr-str source)))
+            (log/warnf "Cannot add-field with unknown source %s" (pr-str source))
             query))
         ;; Then drop any redundant :fields clauses.
         lib.remove-replace/normalize-fields-clauses)))
@@ -718,7 +718,7 @@
           ;; Default case: do nothing and return the query unchaged.
           ;; Generate a warning - we should aim to capture every `:source/*` value above.
           (do
-            (log/warn (i18n/tru "Cannot remove-field with unknown source {0}" (pr-str source)))
+            (log/warnf "Cannot remove-field with unknown source %s" (pr-str source))
             query))
         ;; Then drop any redundant :fields clauses.
         lib.remove-replace/normalize-fields-clauses)))
diff --git a/src/metabase/lib/metadata/calculation.cljc b/src/metabase/lib/metadata/calculation.cljc
index 3d4ada086c630bea87037cd3f3148fcfba5f8ce2..04dc252a12389c218b61428a24406f084ebf9403 100644
--- a/src/metabase/lib/metadata/calculation.cljc
+++ b/src/metabase/lib/metadata/calculation.cljc
@@ -265,7 +265,7 @@
     (try
       (describe-query query)
       (catch #?(:clj Throwable :cljs js/Error) e
-        (log/error e (i18n/tru "Error calculating display name for query: {0}" (ex-message e)))
+        (log/errorf e "Error calculating display name for query: %s" (ex-message e))
         nil))))
 
 (defmulti display-info-method
diff --git a/src/metabase/metabot/client.clj b/src/metabase/metabot/client.clj
index 330aa270a6bde566b297d103b74351b201aaabf3..e716a7c79fcb24bbcc269778b090f45f46c3abd1 100644
--- a/src/metabase/metabot/client.clj
+++ b/src/metabase/metabot/client.clj
@@ -81,7 +81,7 @@
 (defn- default-embedding-endpoint
   "OpenAI is the default completion endpoint\""
   [params options]
-  (log/debugf "Creating embedding...")
+  (log/debug "Creating embedding...")
   (openai.api/create-embedding
    (select-keys params [:model :input])
    options))
diff --git a/src/metabase/models/card.clj b/src/metabase/models/card.clj
index 51fdf83112161a8ccd415680cfc98017fd1c40e2..a8413d20f23fe06213d42798049eef82c9fc97f3 100644
--- a/src/metabase/models/card.clj
+++ b/src/metabase/models/card.clj
@@ -642,20 +642,17 @@ saved later when it is ready."
           id              (:id card)]
       (cond (= port timeoutc)
             (do (a/close! result-metadata-chan)
-                (log/info (trs "Metadata not ready in {0} minutes, abandoning"
-                               (long (/ metadata-async-timeout-ms 1000 60)))))
+                (log/infof "Metadata not ready in %s minutes, abandoning" (long (/ metadata-async-timeout-ms 1000 60))))
 
             (not (seq metadata))
-            (log/info (trs "Not updating metadata asynchronously for card {0} because no metadata"
-                           id))
+            (log/infof "Not updating metadata asynchronously for card %s because no metadata" id)
             :else
             (future
               (let [current-query (t2/select-one-fn :dataset_query Card :id id)]
                 (if (= (:dataset_query card) current-query)
                   (do (t2/update! Card id {:result_metadata metadata})
-                      (log/info (trs "Metadata updated asynchronously for card {0}" id)))
-                  (log/info (trs "Not updating metadata asynchronously for card {0} because query has changed"
-                                 id)))))))))
+                      (log/infof "Metadata updated asynchronously for card %s" id))
+                  (log/infof "Not updating metadata asynchronously for card %s because query has changed" id))))))))
 
 (defn create-card!
   "Create a new Card. Metadata will be fetched off thread. If the metadata takes longer than [[metadata-sync-wait-ms]]
@@ -694,7 +691,7 @@ saved later when it is ready."
      (when-not delay-event?
        (events/publish-event! :event/card-create {:object card :user-id (:id creator)}))
      (when timed-out?
-       (log/info (trs "Metadata not available soon enough. Saving new card and asynchronously updating metadata")))
+       (log/info "Metadata not available soon enough. Saving new card and asynchronously updating metadata"))
      ;; include same information returned by GET /api/card/:id since frontend replaces the Card it currently has with
      ;; returned one -- See #4283
      (u/prog1 card
diff --git a/src/metabase/models/collection.clj b/src/metabase/models/collection.clj
index ca1c452b7f4b45d9a1ea4301300d60ecb0dbe251..4a06ea65368106d3f1de18051ffa976539fd3b4d 100644
--- a/src/metabase/models/collection.clj
+++ b/src/metabase/models/collection.clj
@@ -635,8 +635,8 @@
   (let [orig-children-location (children-location collection)
         new-children-location  (children-location (assoc collection :location new-location))]
     ;; first move this Collection
-    (log/info (trs "Moving Collection {0} and its descendants from {1} to {2}"
-                   (u/the-id collection) (:location collection) new-location))
+    (log/infof "Moving Collection %s and its descendants from %s to %s"
+               (u/the-id collection) (:location collection) new-location)
     (t2/with-transaction [_conn]
       (t2/update! Collection (u/the-id collection) {:location new-location})
       ;; we need to update all the descendant collections as well...
diff --git a/src/metabase/models/data_permissions/graph.clj b/src/metabase/models/data_permissions/graph.clj
index 5676498251f04b167c9034b11f660424bedfd215..ba2f050da225b1fd4f061d678d6a7336b16976c6 100644
--- a/src/metabase/models/data_permissions/graph.clj
+++ b/src/metabase/models/data_permissions/graph.clj
@@ -18,7 +18,7 @@
    [metabase.models.permissions-revision :as perms-revision]
    [metabase.public-settings.premium-features :as premium-features :refer [defenterprise]]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [toucan2.core :as t2]))
@@ -365,10 +365,9 @@
 (defn log-permissions-changes
   "Log changes to the permissions graph."
   [old new]
-  (log/debug
-   (trs "Changing permissions")
-   "\n" (trs "FROM:") (u/pprint-to-str 'magenta old)
-   "\n" (trs "TO:")   (u/pprint-to-str 'blue    new)))
+  (log/debug "Changing permissions"
+             "\n FROM:" (u/pprint-to-str :magenta old)
+             "\n TO:"   (u/pprint-to-str :blue new)))
 
 (defn check-revision-numbers
   "Check that the revision number coming in as part of `new-graph` matches the one from `old-graph`. This way we can
diff --git a/src/metabase/models/database.clj b/src/metabase/models/database.clj
index 0a95db96af2efe7c01680070561dfd5a773b4aa1..dcbf88dfe2c9a260c9c7f6958a64975e06fb73e0 100644
--- a/src/metabase/models/database.clj
+++ b/src/metabase/models/database.clj
@@ -89,7 +89,7 @@
     (classloader/require 'metabase.task.sync-databases)
     ((resolve 'metabase.task.sync-databases/check-and-schedule-tasks-for-db!) database)
     (catch Throwable e
-      (log/error e (trs "Error scheduling tasks for DB")))))
+      (log/error e "Error scheduling tasks for DB"))))
 
 ;; TODO - something like NSNotificationCenter in Objective-C would be really really useful here so things that want to
 ;; implement behavior when an object is deleted can do it without having to put code here
@@ -101,7 +101,7 @@
     (classloader/require 'metabase.task.sync-databases)
     ((resolve 'metabase.task.sync-databases/unschedule-tasks-for-db!) database)
     (catch Throwable e
-      (log/error e (trs "Error unscheduling tasks for DB.")))))
+      (log/error e "Error unscheduling tasks for DB."))))
 
 (defn- set-new-database-permissions!
   [database]
@@ -174,9 +174,7 @@
                                     acc))
                                 []
                                 possible-secret-prop-names)]
-        (log/info (trs "Deleting secret ID {0} from app DB because the owning database ({1}) is being deleted"
-                       secret-id
-                       id))
+        (log/infof "Deleting secret ID %s from app DB because the owning database (%s) is being deleted" secret-id id)
         (t2/delete! Secret :id secret-id)))))
 
 (t2/define-before-delete :model/Database
@@ -186,7 +184,7 @@
   (try
     (driver/notify-database-updated driver database)
     (catch Throwable e
-      (log/error e (trs "Error sending database deletion notification")))))
+      (log/error e "Error sending database deletion notification"))))
 
 (defn- handle-db-details-secret-prop!
   "Helper fn for reducing over a map of all the secret connection-properties, keyed by name. This is side effecting. At
@@ -251,10 +249,9 @@
                        :existing-engine existing-engine
                        :new-engine      new-engine}))
       (u/prog1 (-> database
-                   (cond->
-                     ;; If the engine doesn't support nested field columns, `json_unfolding` must be nil
-                     (and (some? (:details database))
-                          (not (driver/database-supports? (or new-engine existing-engine) :nested-field-columns database)))
+                   ;; If the engine doesn't support nested field columns, `json_unfolding` must be nil
+                   (cond-> (and (some? (:details database))
+                                (not (driver/database-supports? (or new-engine existing-engine) :nested-field-columns database)))
                      (update :details dissoc :json_unfolding))
                    handle-secrets-changes)
         ;; TODO - this logic would make more sense in post-update if such a method existed
@@ -266,16 +263,17 @@
             (when (not= [new-metadata-schedule new-fieldvalues-schedule]
                         [old-metadata-schedule old-fieldvalues-schedule])
               (log/info
-                (trs "{0} Database ''{1}'' sync/analyze schedules have changed!" existing-engine existing-name)
-                "\n"
-                (trs "Sync metadata was: ''{0}'' is now: ''{1}''" old-metadata-schedule new-metadata-schedule)
-                "\n"
-                (trs "Cache FieldValues was: ''{0}'', is now: ''{1}''" old-fieldvalues-schedule new-fieldvalues-schedule))
-              ;; reschedule the database. Make sure we're passing back the old schedule if one of the two wasn't supplied
+               (format "%s Database '%s' sync/analyze schedules have changed!" existing-engine existing-name)
+               "\n"
+               (format "Sync metadata was: '%s' is now: '%s'" old-metadata-schedule new-metadata-schedule)
+               "\n"
+               (format "Cache FieldValues was: '%s', is now: '%s'" old-fieldvalues-schedule new-fieldvalues-schedule))
+              ;; reschedule the database. Make sure we're passing back the old schedule if one of the two wasn't
+              ;; supplied
               (schedule-tasks!
-                (assoc database
-                       :metadata_sync_schedule      new-metadata-schedule
-                       :cache_field_values_schedule new-fieldvalues-schedule)))))
+               (assoc database
+                      :metadata_sync_schedule      new-metadata-schedule
+                      :cache_field_values_schedule new-fieldvalues-schedule)))))
         ;; This maintains a constraint that if a driver doesn't support actions, it can never be enabled
         ;; If we drop support for actions for a driver, we'd need to add a migration to disable actions for all databases
         (when (and (:database-enable-actions (or new-settings existing-settings))
diff --git a/src/metabase/models/field.clj b/src/metabase/models/field.clj
index 8ce567069f8ec11a8ff6c2ac7ae4517e6e12cb45..862ee6a41afc45cc60d0129c80142e64ff289efa 100644
--- a/src/metabase/models/field.clj
+++ b/src/metabase/models/field.clj
@@ -18,7 +18,7 @@
     :as premium-features
     :refer [defenterprise]]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -77,7 +77,7 @@
              ancestor-types)
           k
           (do
-            (log/warn (trs "Invalid Field {0} {1}: falling back to {2}" column-name k fallback-type))
+            (log/warnf "Invalid Field %s %s: falling back to %s" column-name k fallback-type)
             fallback-type))))))
 
 (def ^:private transform-field-base-type
diff --git a/src/metabase/models/field_values.clj b/src/metabase/models/field_values.clj
index c42e2727bb5c4f3408c05ffaa6d761526ca10f9a..a831b44f17dd5aeee161e183d7046a10c5fa3f9b 100644
--- a/src/metabase/models/field_values.clj
+++ b/src/metabase/models/field_values.clj
@@ -34,7 +34,7 @@
    [metabase.public-settings.premium-features :refer [defenterprise]]
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli.schema :as ms]
    [methodical.core :as methodical]
@@ -360,7 +360,7 @@
                           (= (count distinct-values)
                              metadata-queries/absolute-max-distinct-values-limit))})
     (catch Throwable e
-      (log/error e (trs "Error fetching field values"))
+      (log/error e "Error fetching field values")
       nil)))
 
 (defn- delete-duplicates-and-return-latest!
@@ -415,9 +415,11 @@
            (or has_more_values
                (> (count values) auto-list-cardinality-threshold)))
       (do
-        (log/info (trs "Field {0} was previously automatically set to show a list widget, but now has {1} values."
-                       field-name (count values))
-                  (trs "Switching Field to use a search widget instead."))
+        (log/infof
+         (str "Field %s was previously automatically set to show a list widget, but now has %s values."
+              " Switching Field to use a search widget instead.")
+         field-name
+         (count values))
         (t2/update! 'Field (u/the-id field) {:has_field_values nil})
         (clear-field-values-for-field! field)
         ::fv-deleted)
@@ -425,28 +427,28 @@
       (and (= (:values field-values) values)
            (= (:has_more_values field-values) has_more_values))
       (do
-        (log/debug (trs "FieldValues for Field {0} remain unchanged. Skipping..." field-name))
+        (log/debugf "FieldValues for Field %s remain unchanged. Skipping..." field-name)
         ::fv-skipped)
 
       ;; if the FieldValues object already exists then update values in it
       (and field-values unwrapped-values)
       (do
-       (log/debug (trs "Storing updated FieldValues for Field {0}..." field-name))
-       (t2/update! FieldValues (u/the-id field-values)
-                   (m/remove-vals nil?
-                                  {:has_more_values       has_more_values
-                                   :values                values
-                                   :human_readable_values (fixup-human-readable-values field-values values)}))
-       ::fv-updated)
+        (log/debugf "Storing updated FieldValues for Field %s..." field-name)
+        (t2/update! FieldValues (u/the-id field-values)
+                    (m/remove-vals nil?
+                                   {:has_more_values       has_more_values
+                                    :values                values
+                                    :human_readable_values (fixup-human-readable-values field-values values)}))
+        ::fv-updated)
 
       ;; if FieldValues object doesn't exist create one
       unwrapped-values
       (do
-        (log/debug (trs "Storing FieldValues for Field {0}..." field-name))
+        (log/debugf "Storing FieldValues for Field %s..." field-name)
         (mdb.query/select-or-insert! FieldValues {:field_id (u/the-id field), :type :full}
-          (constantly {:has_more_values       has_more_values
-                       :values                values
-                       :human_readable_values human-readable-values}))
+                                     (constantly {:has_more_values       has_more_values
+                                                  :values                values
+                                                  :human_readable_values human-readable-values}))
         ::fv-created)
 
       ;; otherwise this Field isn't eligible, so delete any FieldValues that might exist
@@ -505,13 +507,12 @@
                  (filter field-should-have-field-values?
                          (t2/select ['Field :name :id :base_type :effective_type :coercion_strategy
                                      :semantic_type :visibility_type :table_id :has_field_values]
-                           :id [:in field-ids])))
+                                    :id [:in field-ids])))
         table-id->is-on-demand? (table-ids->table-id->is-on-demand? (map :table_id fields))]
     (doseq [{table-id :table_id, :as field} fields]
       (when (table-id->is-on-demand? table-id)
-        (log/debug
-         (trs "Field {0} ''{1}'' should have FieldValues and belongs to a Database with On-Demand FieldValues updating."
-                 (u/the-id field) (:name field)))
+        (log/debugf "Field %s '%s' should have FieldValues and belongs to a Database with On-Demand FieldValues updating."
+                    (u/the-id field) (:name field))
         (create-or-update-full-field-values! field)))))
 
 ;;; +----------------------------------------------------------------------------------------------------------------+
diff --git a/src/metabase/models/humanization.clj b/src/metabase/models/humanization.clj
index accabe7d2164fa3f2733ca1e0f3ea9bd0819b229..4404ed928cce9755d75baace4ee1c4849546def6 100644
--- a/src/metabase/models/humanization.clj
+++ b/src/metabase/models/humanization.clj
@@ -13,7 +13,7 @@
    [metabase.models.setting :as setting :refer [defsetting]]
    [metabase.util :as u]
    [metabase.util.humanization :as u.humanization]
-   [metabase.util.i18n :refer [deferred-tru trs tru]]
+   [metabase.util.i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [toucan2.core :as t2]))
@@ -45,10 +45,10 @@
                 custom-display-name?      (not= old-strategy-display-name display-name)]
             (when (and (not= display-name new-strategy-display-name)
                        (not custom-display-name?))
-              (log/info (trs "Updating display name for {0} ''{1}'': ''{2}'' -> ''{3}''"
-                             (name model) internal-name display-name new-strategy-display-name))
+              (log/infof "Updating display name for %s '%s': '%s' -> '%s'"
+                         (name model) internal-name display-name new-strategy-display-name)
               (t2/update! model id
-                {:display_name new-strategy-display-name}))))
+                          {:display_name new-strategy-display-name}))))
         (t2/reducible-select [model :id :name :display_name])))
 
 (mu/defn ^:private re-humanize-table-and-field-names!
@@ -71,8 +71,8 @@
       ;; now rehumanize all the Tables and Fields using the new strategy.
       ;; TODO: Should we do this in a background thread because it is potentially slow?
       ;; https://github.com/metabase/metabase/issues/39406
-      (log/info (trs "Changing Table & Field names humanization strategy from ''{0}'' to ''{1}''"
-                     (name old-strategy) (name new-strategy)))
+      (log/infof "Changing Table & Field names humanization strategy from '%s' to '%s'"
+                 (name old-strategy) (name new-strategy))
       (re-humanize-table-and-field-names! old-strategy))))
 
 (defsetting ^{:added "0.28.0"} humanization-strategy
diff --git a/src/metabase/models/interface.clj b/src/metabase/models/interface.clj
index 289da79aafe48741aef35be00bc035331b067878..35496760209afbb63fb5513104e9218ee27bad08 100644
--- a/src/metabase/models/interface.clj
+++ b/src/metabase/models/interface.clj
@@ -208,8 +208,7 @@
     (try
       (doall (f query))
       (catch Throwable e
-        (log/error e (tru "Unable to normalize:") "\n"
-                   (u/pprint-to-str 'red query))
+        (log/errorf e "Unable to normalize:\n%s" (u/pprint-to-str 'red query))
         nil))))
 
 (defn normalize-parameters-list
diff --git a/src/metabase/models/login_history.clj b/src/metabase/models/login_history.clj
index 4fc88985d923bfffbd192fed19fd0708e1549a7e..f0e70872e54cc82a775d8fd60fea7dcebb0eb694 100644
--- a/src/metabase/models/login_history.clj
+++ b/src/metabase/models/login_history.clj
@@ -5,7 +5,7 @@
    [metabase.models.setting :refer [defsetting]]
    [metabase.server.request.util :as req.util]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :as i18n :refer [trs tru]]
+   [metabase.util.i18n :as i18n :refer [tru]]
    [metabase.util.log :as log]
    [methodical.core :as methodical]
    [toucan2.connection :as t2.conn]
@@ -93,7 +93,7 @@
           (let [[info] (human-friendly-infos [login-history])]
             (messages/send-login-from-new-device-email! info))
           (catch Throwable e
-            (log/error e (trs "Error sending ''login from new device'' notification email"))))))))
+            (log/error e "Error sending 'login from new device' notification email")))))))
 
 (t2/define-after-insert :model/LoginHistory
   [login-history]
diff --git a/src/metabase/models/metric.clj b/src/metabase/models/metric.clj
index 24b7784132876ceb5ccbf76e6c205b14f5f634b5..dc305189db61ed681af9ad470d6b6cb04d41b79f 100644
--- a/src/metabase/models/metric.clj
+++ b/src/metabase/models/metric.clj
@@ -89,7 +89,7 @@
             query       (lib.query/query-from-legacy-inner-query metadata-provider database-id definition)]
         (lib/describe-query query))
       (catch Throwable e
-        (log/error e (tru "Error calculating Metric description: {0}" (ex-message e)))
+        (log/errorf e "Error calculating Metric description: %s" (ex-message e))
         nil))))
 
 (mu/defn ^:private warmed-metadata-provider :- lib.metadata/MetadataProvider
diff --git a/src/metabase/models/model_index.clj b/src/metabase/models/model_index.clj
index fbab288704a648fccf40858ce4016269ff02765e..595d206f69a4ec213820d1e376f29fad62a24f76 100644
--- a/src/metabase/models/model_index.clj
+++ b/src/metabase/models/model_index.clj
@@ -9,7 +9,6 @@
    [metabase.query-processor :as qp]
    [metabase.sync.schedules :as sync.schedules]
    [metabase.util.cron :as u.cron]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [methodical.core :as methodical]
@@ -87,7 +86,7 @@ don't, (and shouldn't) care that those are expressions. They are just another fi
                              :limit        (inc max-indexed-values)}})
                 :data :rows (filter valid-tuples?))]
       (catch Exception e
-        (log/warn (trs "Error fetching indexed values for model {0}" (:id model)) e)
+        (log/warnf e "Error fetching indexed values for model %s" (:id model))
         [(ex-message e) []]))))
 
 (defn find-changes
@@ -140,9 +139,8 @@ don't, (and shouldn't) care that those are expressions. They are just another fi
                                      "overflow"
                                      "indexed")}))
         (catch Exception e
-          (log/error (format "Error saving model-index values for model-index: %d, model: %d"
-                             (:id model-index) (:model-id model-index))
-                     e)
+          (log/error e (format "Error saving model-index values for model-index: %d, model: %d"
+                               (:id model-index) (:model-id model-index)))
           (t2/update! ModelIndex (:id model-index)
                       {:state      "error"
                        :error      (ex-message e)
diff --git a/src/metabase/models/permissions.clj b/src/metabase/models/permissions.clj
index 2551e3b99044cb394eb52b2ee16acc4313e1a6f5..3bd78beb05705b67acb8ab8f29052eb2dc126d9d 100644
--- a/src/metabase/models/permissions.clj
+++ b/src/metabase/models/permissions.clj
@@ -179,7 +179,7 @@
     :refer [defenterprise]]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -353,9 +353,7 @@
   [permissions]
   (u/prog1 permissions
     (assert-valid permissions)
-    (log/debug (u/colorize 'green (trs "Granting permissions for group {0}: {1}"
-                                       (:group_id permissions)
-                                       (:object permissions))))))
+    (log/debug (u/format-color :green "Granting permissions for group %s: %s" (:group_id permissions) (:object permissions)))))
 
 (t2/define-before-update :model/Permissions
   [_]
@@ -363,9 +361,7 @@
 
 (t2/define-before-delete :model/Permissions
   [permissions]
-  (log/debug (u/colorize 'red (trs "Revoking permissions for group {0}: {1}"
-                                   (:group_id permissions)
-                                   (:object permissions))))
+  (log/debug (u/format-color :red "Revoking permissions for group %s: %s" (:group_id permissions) (:object permissions)))
   (assert-not-admin-group permissions))
 
 
@@ -415,7 +411,7 @@
                                           (distinct (conj (perms.u/->v2-path path) path))))
      ;; on some occasions through weirdness we might accidentally try to insert a key that's already been inserted
      (catch Throwable e
-       (log/error e (u/format-color 'red (tru "Failed to grant permissions")))
+       (log/error e (u/format-color 'red "Failed to grant permissions"))
        ;; if we're running tests, we're doing something wrong here if duplicate permissions are getting assigned,
        ;; mostly likely because tests aren't properly cleaning up after themselves, and possibly causing other tests
        ;; to pass when they shouldn't. Don't allow this during tests
diff --git a/src/metabase/models/segment.clj b/src/metabase/models/segment.clj
index 986582a33d0990bf441716109ce1534af1b519ed..2ffd3549c786455db122323b3f83496e8e8714f6 100644
--- a/src/metabase/models/segment.clj
+++ b/src/metabase/models/segment.clj
@@ -83,7 +83,7 @@
             query       (lib.query/query-from-legacy-inner-query metadata-provider database-id definition)]
         (lib/describe-top-level-key query :filters))
       (catch Throwable e
-        (log/error e (tru "Error calculating Segment description: {0}" (ex-message e)))
+        (log/errorf e "Error calculating Segment description: %s" (ex-message e))
         nil))))
 
 (mu/defn ^:private warmed-metadata-provider :- lib.metadata/MetadataProvider
diff --git a/src/metabase/models/serialization.clj b/src/metabase/models/serialization.clj
index 3634d022d97c90b810cf89f9c1fdd3ad9340b6e8..815713a70b3fa4ea3cc2a1bcd406b7b8f1d13712 100644
--- a/src/metabase/models/serialization.clj
+++ b/src/metabase/models/serialization.clj
@@ -24,7 +24,6 @@
    [metabase.shared.models.visualization-settings :as mb.viz]
    [metabase.util :as u]
    [metabase.util.connection :as u.conn]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]
    [toucan2.model :as t2.model]))
@@ -338,7 +337,7 @@
 
 (defn- log-and-extract-one
   [model opts instance]
-  (log/info (trs "Extracting {0} {1}" model (:id instance)))
+  (log/infof "Extracting %s %s" model (:id instance))
   (extract-one model opts instance))
 
 (defmethod extract-all :default [model opts]
diff --git a/src/metabase/models/setting.clj b/src/metabase/models/setting.clj
index b418e906addda7174c8f03c65a43104205ae14a7..02bbf1572a1fec30bc6c5bb89fd158704675a19e 100644
--- a/src/metabase/models/setting.clj
+++ b/src/metabase/models/setting.clj
@@ -729,9 +729,9 @@
        ;; and there's actually a row in the DB that's not in the cache for some reason. Go ahead and update the
        ;; existing value and log a warning
        (catch Throwable e
-         (log/warn (deferred-tru "Error inserting a new Setting:") "\n"
-                   (.getMessage e) "\n"
-                   (deferred-tru "Assuming Setting already exists in DB and updating existing value."))
+         (log/warn "Error inserting a new Setting:\n"
+                   (ex-message e) "\n"
+                   "Assuming Setting already exists in DB and updating existing value.")
          (update-setting! setting-name new-value))))
 
 (defn- obfuscated-value? [v]
@@ -766,16 +766,15 @@
         setting-name                      (setting-name setting)]
     ;; if someone attempts to set a sensitive setting to an obfuscated value (probably via a misuse of the `set-many!` function, setting values that have not changed), ignore the change. Log a message that we are ignoring it.
     (if obfuscated?
-      (log/info (trs "Attempted to set Setting {0} to obfuscated value. Ignoring change." setting-name))
+      (log/infof "Attempted to set Setting %s to obfuscated value. Ignoring change." setting-name)
       (do
         (when (and deprecated (not (nil? new-value)))
-          (log/warn (trs "Setting {0} is deprecated as of Metabase {1} and may be removed in a future version."
-                         setting-name
-                         deprecated)))
+          (log/warnf "Setting %s is deprecated as of Metabase %s and may be removed in a future version."
+                     setting-name deprecated))
         (when (and
                (= :only (:user-local setting))
                (not (should-set-user-local-value? setting)))
-          (log/warn (trs "Setting {0} can only be set in a user-local way, but there are no *user-local-values*." setting-name)))
+          (log/warnf "Setting %s can only be set in a user-local way, but there are no *user-local-values*." setting-name))
         (if (should-set-user-local-value? setting)
           ;; If this is user-local and this is being set in the context of an API call, we don't want to update the
           ;; site-wide value or write or read from the cache
@@ -1336,7 +1335,7 @@
      :value          (try
                        (m/mapply user-facing-value setting options)
                        (catch Throwable e
-                         (log/error e (trs "Error fetching value of Setting"))))
+                         (log/error e "Error fetching value of Setting")))
      :is_env_setting from-env?
      :env_name       (env-var-name setting)
      :description    (str (description))
diff --git a/src/metabase/models/setting/cache.clj b/src/metabase/models/setting/cache.clj
index 390cbbcbcdbdf6980d5a7a2c37ca52ef0ee8eafa..c9ea9242cbc370ed5ce337ed47f20438fbe1baec 100644
--- a/src/metabase/models/setting/cache.clj
+++ b/src/metabase/models/setting/cache.clj
@@ -7,7 +7,6 @@
    [metabase.db :as mdb]
    [metabase.util :as u]
    [metabase.util.honey-sql-2 :as h2x]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2])
   (:import
@@ -71,7 +70,7 @@
 (defn update-settings-last-updated!
   "Update the value of `settings-last-updated` in the DB; if the row does not exist, insert one."
   []
-  (log/debug (trs "Updating value of settings-last-updated in DB..."))
+  (log/debug "Updating value of settings-last-updated in DB...")
   ;; for MySQL, cast(current_timestamp AS char); for H2 & Postgres, cast(current_timestamp AS text)
   (let [current-timestamp-as-string-honeysql (h2x/cast (if (= (mdb/db-type) :mysql) :char :text)
                                                        [:raw "current_timestamp"])]
@@ -86,8 +85,8 @@
           (t2/insert! (t2/table-name (t2/resolve-model 'Setting)) :key settings-last-updated-key, :value current-timestamp-as-string-honeysql)
           (catch java.sql.SQLException e
             ;; go ahead and log the Exception anyway on the off chance that it *wasn't* just a race condition issue
-            (log/error (trs "Error updating Settings last updated value: {0}"
-                            (with-out-str (jdbc/print-sql-exception-chain e))))))))
+            (log/errorf "Error updating Settings last updated value: %s"
+                        (with-out-str (jdbc/print-sql-exception-chain e)))))))
   ;; Now that we updated the value in the DB, go ahead and update our cached value as well, because we know about the
   ;; changes
   (swap! (cache*) assoc settings-last-updated-key (t2/select-one-fn :value 'Setting :key settings-last-updated-key)))
@@ -101,7 +100,7 @@
       will be no value until the first time a normal Setting is updated; thus if it is not yet set, we do not yet need
       to invalidate our cache.)"
   []
-  (log/debug (trs "Checking whether settings cache is out of date (requires DB call)..."))
+  (log/debug "Checking whether settings cache is out of date (requires DB call)...")
   (let [current-cache (cache)]
     (boolean
       (or
@@ -118,8 +117,7 @@
             (log/trace "last known Settings update: " (pr-str last-known-update))
             (log/trace "actual last Settings update:" (pr-str <>))
             (when <>
-              (log/info (u/format-color 'red
-                            (trs "Settings have been changed on another instance, and will be reloaded here."))))))))))
+              (log/info (u/format-color :red "Settings have been changed on another instance, and will be reloaded here.")))))))))
 
 (def ^:private ^:const cache-update-check-interval-ms
   "How often we should check whether the Settings cache is out of date (which requires a DB call)?"
@@ -136,7 +134,7 @@
 (defn restore-cache!
   "Populate cache with the latest hotness from the db"
   []
-  (log/debug (trs "Refreshing Settings cache..."))
+  (log/debug "Refreshing Settings cache...")
   (reset! (cache*) (t2/select-fn->fn :key :value 'Setting)))
 
 (defonce ^:private ^ReentrantLock restore-cache-lock (ReentrantLock.))
diff --git a/src/metabase/models/task_history.clj b/src/metabase/models/task_history.clj
index a4980a5bf6f5bc07d1ecee662bfd7f3d0d17c0cc..082d3da395ab02e7af65c3206ac241e64eb7a448 100644
--- a/src/metabase/models/task_history.clj
+++ b/src/metabase/models/task_history.clj
@@ -6,7 +6,6 @@
    [metabase.models.permissions :as perms]
    [metabase.public-settings.premium-features :as premium-features]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]
@@ -86,7 +85,7 @@
                                                     :ended_at   (t/instant end-time-ms)
                                                     :duration   duration-ms)))
       (catch Throwable e
-        (log/warn e (trs "Error saving task history"))))))
+        (log/warn e "Error saving task history")))))
 
 (mu/defn do-with-task-history
   "Impl for `with-task-history` macro; see documentation below."
diff --git a/src/metabase/models/user.clj b/src/metabase/models/user.clj
index b0024e60065a0214b73b0082d44f5c1beeb3c3c7..f5af32ccb8e4c544352d2bb2515e5abf53f874ca 100644
--- a/src/metabase/models/user.clj
+++ b/src/metabase/models/user.clj
@@ -118,15 +118,15 @@
   [{user-id :id, superuser? :is_superuser, :as user}]
   (u/prog1 user
     (let [current-version (:tag config/mb-version-info)]
-      (log/info (trs "Setting User {0}''s last_acknowledged_version to {1}, the current version" user-id current-version))
+      (log/infof "Setting User %s's last_acknowledged_version to %s, the current version" user-id current-version)
       ;; Can't use mw.session/with-current-user due to circular require
       (binding [api/*current-user-id*       user-id
                 setting/*user-local-values* (delay (atom (user-local-settings user)))]
         (setting/set! :last-acknowledged-version current-version)))
     ;; add the newly created user to the magic perms groups.
-    (log/info (trs "Adding User {0} to All Users permissions group..." user-id))
+    (log/infof "Adding User %s to All Users permissions group..." user-id)
     (when superuser?
-      (log/info (trs "Adding User {0} to All Users permissions group..." user-id)))
+      (log/infof "Adding User %s to All Users permissions group..." user-id))
     (let [groups (filter some? [(perms-group/all-users)
                                 (when superuser? (perms-group/admin))])]
       (binding [perms-group-membership/*allow-changing-all-users-group-members* true]
diff --git a/src/metabase/plugins.clj b/src/metabase/plugins.clj
index 604934558273265c319324c1ec09ac95f94cfd25..881b5f70aa60f77f3b2fc80bf115966badaf1788 100644
--- a/src/metabase/plugins.clj
+++ b/src/metabase/plugins.clj
@@ -38,11 +38,11 @@
        (catch Throwable e
          (log/warn
           e
-          (trs "Metabase cannot use the plugins directory {0}" filename)
+          (format "Metabase cannot use the plugins directory %s" filename)
           "\n"
-          (trs "Please make sure the directory exists and that Metabase has permission to write to it.")
-          (trs "You can change the directory Metabase uses for modules by setting the environment variable MB_PLUGINS_DIR.")
-          (trs "Falling back to a temporary directory for now."))
+          "Please make sure the directory exists and that Metabase has permission to write to it."
+          "You can change the directory Metabase uses for modules by setting the environment variable MB_PLUGINS_DIR."
+          "Falling back to a temporary directory for now.")
          ;; Check whether the fallback temporary directory is writable. If it's not, there's no way for us to
          ;; gracefully proceed here. Throw an Exception detailing the critical issues.
          (let [path (u.files/get-path (System/getProperty "java.io.tmpdir"))]
@@ -114,7 +114,7 @@
                             ;; if different JARs with `metabase` packages have different signing keys. Go ahead and
                             ;; ignore it but let people know they can get rid of it.
                             (log/warn
-                             (trs "spark-deps.jar is no longer needed by Metabase 0.32.0+. You can delete it from the plugins directory."))))]
+                             "spark-deps.jar is no longer needed by Metabase 0.32.0+. You can delete it from the plugins directory.")))]
     path))
 
 (when (or config/is-dev? config/is-test?)
@@ -149,7 +149,7 @@
     []
     ;; TODO - this should probably do an actual search in case we ever add any additional directories
     (doseq [manifest-path (driver-manifest-paths)]
-      (log/info (trs "Loading local plugin manifest at {0}" (str manifest-path)))
+      (log/infof "Loading local plugin manifest at %s" (str manifest-path))
       (load-local-plugin-manifest! manifest-path))))
 
 (defn- has-manifest? ^Boolean [^Path path]
@@ -165,10 +165,10 @@
     (try
       (init-plugin! path)
       (catch Throwable e
-        (log/error e (trs "Failied to initialize plugin {0}" (.getFileName path)))))))
+        (log/errorf e "Failied to initialize plugin %s" (.getFileName path))))))
 
 (defn- load! []
-  (log/info (trs "Loading plugins in {0}..." (str (plugins-dir))))
+  (log/infof "Loading plugins in %s..." (str (plugins-dir)))
   (extract-system-modules!)
   (let [paths (plugins-paths)]
     (init-plugins! paths))
diff --git a/src/metabase/plugins/dependencies.clj b/src/metabase/plugins/dependencies.clj
index c5a25db80374e4af6a40e8f1c3d39666a599ee73..b807f6f586f8d914ad70ab1cbf460b0548d39461 100644
--- a/src/metabase/plugins/dependencies.clj
+++ b/src/metabase/plugins/dependencies.clj
@@ -25,9 +25,8 @@
 
 (defmethod dependency-satisfied? :default [_ {{plugin-name :name} :info} dep]
   (log/error
-   (u/format-color 'red
-       (trs "Plugin {0} declares a dependency that Metabase does not understand: {1}" plugin-name dep))
-   (trs "Refer to the plugin manifest reference for a complete list of valid plugin dependencies:")
+   (u/format-color :red "Plugin %s declares a dependency that Metabase does not understand: %s" plugin-name dep)
+   "Refer to the plugin manifest reference for a complete list of valid plugin dependencies:"
    "https://github.com/metabase/metabase/wiki/Metabase-Plugin-Manifest-Reference")
   false)
 
diff --git a/src/metabase/plugins/init_steps.clj b/src/metabase/plugins/init_steps.clj
index 888785858f86950826f1a8b67f3f422e0a6acb5f..d46a1354f3d7fa4c6ae35e145a549835bd19b353 100644
--- a/src/metabase/plugins/init_steps.clj
+++ b/src/metabase/plugins/init_steps.clj
@@ -8,7 +8,6 @@
    [metabase.plugins.classloader :as classloader]
    [metabase.plugins.jdbc-proxy :as jdbc-proxy]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (defmulti ^:private do-init-step!
@@ -18,7 +17,7 @@
   (comp keyword :step))
 
 (defmethod do-init-step! :load-namespace [{nmspace :namespace}]
-  (log/debug (u/format-color 'blue (trs "Loading plugin namespace {0}..." nmspace)))
+  (log/debug (u/format-color 'blue "Loading plugin namespace %s..." nmspace))
   (classloader/require (symbol nmspace)))
 
 (defmethod do-init-step! :register-jdbc-driver [{class-name :class}]
diff --git a/src/metabase/plugins/initialize.clj b/src/metabase/plugins/initialize.clj
index a0a8b4d7b31eb1af52e4b8568caadc2f78d8ddcb..47cce73cb2d6bd2bab83eb1ed5377381b8ab169c 100644
--- a/src/metabase/plugins/initialize.clj
+++ b/src/metabase/plugins/initialize.clj
@@ -10,7 +10,6 @@
    [metabase.plugins.init-steps :as init-steps]
    [metabase.plugins.lazy-loaded-driver :as lazy-loaded-driver]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
@@ -36,8 +35,8 @@
     ;; getting it again
     (let [plugins-ready-to-init (deps/update-unsatisfied-deps! (swap! initialized-plugin-names conj plugin-name))]
       (when (seq plugins-ready-to-init)
-        (log/debug (u/format-color 'yellow (trs "Dependencies satisfied; these plugins will now be loaded: {0}"
-                                                (mapv (comp :name :info) plugins-ready-to-init)))))
+        (log/debug (u/format-color 'yellow (format "Dependencies satisfied; these plugins will now be loaded: %s"
+                                                   (mapv (comp :name :info) plugins-ready-to-init)))))
       (doseq [plugin-info plugins-ready-to-init]
         (init! plugin-info)))
     :ok))
diff --git a/src/metabase/plugins/jdbc_proxy.clj b/src/metabase/plugins/jdbc_proxy.clj
index 194844d77d770d57711a6aa4fed1afd5b817af97..1893f8cf3c829027007bc4d1da87ccea8f257b59 100644
--- a/src/metabase/plugins/jdbc_proxy.clj
+++ b/src/metabase/plugins/jdbc_proxy.clj
@@ -4,7 +4,6 @@
   (:require
    [metabase.plugins.classloader :as classloader]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [potemkin.types :as p.types]
    [pretty.core :refer [PrettyPrintable]])
@@ -61,15 +60,16 @@
     ;; some situations -- Oracle for example doesn't seem to behave properly when you do this. This mainly affects dev
     ;; which merges driver dependencies into the core project deps.
     (if loaded-by-system-classloader?
-      (log/debug (u/format-color 'cyan (trs "Not creating proxy JDBC driver for class {0} -- original driver was loaded by system ClassLoader"
-                                            class-name)))
+      (log/debug (u/format-color 'cyan
+                                 "Not creating proxy JDBC driver for class %s -- original driver was loaded by system ClassLoader"
+                                 class-name))
       (let [driver (proxy-driver (.newInstance klass))]
-        (log/debug (u/format-color 'blue (trs "Registering JDBC proxy driver for {0}..." class-name)))
+        (log/debug (u/format-color 'blue "Registering JDBC proxy driver for %s..." class-name))
         (DriverManager/registerDriver driver)
 
         ;; deregister the non-proxy version of the driver so it doesn't try to handle our URLs. Most JDBC drivers register
         ;; themseleves when the classes are loaded
         (doseq [driver (enumeration-seq (DriverManager/getDrivers))
                 :when  (instance? klass driver)]
-          (log/debug (u/format-color 'cyan (trs "Deregistering original JDBC driver {0}..." driver)))
+          (log/debug (u/format-color 'cyan "Deregistering original JDBC driver %s..." driver))
           (DriverManager/deregisterDriver driver))))))
diff --git a/src/metabase/plugins/lazy_loaded_driver.clj b/src/metabase/plugins/lazy_loaded_driver.clj
index 88d72fb81b66c861794d1ec34d199d344c0cb6b4..9e27edb894bd5d416b1d9e4ced572ec7f19c5961 100644
--- a/src/metabase/plugins/lazy_loaded_driver.clj
+++ b/src/metabase/plugins/lazy_loaded_driver.clj
@@ -79,8 +79,7 @@
     ;; about it
     (when (and (not abstract)
                (empty? connection-props))
-      (log/warn
-       (u/format-color 'red (trs "Warning: plugin manifest for {0} does not include connection properties" driver))))
+      (log/warn (u/format-color :red "Warning: plugin manifest for %s does not include connection properties" driver)))
     ;; ok, now add implementations for the so-called "non-trivial" driver multimethods
     (doseq [[^MultiFn multifn, f]
             {driver/initialize!           (make-initialize! driver add-to-classpath! init-steps)
@@ -91,5 +90,5 @@
       (when f
         (.addMethod multifn driver f)))
     ;; finally, register the Metabase driver
-    (log/debug (u/format-color 'magenta (trs "Registering lazy loading driver {0}..." driver)))
+    (log/debug (u/format-color :magenta "Registering lazy loading driver %s..." driver))
     (driver/register! driver, :parent (set (map keyword (u/one-or-many parent))), :abstract? abstract)))
diff --git a/src/metabase/public_settings.clj b/src/metabase/public_settings.clj
index 5d76f858c063369b7de49ecff6d35dbdf4e94509..5e9005a26d722926f6f7291fe5d3f40e9c383bb5 100644
--- a/src/metabase/public_settings.clj
+++ b/src/metabase/public_settings.clj
@@ -170,7 +170,7 @@
                 (try
                   (some-> (setting/get-value-of-type :string :site-url) normalize-site-url)
                   (catch clojure.lang.ExceptionInfo e
-                    (log/error e (trs "site-url is invalid; returning nil for now. Will be reset on next request.")))))
+                    (log/error e "site-url is invalid; returning nil for now. Will be reset on next request."))))
   :setter     (fn [new-value]
                 (let [new-value (some-> new-value normalize-site-url)
                       https?    (some-> new-value (str/starts-with?  "https:"))]
diff --git a/src/metabase/public_settings/premium_features.clj b/src/metabase/public_settings/premium_features.clj
index cc1ccfd4d7d8241b96ccf5950564bff5da56a0f5..71687458b264b1a4abfff047d52b3bb7b4df9a85 100644
--- a/src/metabase/public_settings/premium_features.clj
+++ b/src/metabase/public_settings/premium_features.clj
@@ -163,7 +163,7 @@
                  (catch Exception e1
                    ;; Unwrap exception from inside the future
                    (let [e1 (ex-cause e1)]
-                     (log/error e1 (trs "Error fetching token status from {0}:" token-check-url))
+                     (log/errorf e1 "Error fetching token status from %s:" token-check-url)
                      ;; Try the fallback URL, which was the default URL prior to 45.2
                      (try (fetch-token-and-parse-body token store-url site-uuid)
                           ;; if there was an error fetching the token from both the normal and fallback URLs, log the
@@ -171,7 +171,7 @@
                           ;; will get displayed in the Settings page in the admin panel so we do not want something
                           ;; complicated
                           (catch Exception e2
-                            (log/error (ex-cause e2) (trs "Error fetching token status from {0}:" store-url))
+                            (log/errorf (ex-cause e2) "Error fetching token status from %s:" store-url)
                             (let [body (u/ignore-exceptions (some-> (ex-data e1) :body (json/parse-string keyword)))]
                               (or
                                body
@@ -272,10 +272,10 @@
           (throw (ex-info (tru "Token format is invalid.")
                           {:status-code 400, :error-details "Token should be 64 hexadecimal characters."})))
         (valid-token->features new-value)
-        (log/info (trs "Token is valid.")))
+        (log/info "Token is valid."))
       (setting/set-value-of-type! :string :premium-embedding-token new-value)
       (catch Throwable e
-        (log/error e (trs "Error setting premium features token"))
+        (log/error e "Error setting premium features token")
         (throw (ex-info (.getMessage e) (merge
                                          {:message (.getMessage e), :status-code 400}
                                          (ex-data e)))))))) ; merge in error-details if present
@@ -283,8 +283,8 @@
 (let [cached-logger (memoize/ttl
                      ^{::memoize/args-fn (fn [[token _e]] [token])}
                      (fn [_token e]
-                       (log/error (trs "Error validating token") ":" (ex-message e))
-                       (log/debug e (trs "Error validating token")))
+                       (log/error "Error validating token:" (ex-message e))
+                       (log/debug e "Error validating token"))
                      ;; log every five minutes
                      :ttl/threshold (* 1000 60 5))]
   (mu/defn ^:dynamic *token-features* :- [:set ms/NonBlankString]
diff --git a/src/metabase/pulse.clj b/src/metabase/pulse.clj
index 51ed41aada22b72f365869ea7d6043d33292d4b6..995180423cbaeb436a942b8364388f1681cfd61b 100644
--- a/src/metabase/pulse.clj
+++ b/src/metabase/pulse.clj
@@ -86,7 +86,7 @@
          :result   result
          :type     :card}))
     (catch Throwable e
-      (log/warn e (trs "Error running query for Card {0}" card-or-id)))))
+      (log/warnf e "Error running query for Card %s" card-or-id))))
 
 (defn virtual-card-of-type?
   "Check if dashcard is a virtual with type `ttype`, if `true` returns the dashcard, else returns `nil`.
@@ -429,8 +429,8 @@
 
 (defmethod notification [:pulse :email]
   [{pulse-id :id, pulse-name :name, dashboard-id :dashboard_id, :as pulse} parts {:keys [recipients]}]
-  (log/debug (u/format-color 'cyan (trs "Sending Pulse ({0}: {1}) with {2} Cards via email"
-                                        pulse-id (pr-str pulse-name) (parts->cards-count parts))))
+  (log/debug (u/format-color :cyan "Sending Pulse (%s: %s) with %s Cards via email"
+                             pulse-id (pr-str pulse-name) (parts->cards-count parts)))
   (let [user-recipients     (filter (fn [recipient] (and (u/email? (:email recipient))
                                                          (some? (:id recipient)))) recipients)
         non-user-recipients (filter (fn [recipient] (and (u/email? (:email recipient))
@@ -449,8 +449,8 @@
   [{pulse-id :id, pulse-name :name, dashboard-id :dashboard_id, :as pulse}
    parts
    {{channel-id :channel} :details}]
-  (log/debug (u/format-color 'cyan (trs "Sending Pulse ({0}: {1}) with {2} Cards via Slack"
-                                        pulse-id (pr-str pulse-name) (parts->cards-count parts))))
+  (log/debug (u/format-color :cyan "Sending Pulse (%s: %s) with %s Cards via Slack"
+                             pulse-id (pr-str pulse-name) (parts->cards-count parts)))
   (let [dashboard (t2/select-one Dashboard :id dashboard-id)]
     {:channel-id  channel-id
      :attachments (remove nil?
@@ -460,7 +460,7 @@
 
 (defmethod notification [:alert :email]
   [{:keys [id] :as pulse} parts channel]
-  (log/debug (trs "Sending Alert ({0}: {1}) via email" id name))
+  (log/debugf "Sending Alert (%s: %s) via email" id name)
   (let [condition-kwd       (messages/pulse->alert-condition-kwd pulse)
         email-subject       (trs "Alert: {0} has {1}"
                                  (first-question-name pulse)
@@ -481,7 +481,7 @@
 
 (defmethod notification [:alert :slack]
   [pulse parts {{channel-id :channel} :details}]
-  (log/debug (u/format-color 'cyan (trs "Sending Alert ({0}: {1}) via Slack" (:id pulse) (:name pulse))))
+  (log/debug (u/format-color :cyan "Sending Alert (%s: %s) via Slack" (:id pulse) (:name pulse)))
   {:channel-id  channel-id
    :attachments (cons {:blocks [{:type "header"
                                  :text {:type "plain_text"
@@ -568,7 +568,7 @@
     (try
       (send-notification-retrying! notification)
       (catch Throwable e
-        (log/error e (trs "Error sending notification!"))))))
+        (log/error e "Error sending notification!")))))
 
 (defn send-pulse!
   "Execute and Send a `Pulse`, optionally specifying the specific `PulseChannels`.  This includes running each
diff --git a/src/metabase/pulse/render.clj b/src/metabase/pulse/render.clj
index 1caab59520ef31c44d9a93e4c8bc08a38f2829e0..115504831494e8c7991f476924b8078a527d9ce3 100644
--- a/src/metabase/pulse/render.clj
+++ b/src/metabase/pulse/render.clj
@@ -9,7 +9,7 @@
    [metabase.pulse.render.png :as png]
    [metabase.pulse.render.style :as style]
    [metabase.shared.models.visualization-settings :as mb.viz]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.urls :as urls]))
@@ -140,25 +140,25 @@
                          (when (is-attached? card)
                            :attached)
                          :unknown)]
-      (log/debug (trs "Rendering pulse card with chart-type {0} and render-type {1}" chart-type render-type))
+      (log/debugf "Rendering pulse card with chart-type %s and render-type %s" chart-type render-type)
       (body/render chart-type render-type timezone-id card dashcard data))
     (catch Throwable e
       (if (:card-error (ex-data e))
         (do
-          (log/error e (trs "Pulse card query error"))
+          (log/error e "Pulse card query error")
           (body/render :card-error nil nil nil nil nil))
         (do
-          (log/error e (trs "Pulse card render error"))
+          (log/error e "Pulse card render error")
           (body/render :render-error nil nil nil nil nil))))))
 
 
 (mu/defn render-pulse-card :- formatter/RenderedPulseCard
   "Render a single `card` for a `Pulse` to Hiccup HTML. `result` is the QP results. Returns a map with keys
 
-- attachments
-- content (a hiccup form suitable for rendering on rich clients or rendering into an image)
-- render/text : raw text suitable for substituting on clients when text is preferable. (Currently slack uses this for
-  scalar results where text is preferable to an image of a div of a single result."
+  - attachments
+  - content (a hiccup form suitable for rendering on rich clients or rendering into an image)
+  - render/text : raw text suitable for substituting on clients when text is preferable. (Currently slack uses this for
+    scalar results where text is preferable to an image of a div of a single result."
   [render-type
    timezone-id :- [:maybe :string]
    card
diff --git a/src/metabase/pulse/render/png.clj b/src/metabase/pulse/render/png.clj
index 5815643eb167f8d7bcc9cc2ee797e3f7ead3c57e..fcaf82ee2ed536a70dbf4772d66051720ccb08df 100644
--- a/src/metabase/pulse/render/png.clj
+++ b/src/metabase/pulse/render/png.clj
@@ -10,7 +10,6 @@
    [hiccup.core :refer [html]]
    [metabase.formatter :as formatter]
    [metabase.pulse.render.style :as style]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu])
   (:import
@@ -89,5 +88,5 @@
             (write-image! "png" os))
         (.toByteArray os)))
     (catch Throwable e
-      (log/error e (trs "Error rendering Pulse"))
+      (log/error e "Error rendering Pulse")
       (throw e))))
diff --git a/src/metabase/pulse/util.clj b/src/metabase/pulse/util.clj
index b44e56e0b3a5ecabe7d9a28a1122cb1487b95979..2c0ef1d05660c42b1c3472cf66429cda6f96169a 100644
--- a/src/metabase/pulse/util.clj
+++ b/src/metabase/pulse/util.clj
@@ -6,7 +6,6 @@
    [metabase.query-processor.middleware.permissions :as qp.perms]
    [metabase.server.middleware.session :as mw.session]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2]))
 
@@ -43,7 +42,7 @@
           {:card   card
            :result result}))
       (catch Throwable e
-        (log/warn e (trs "Error running query for Card {0}" card-id))))))
+        (log/warnf e "Error running query for Card %s" card-id)))))
 
 (defn execute-multi-card
   "Multi series card is composed of multiple cards, all of which need to be executed.
diff --git a/src/metabase/query_processor/middleware/add_implicit_clauses.clj b/src/metabase/query_processor/middleware/add_implicit_clauses.clj
index 31f15eec69d5bc5c7c052c05dd40874e71c50d1c..e1735108a3d9480d2d62ec48d53657259f7a0ec8 100644
--- a/src/metabase/query_processor/middleware/add_implicit_clauses.clj
+++ b/src/metabase/query_processor/middleware/add_implicit_clauses.clj
@@ -10,7 +10,7 @@
    [metabase.query-processor.error-type :as qp.error-type]
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]))
@@ -82,9 +82,9 @@
              (qp.store/initialized?))
     ;; by 'caching' this result, this log message will only be shown once for a given QP run.
     (qp.store/cached [::should-add-implicit-fields-warning]
-      (log/warn (str (trs "Warning: cannot determine fields for an explicit `source-query` unless you also include `source-metadata`.")
-                     \newline
-                     (trs "Query: {0}" (u/pprint-to-str source-query))))))
+      (log/warn (str "Warning: cannot determine fields for an explicit `source-query` unless you also include"
+                     " `source-metadata`.\n"
+                     (format "Query: %s" (u/pprint-to-str source-query))))))
   ;; Determine whether we can add the implicit `:fields`
   (and (or source-table
            (and source-query (seq source-metadata)))
diff --git a/src/metabase/query_processor/middleware/add_source_metadata.clj b/src/metabase/query_processor/middleware/add_source_metadata.clj
index 0c7c791bea09ec2882d0f1c5023872188c38abcd..4548769aee58e1e9155907373cd9d3fbc193e7ce 100644
--- a/src/metabase/query_processor/middleware/add_source_metadata.clj
+++ b/src/metabase/query_processor/middleware/add_source_metadata.clj
@@ -7,7 +7,6 @@
    [metabase.lib.util.match :as lib.util.match]
    [metabase.query-processor.interface :as qp.i]
    [metabase.query-processor.store :as qp.store]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
@@ -40,9 +39,8 @@
     ;; a native source query
     (do
       (when-not qp.i/*disable-qp-logging*
-        (log/warn
-         (trs "Cannot infer `:source-metadata` for source query with native source query without source metadata.")
-         {:source-query source-query}))
+        (log/warn "Cannot infer `:source-metadata` for source query with native source query without source metadata."
+                  {:source-query source-query}))
       nil)))
 
 (mu/defn mbql-source-query->metadata :- [:maybe [:sequential mbql.s/SourceQueryMetadata]]
@@ -60,7 +58,7 @@
         (select-keys col [:name :id :table_id :display_name :base_type :effective_type :coercion_strategy
                           :semantic_type :unit :fingerprint :settings :source_alias :field_ref :nfc_path :parent_id])))
     (catch Throwable e
-      (log/error e (str (trs "Error determining expected columns for query: {0}" (ex-message e))))
+      (log/errorf e "Error determining expected columns for query: %s" (ex-message e))
       nil)))
 
 (mu/defn ^:private add-source-metadata :- [:map
diff --git a/src/metabase/query_processor/middleware/cache.clj b/src/metabase/query_processor/middleware/cache.clj
index 980eb068868725d5208e778ef826edd5c169e95a..e2797b190123f04316e922663f841478d579c5cd 100644
--- a/src/metabase/query_processor/middleware/cache.clj
+++ b/src/metabase/query_processor/middleware/cache.clj
@@ -169,9 +169,9 @@
                             (i/short-hex-hash query-hash) (pr-str (:cache-version metadata)))
                 (when (and (= (:cache-version metadata) cache-version)
                            reducible-rows)
-                  (log/tracef "Reducing cached rows...")
+                  (log/trace "Reducing cached rows...")
                   (let [result (qp.pipeline/*reduce* (cached-results-rff rff query-hash) metadata reducible-rows)]
-                    (log/tracef "All cached rows reduced")
+                    (log/trace "All cached rows reduced")
                     [::ok result])))
               (log/debugf "Not found cached results for hash '%s'" (i/short-hex-hash query-hash)))))
         [::miss nil])
diff --git a/src/metabase/query_processor/middleware/cache/impl.clj b/src/metabase/query_processor/middleware/cache/impl.clj
index 3ab555bfce6f60d7e98a2baec1e67526a97cd7a9..ca31ebd8ea941972de1a14cd26a70cb66f3b4c77 100644
--- a/src/metabase/query_processor/middleware/cache/impl.clj
+++ b/src/metabase/query_processor/middleware/cache/impl.clj
@@ -18,7 +18,7 @@
   (let [byte-count  (atom 0)
         check-total (fn [current-total]
                       (when (> current-total max-bytes)
-                        (log/info (trs "Results are too large to cache.") (u/emoji "😫"))
+                        (log/info "Results are too large to cache." (u/emoji "😫"))
                         (throw (ex-info (trs "Results are too large to cache.") {:type ::max-bytes}))))]
     (proxy [FilterOutputStream] [os]
       (write
diff --git a/src/metabase/query_processor/middleware/cache_backend/db.clj b/src/metabase/query_processor/middleware/cache_backend/db.clj
index 42c330a5d81da3eabcbf93ccbc052d81d1486fbb..3ecc60ab52b4573442543c4c4aeb2787a532ed9a 100644
--- a/src/metabase/query_processor/middleware/cache_backend/db.clj
+++ b/src/metabase/query_processor/middleware/cache_backend/db.clj
@@ -8,7 +8,6 @@
    [metabase.public-settings.premium-features :refer [defenterprise]]
    [metabase.query-processor.middleware.cache-backend.interface :as i]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.connection :as t2.connection]
    #_{:clj-kondo/ignore [:discouraged-namespace]}
@@ -94,7 +93,7 @@
   "Delete any cache entries that are older than the global max age `max-cache-entry-age-seconds` (currently 3 months)."
   [max-age-seconds]
   {:pre [(number? max-age-seconds)]}
-  (log/tracef "Purging old cache entries.")
+  (log/trace "Purging old cache entries.")
   (try
     (t2/delete! (t2/table-name QueryCache)
                 :updated_at [:<= (seconds-ago max-age-seconds)])
@@ -116,7 +115,7 @@
                                                :query_hash query-hash
                                                :results    results)))
     (catch Throwable e
-      (log/error e (trs "Error saving query results to cache."))))
+      (log/error e "Error saving query results to cache.")))
   nil)
 
 (defmethod i/cache-backend :db
diff --git a/src/metabase/query_processor/middleware/catch_exceptions.clj b/src/metabase/query_processor/middleware/catch_exceptions.clj
index 8bf8412ec144391f6ebb9e322722a526c57701bf..4529d3710f12f59215c47c4732b3005ff0a3fc33 100644
--- a/src/metabase/query_processor/middleware/catch_exceptions.clj
+++ b/src/metabase/query_processor/middleware/catch_exceptions.clj
@@ -129,11 +129,9 @@
           (catch Throwable e
             ;; format the Exception and return it
             (let [formatted-exception (format-exception* query e @extra-info)]
-              (log/error (str (trs "Error processing query: {0}"
-                                   (or (:error formatted-exception)
-                                       ;; log in server locale, respond in user locale
-                                       (trs "Error running query")))
-                              "\n" (u/pprint-to-str formatted-exception)))
+              (log/errorf "Error processing query: %s\n%s"
+                          (or (:error formatted-exception) "Error running query")
+                          (u/pprint-to-str formatted-exception))
               ;; ensure always a message on the error otherwise FE thinks query was successful. (#23258, #23281)
               (let [result (update formatted-exception
                                    :error (fnil identity (trs "Error running query")))]
diff --git a/src/metabase/query_processor/middleware/expand_macros.clj b/src/metabase/query_processor/middleware/expand_macros.clj
index a65c950b39c6323fad082f209e254bd9b7445de3..c21db80d5b8904b695b0407629af718bb893e8bb 100644
--- a/src/metabase/query_processor/middleware/expand_macros.clj
+++ b/src/metabase/query_processor/middleware/expand_macros.clj
@@ -190,5 +190,5 @@
      (if-not (= query' query)
        (recur query' (inc recursion-depth))
        (do
-         (log/tracef "No more legacy Metrics/Segments to expand.")
+         (log/trace "No more legacy Metrics/Segments to expand.")
          query')))))
diff --git a/src/metabase/query_processor/middleware/fetch_source_query_legacy.clj b/src/metabase/query_processor/middleware/fetch_source_query_legacy.clj
index 2c037371c74930b268a113b1094cff27bfd02d29..4bbe2e599d937ae0b45f40053be999989b9e6b34 100644
--- a/src/metabase/query_processor/middleware/fetch_source_query_legacy.clj
+++ b/src/metabase/query_processor/middleware/fetch_source_query_legacy.clj
@@ -13,7 +13,7 @@
    [metabase.query-processor.store :as qp.store]
    [metabase.query-processor.util.persisted-cache :as qp.persisted]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
@@ -68,14 +68,12 @@
          persisted?     (qp.persisted/can-substitute? card persisted-info)
          source-query   (source-query card)]
      (when (and persisted? log?)
-       (log/info (trs "Found substitute cached query for card {0} from {1}.{2}"
-                      card-id
-                      (ddl.i/schema-name {:id database-id} (public-settings/site-uuid))
-                      (:table-name persisted-info))))
+       (log/infof "Found substitute cached query for card %s from %s.%s"
+                  card-id
+                  (ddl.i/schema-name {:id database-id} (public-settings/site-uuid))
+                  (:table-name persisted-info)))
      ;; log the query at this point, it's useful for some purposes
-     (log/debug (trs "Fetched source query from Card {0}:" card-id)
-                "\n"
-                (u/pprint-to-str 'yellow source-query))
+     (log/debugf "Fetched source query from Card %s:\n%s" card-id (u/pprint-to-str 'yellow source-query))
      (cond-> {:source-query    (cond-> source-query
                                  ;; This will be applied, if still appropriate, by the peristence middleware
                                  persisted?
diff --git a/src/metabase/query_processor/middleware/fix_bad_references.clj b/src/metabase/query_processor/middleware/fix_bad_references.clj
index 08f6f35b98eb1e0b8581c9226524e0db102dc751..063344424fd22973022632c1a7d0d25d69ae8398 100644
--- a/src/metabase/query_processor/middleware/fix_bad_references.clj
+++ b/src/metabase/query_processor/middleware/fix_bad_references.clj
@@ -5,7 +5,6 @@
    [metabase.lib.util.match :as lib.util.match]
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (defn- find-source-table [{:keys [source-table source-query]}]
@@ -57,16 +56,16 @@
       (opts :guard (complement :join-alias))]
      (let [{:keys [table-id], :as field} (lib.metadata/field (qp.store/metadata-provider) id)
            {join-alias :alias}           (find-join-against-table inner-query table-id)]
-       (log/warn (u/colorize 'yellow (str (trs "Bad :field clause {0} for field {1} at {2}: clause should have a :join-alias."
-                                               (pr-str &match)
-                                               (pr-str (format "%s.%s"
-                                                               (:name (table table-id))
-                                                               (:name field)))
-                                               (pr-str &parents))
-                                          " "
-                                          (if join-alias
-                                            (trs "Guessing join {0}" (pr-str join-alias))
-                                            (trs "Unable to infer an appropriate join. Query may not work as expected.")))))
+       (log/warn (u/colorize :yellow (str
+                                      (format
+                                       "Bad :field clause %s for field %s at %s: clause should have a :join-alias."
+                                       (pr-str &match)
+                                       (pr-str (format "%s.%s" (:name (table table-id)) (:name field)))
+                                       (pr-str &parents))
+                                      " "
+                                      (if join-alias
+                                        (format "Guessing join %s" (pr-str join-alias))
+                                        "Unable to infer an appropriate join. Query may not work as expected."))))
        (*bad-field-reference-fn* &match)
        (if join-alias
          [:field id (assoc opts :join-alias join-alias)]
diff --git a/src/metabase/query_processor/middleware/format_rows.clj b/src/metabase/query_processor/middleware/format_rows.clj
index bc8abfb46a5e77e83d6ab7314f1925bd2df91a7b..9fbd792e17bb50bac3682d689846f24dfaf9cb5b 100644
--- a/src/metabase/query_processor/middleware/format_rows.clj
+++ b/src/metabase/query_processor/middleware/format_rows.clj
@@ -5,7 +5,6 @@
    [java-time.api :as t]
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [potemkin.types :as p.types])
   (:import
@@ -57,7 +56,7 @@
 
 (defn- format-rows-xform [rf metadata]
   {:pre [(fn? rf)]}
-  (log/debug (tru "Formatting rows with results timezone ID {0}" (qp.timezone/results-timezone-id)))
+  (log/debugf "Formatting rows with results timezone ID %s" (qp.timezone/results-timezone-id))
   (let [timezone-id  (t/zone-id (qp.timezone/results-timezone-id))
         ;; a column will have `converted_timezone` metadata if it is the result of `convert-timezone` expression
         ;; in that case, we'll format the results with the target timezone.
diff --git a/src/metabase/query_processor/middleware/optimize_temporal_filters.clj b/src/metabase/query_processor/middleware/optimize_temporal_filters.clj
index a56a493cc534abae6fc772642e7678265649bbcd..4f79c9907e9f6268ce60c920fd846c3ea99509c9 100644
--- a/src/metabase/query_processor/middleware/optimize_temporal_filters.clj
+++ b/src/metabase/query_processor/middleware/optimize_temporal_filters.clj
@@ -9,7 +9,6 @@
    [metabase.query-processor.store :as qp.store]
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.malli.schema :as ms]))
@@ -200,7 +199,7 @@
               ;; if for some reason `optimize-filter` doesn't return an optimized filter clause, log and error and use
               ;; the original. `can-optimize-filter?` shouldn't have said we could optimize this filter in the first
               ;; place
-              (log/error (trs "Error optimizing temporal filter clause") (pr-str &match)))))
+              (log/error "Error optimizing temporal filter clause" (pr-str &match)))))
         &match)))
 
 (defn optimize-temporal-filters
diff --git a/src/metabase/query_processor/middleware/process_userland_query.clj b/src/metabase/query_processor/middleware/process_userland_query.clj
index 2619fdc78c2b856793b7f41495d32c8f65011f4d..b990afd6af77ebf20097c2a26eb50ed3ad8f9a30 100644
--- a/src/metabase/query_processor/middleware/process_userland_query.clj
+++ b/src/metabase/query_processor/middleware/process_userland_query.clj
@@ -14,7 +14,6 @@
     :refer [QueryExecution]]
    [metabase.query-processor.schema :as qp.schema]
    [metabase.query-processor.util :as qp.util]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    #_{:clj-kondo/ignore [:discouraged-namespace]}
@@ -62,7 +61,7 @@
                                                            (try
                                                              (save-query-execution!* execution-info)
                                                              (catch Throwable e
-                                                               (log/error e (trs "Error saving query execution info"))))))))
+                                                               (log/error e "Error saving query execution info")))))))
 
 (defn- save-successful-query-execution! [cache-details is-sandboxed? query-execution result-rows]
   (let [qe-map (assoc query-execution
diff --git a/src/metabase/query_processor/middleware/results_metadata.clj b/src/metabase/query_processor/middleware/results_metadata.clj
index e7a6f2ee93d608eae7050ad770489f054603c7ae..92a32ccc040853adc9b1c4c4657182dc23b69951 100644
--- a/src/metabase/query_processor/middleware/results_metadata.clj
+++ b/src/metabase/query_processor/middleware/results_metadata.clj
@@ -9,7 +9,6 @@
    [metabase.query-processor.schema :as qp.schema]
    [metabase.query-processor.store :as qp.store]
    [metabase.sync.analyze.query-results :as qr]
-   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    #_{:clj-kondo/ignore [:discouraged-namespace]}
@@ -40,7 +39,7 @@
     ;; if for some reason we weren't able to record results metadata for this query then just proceed as normal
     ;; rather than failing the entire query
     (catch Throwable e
-      (log/error e (tru "Error recording results metadata for query")))))
+      (log/error e "Error recording results metadata for query"))))
 
 (defn- merge-final-column-metadata
   "Because insights are generated by reducing functions, they start working before the entire query metadata is in its
diff --git a/src/metabase/query_processor/pipeline.clj b/src/metabase/query_processor/pipeline.clj
index 82fb3a36cb53fc560a46cbfed63bce392885167f..585764a172ff7578f20865d589b04262dbe28321 100644
--- a/src/metabase/query_processor/pipeline.clj
+++ b/src/metabase/query_processor/pipeline.clj
@@ -91,7 +91,7 @@
           (when-not (interrupted-exception? e)
             (throw e))
           ;; ok, at this point we know it's an InterruptedException.
-          (log/tracef e "Caught InterruptedException when executing query, this means the query was canceled. Ignoring exception.")
+          (log/trace e "Caught InterruptedException when executing query, this means the query was canceled. Ignoring exception.")
           ;; just to be extra safe and sure that the canceled chan has gotten a message. It's a promise channel so
           ;; duplicate messages don't matter
           (some-> *canceled-chan* (a/>!! ::cancel))
diff --git a/src/metabase/query_processor/pivot.clj b/src/metabase/query_processor/pivot.clj
index ee0d4ea57eb15f20002f4108f493ba507fa5de1f..7b98da18f4e072ea0f9bb8423733c22874d57e3d 100644
--- a/src/metabase/query_processor/pivot.clj
+++ b/src/metabase/query_processor/pivot.clj
@@ -15,7 +15,7 @@
    [metabase.query-processor.schema :as qp.schema]
    [metabase.query-processor.setup :as qp.setup]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs tru]]
+   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
@@ -177,7 +177,7 @@
                       (seq info) (qp/userland-query info))]
           (qp/process-query query rff))
         (catch Throwable e
-          (log/error e (trs "Error processing additional pivot table query"))
+          (log/error e "Error processing additional pivot table query")
           (throw e))))))
 
 (mu/defn ^:private process-queries-append-results
diff --git a/src/metabase/query_processor/streaming.clj b/src/metabase/query_processor/streaming.clj
index 543a405d45b77a599b6a59f6885f674b8a59de7f..9881a19e63038867356a896aa49d63a391069cf6 100644
--- a/src/metabase/query_processor/streaming.clj
+++ b/src/metabase/query_processor/streaming.clj
@@ -117,7 +117,7 @@
           row-count                   (volatile! 0)]
       (fn
         ([]
-         (log/tracef "Writing initial metadata to results writer.")
+         (log/trace "Writing initial metadata to results writer.")
          (qp.si/begin! results-writer
                        {:data (assoc initial-metadata :ordered-cols ordered-cols)}
                        viz-settings')
@@ -129,7 +129,7 @@
                 :status :completed))
 
         ([metadata row]
-         (log/tracef "Writing one row to results writer.")
+         (log/trace "Writing one row to results writer.")
          (qp.si/write-row! results-writer row (dec (vswap! row-count inc)) ordered-cols viz-settings')
          metadata)))))
 
diff --git a/src/metabase/query_processor/timezone.clj b/src/metabase/query_processor/timezone.clj
index 5792bf318ae1f36084f3d6b38933b7adc5f5916b..cd66036fc25f7aa1f24f9b5ce155b17c7360c7e7 100644
--- a/src/metabase/query_processor/timezone.clj
+++ b/src/metabase/query_processor/timezone.clj
@@ -6,7 +6,6 @@
    [metabase.driver :as driver]
    [metabase.lib.metadata :as lib.metadata]
    [metabase.query-processor.store :as qp.store]
-   [metabase.util.i18n :refer [tru]]
    [metabase.util.log :as log])
   (:import
    (java.time ZonedDateTime)))
@@ -27,7 +26,7 @@
       (t/zone-id timezone-id)
       timezone-id
       (catch Throwable _
-        (log/warn (tru "Invalid timezone ID ''{0}''" timezone-id))
+        (log/warnf "Invalid timezone ID '%s'" timezone-id)
         nil))))
 
 (defn- report-timezone-id* []
diff --git a/src/metabase/sample_data.clj b/src/metabase/sample_data.clj
index 4a718c92e0e4ee11061b30938ef03d0cfe671be7..7d4c7b141911b684f4823dcfccbc3aee8c0b3efa 100644
--- a/src/metabase/sample_data.clj
+++ b/src/metabase/sample_data.clj
@@ -60,9 +60,9 @@
        (do
          ;; If the plugins directory is a temp directory, fall back to reading the DB directly from the JAR until a
          ;; working plugins directory is available. (We want to ensure the sample DB is in a stable location.)
-         (log/warn (trs (str "Sample database could not be extracted to the plugins directory,"
-                             "which may result in slow startup times. "
-                             "Please set MB_PLUGINS_DIR to a writable directory and restart Metabase.")))
+         (log/warn (str "Sample database could not be extracted to the plugins directory,"
+                        "which may result in slow startup times. "
+                        "Please set MB_PLUGINS_DIR to a writable directory and restart Metabase."))
          (jar-db-details resource)))}))
 
 (defn add-sample-database!
@@ -70,7 +70,7 @@
   []
   (when-not (t2/exists? Database :is_sample true)
     (try
-      (log/info (trs "Loading sample database"))
+      (log/info "Loading sample database")
       (let [details (try-to-extract-sample-database!)]
         (log/debug "Syncing Sample Database...")
         (sync/sync-database! (first (t2/insert-returning-instances! Database
@@ -80,7 +80,7 @@
                                                                     :is_sample true))))
       (log/debug "Finished adding Sample Database.")
       (catch Throwable e
-        (log/error e (trs "Failed to load sample database"))))))
+        (log/error e "Failed to load sample database")))))
 
 (defn update-sample-database-if-needed!
   "Update the path to the sample database DB if it exists in case the JAR has moved."
diff --git a/src/metabase/server.clj b/src/metabase/server.clj
index 273625f316dff8c94b60aeb3ee9c1694e75119ed..8eae7e62dee4ed1e867ec003205ac688b7cf3104 100644
--- a/src/metabase/server.clj
+++ b/src/metabase/server.clj
@@ -7,7 +7,6 @@
    [metabase.config :as config]
    [metabase.server.protocols :as server.protocols]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [ring.adapter.jetty :as ring-jetty]
    [ring.util.jakarta.servlet :as servlet])
@@ -68,11 +67,11 @@
                                     (.setTimeout timeout))
             request-map           (servlet/build-request-map request)
             raise                 (fn raise [^Throwable e]
-                                    (log/error e (trs "Unexpected exception in endpoint"))
+                                    (log/error e "Unexpected exception in endpoint")
                                     (try
                                       (.sendError response 500 (.getMessage e))
                                       (catch Throwable e
-                                        (log/error e (trs "Unexpected exception writing error response"))))
+                                        (log/error e "Unexpected exception writing error response")))
                                     (.complete context))]
         (try
           (handler
@@ -85,7 +84,7 @@
                                                              :response-map  response-map}))
            raise)
           (catch Throwable e
-            (log/error e (trs "Unexpected Exception in API request handler"))
+            (log/error e "Unexpected Exception in API request handler")
             (raise e))
           (finally
             (.setHandled base-request true)))))))
@@ -126,6 +125,6 @@
   []
   (let [[^Server old-server] (reset-vals! instance* nil)]
     (when old-server
-      (log/info (trs "Shutting Down Embedded Jetty Webserver"))
+      (log/info "Shutting Down Embedded Jetty Webserver")
       (.stop old-server)
       :stopped)))
diff --git a/src/metabase/server/middleware/exceptions.clj b/src/metabase/server/middleware/exceptions.clj
index d4b303f6f0a0e04263f0f2449e9d007717aed98e..711cdb4602904e879cad5095f21b88cd02dae280 100644
--- a/src/metabase/server/middleware/exceptions.clj
+++ b/src/metabase/server/middleware/exceptions.clj
@@ -4,7 +4,7 @@
    [clojure.java.jdbc :as jdbc]
    [clojure.string :as str]
    [metabase.server.middleware.security :as mw.security]
-   [metabase.util.i18n :refer [deferred-tru trs]]
+   [metabase.util.i18n :refer [deferred-tru]]
    [metabase.util.log :as log])
   (:import
    (java.sql SQLException)
@@ -20,7 +20,7 @@
   [handler]
   (fn [request respond _raise]
     (let [raise (fn [e]
-                  (log/warn e (trs "Exception in API call"))
+                  (log/warn e "Exception in API call")
                   (if (= 404 (:status-code (ex-data e)))
                     (respond {:status 404, :body (deferred-tru "Not found.")})
                     (respond {:status 400, :body (deferred-tru "An error occurred.")})))]
@@ -40,7 +40,7 @@
       (try
         (handler request respond raise)
         (catch Throwable e
-          (log/error e (trs "Exception in API call"))
+          (log/error e "Exception in API call")
           (raise e))))))
 
 (defmulti api-exception-response
@@ -85,7 +85,7 @@
 
 (defmethod api-exception-response EofException
   [_e]
-  (log/info (trs "Request canceled before finishing."))
+  (log/info "Request canceled before finishing.")
   {:status-code 204, :body nil, :headers (mw.security/security-headers)})
 
 (defn catch-api-exceptions
diff --git a/src/metabase/server/middleware/log.clj b/src/metabase/server/middleware/log.clj
index 8d2904e13aed139cf163237e3f30e52301640b12..72e60d0c367fedade7cd1bd8408076d2c6605e5e 100644
--- a/src/metabase/server/middleware/log.clj
+++ b/src/metabase/server/middleware/log.clj
@@ -150,7 +150,7 @@
                 log-options)]
       (log-fn (u/format-color color (format-info info opts))))
     (catch Throwable e
-      (log/error e (trs "Error logging API request")))))
+      (log/error e "Error logging API request"))))
 
 
 ;;; +----------------------------------------------------------------------------------------------------------------+
diff --git a/src/metabase/server/middleware/misc.clj b/src/metabase/server/middleware/misc.clj
index 0bd79f890e3ac7e81f3a4fbcc22e37723987c5f2..9082c9086aa88f97249b904e4a1afa902994737c 100644
--- a/src/metabase/server/middleware/misc.clj
+++ b/src/metabase/server/middleware/misc.clj
@@ -6,7 +6,6 @@
    [metabase.db :as mdb]
    [metabase.public-settings :as public-settings]
    [metabase.server.request.util :as req.util]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (clojure.core.async.impl.channels ManyToManyChannel)
@@ -47,11 +46,11 @@
              (not= uri "/api/health")
              (or (nil? user-agent) ((complement str/includes?) user-agent "HealthChecker")))
     (when-let [site-url (or origin x-forwarded-host host)]
-      (log/info (trs "Setting Metabase site URL to {0}" site-url))
+      (log/infof "Setting Metabase site URL to %s" site-url)
       (try
         (public-settings/site-url! site-url)
         (catch Throwable e
-          (log/warn e (trs "Failed to set site-url")))))))
+          (log/warn e "Failed to set site-url"))))))
 
 (defn maybe-set-site-url
   "Middleware to set the `site-url` setting on the initial setup request"
diff --git a/src/metabase/server/middleware/session.clj b/src/metabase/server/middleware/session.clj
index 250cd468aa0df1e248a0e6acc9d8162eceb1330e..9c2782cd1c6613e56f8dab58b4660fd8eb6e2e89 100644
--- a/src/metabase/server/middleware/session.clj
+++ b/src/metabase/server/middleware/session.clj
@@ -37,7 +37,7 @@
    [metabase.public-settings.premium-features :as premium-features]
    [metabase.server.request.util :as req.util]
    [metabase.util :as u]
-   [metabase.util.i18n :as i18n :refer [deferred-trs deferred-tru trs tru]]
+   [metabase.util.i18n :as i18n :refer [deferred-tru tru]]
    [metabase.util.log :as log]
    [metabase.util.malli :as mu]
    [metabase.util.password :as u.password]
@@ -197,9 +197,9 @@
                           {:max-age (* 60 (config/config-int :max-session-age))}))]
     (when (and (= (session-cookie-samesite) :none) (not (req.util/https? request)))
       (log/warn
-       (str (deferred-trs "Session cookie's SameSite is configured to \"None\", but site is served over an insecure connection. Some browsers will reject cookies under these conditions.")
-            " "
-            "https://www.chromestatus.com/feature/5633521622188032")))
+       (str "Session cookie's SameSite is configured to \"None\", but site is served over an insecure connection."
+            " Some browsers will reject cookies under these conditions."
+            " https://www.chromestatus.com/feature/5633521622188032")))
     (-> response
         wrap-body-if-needed
         (cond-> (= session-type :full-app-embed)
@@ -497,15 +497,15 @@
              (let [value (setting/get-value-of-type :json :session-timeout)]
                (if-let [error-key (check-session-timeout value)]
                  (do (log/warn (case error-key
-                                 :amount-must-be-positive            (trs "Session timeout amount must be positive.")
-                                 :amount-must-be-less-than-100-years (trs "Session timeout must be less than 100 years.")))
+                                 :amount-must-be-positive            "Session timeout amount must be positive."
+                                 :amount-must-be-less-than-100-years "Session timeout must be less than 100 years."))
                      nil)
                  value)))
   :setter  (fn [new-value]
              (when-let [error-key (check-session-timeout new-value)]
                (throw (ex-info (case error-key
-                                 :amount-must-be-positive            (tru "Session timeout amount must be positive.")
-                                 :amount-must-be-less-than-100-years (tru "Session timeout must be less than 100 years."))
+                                 :amount-must-be-positive            "Session timeout amount must be positive."
+                                 :amount-must-be-less-than-100-years "Session timeout must be less than 100 years.")
                                {:status-code 400})))
              (setting/set-value-of-type! :json :session-timeout new-value)))
 
diff --git a/src/metabase/server/request/util.clj b/src/metabase/server/request/util.clj
index 4b718bde906e3bff7f46b3c4176ebd05a8f68fde..127548b611d6a4ad8f7fa87aa220bf19219af1ef 100644
--- a/src/metabase/server/request/util.clj
+++ b/src/metabase/server/request/util.clj
@@ -101,13 +101,13 @@
   "Information about the device that made this request, as recorded by the `LoginHistory` table."
   [{{:strs [user-agent]} :headers, :keys [browser-id], :as request}]
   (let [id          (or browser-id
-                        (log/warn (trs "Login request is missing device ID information")))
+                        (log/warn "Login request is missing device ID information"))
         description (or user-agent
-                        (log/warn (trs "Login request is missing user-agent information")))
+                        (log/warn "Login request is missing user-agent information"))
         ip-address  (or (ip-address request)
-                        (log/warn (trs "Unable to determine login request IP address")))]
+                        (log/warn "Unable to determine login request IP address"))]
     (when-not (and id description ip-address)
-      (log/warn (tru "Error determining login history for request")))
+      (log/warn "Error determining login history for request"))
     {:device_id          (or id (trs "unknown"))
      :device_description (or description (trs "unknown"))
      :ip_address         (or ip-address (trs "unknown"))}))
@@ -168,7 +168,7 @@
                                                     "Unknown location")
                                    :timezone    (u/ignore-exceptions (some-> (:timezone info) t/zone-id))}])))
          (catch Throwable e
-           (log/error e (trs "Error geocoding IP addresses") {:url url})
+           (log/error e "Error geocoding IP addresses" {:url url})
            nil))))))
 
 (def response-unauthentic
diff --git a/src/metabase/server/routes.clj b/src/metabase/server/routes.clj
index 9bb4cd69251a7d610292cf27ef0ce7095fc1549e..fda3504ba48d15c21c945ea3bd9d0751dea7b860 100644
--- a/src/metabase/server/routes.clj
+++ b/src/metabase/server/routes.clj
@@ -14,7 +14,6 @@
    [metabase.public-settings :as public-settings]
    [metabase.server.routes.index :as index]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [ring.util.response :as response]))
 
@@ -57,7 +56,7 @@
                 {:status 200, :body {:status "ok"}}
                 {:status 503 :body {:status "Unable to get app-db connection"}})
               (catch Exception e
-                (log/warn e (trs "Error in api/health database check"))
+                (log/warn e "Error in api/health database check")
                 {:status 503 :body {:status "Error getting app-db connection"}}))
          {:status 503, :body {:status "initializing", :progress (init-status/progress)}}))
 
diff --git a/src/metabase/sync/analyze/classifiers/category.clj b/src/metabase/sync/analyze/classifiers/category.clj
index 4db40ecec89802a3d4362493a36b9edcf43e8b30..75651a8929d859caa0098f3fc3174f307bbe9dba 100644
--- a/src/metabase/sync/analyze/classifiers/category.clj
+++ b/src/metabase/sync/analyze/classifiers/category.clj
@@ -38,10 +38,10 @@
                (or (some-> nil% (< 1))
                    (isa? (:base_type field) :type/Boolean))
                (some-> distinct-count (<= field-values/category-cardinality-threshold)))
-      (log/debug (format "%s has %d distinct values. Since that is less than %d, we're marking it as a category."
-                         (sync-util/name-for-logging field)
-                         distinct-count
-                         field-values/category-cardinality-threshold))
+      (log/debugf "%s has %d distinct values. Since that is less than %d, we're marking it as a category."
+                  (sync-util/name-for-logging field)
+                  distinct-count
+                  field-values/category-cardinality-threshold)
       true)))
 
 (mu/defn ^:private field-should-be-auto-list? :- [:maybe :boolean]
@@ -53,10 +53,10 @@
   (let [distinct-count (get-in fingerprint [:global :distinct-count])]
     (when (and (nil? (:has-field-values field))
                (some-> distinct-count (<= field-values/auto-list-cardinality-threshold)))
-      (log/debug (format "%s has %d distinct values. Since that is less than %d, it should have cached FieldValues."
-                         (sync-util/name-for-logging field)
-                         distinct-count
-                         field-values/auto-list-cardinality-threshold))
+      (log/debugf "%s has %d distinct values. Since that is less than %d, it should have cached FieldValues."
+                  (sync-util/name-for-logging field)
+                  distinct-count
+                  field-values/auto-list-cardinality-threshold)
       true)))
 
 (mu/defn infer-is-category-or-list :- [:maybe i/FieldInstance]
diff --git a/src/metabase/sync/analyze/classifiers/name.clj b/src/metabase/sync/analyze/classifiers/name.clj
index d2b56041e05be14301bee95ab6aea1344b68fe05..543ea59f4973920e66a3584cee56372f6db4552e 100644
--- a/src/metabase/sync/analyze/classifiers/name.clj
+++ b/src/metabase/sync/analyze/classifiers/name.clj
@@ -156,9 +156,9 @@
   [field-or-column :- FieldOrColumn
    _fingerprint    :- [:maybe i/Fingerprint]]
   (when-let [inferred-semantic-type (infer-semantic-type field-or-column)]
-    (log/debug (format "Based on the name of %s, we're giving it a semantic type of %s."
-                       (sync-util/name-for-logging field-or-column)
-                       inferred-semantic-type))
+    (log/debugf "Based on the name of %s, we're giving it a semantic type of %s."
+                (sync-util/name-for-logging field-or-column)
+                inferred-semantic-type)
     (assoc field-or-column :semantic_type inferred-semantic-type)))
 
 (defn- prefix-or-postfix
diff --git a/src/metabase/sync/analyze/classifiers/text_fingerprint.clj b/src/metabase/sync/analyze/classifiers/text_fingerprint.clj
index 0eb36eac1abfdfcdfe4d5e399af9a5b9d0f26ecc..86e3bfbd707f1860d255521f614a193adf7fa524 100644
--- a/src/metabase/sync/analyze/classifiers/text_fingerprint.clj
+++ b/src/metabase/sync/analyze/classifiers/text_fingerprint.clj
@@ -63,7 +63,7 @@
              (can-edit-semantic-type? field))
     (when-let [text-fingerprint (get-in fingerprint [:type :type/Text])]
       (when-let [inferred-semantic-type (infer-semantic-type-for-text-fingerprint text-fingerprint)]
-        (log/debug (format "Based on the fingerprint of %s, we're marking it as %s."
-                           (sync-util/name-for-logging field) inferred-semantic-type))
+        (log/debugf "Based on the fingerprint of %s, we're marking it as %s."
+                    (sync-util/name-for-logging field) inferred-semantic-type)
         (assoc field
                :semantic_type inferred-semantic-type)))))
diff --git a/src/metabase/sync/analyze/classify.clj b/src/metabase/sync/analyze/classify.clj
index d22c55ca2f92129096da834ec94d9bf5ac003a3e..d489198f6b595f819c904cf88b39b28ee39ad520 100644
--- a/src/metabase/sync/analyze/classify.clj
+++ b/src/metabase/sync/analyze/classify.clj
@@ -57,9 +57,9 @@
   (assert (= (type original-model) (type updated-model)))
   (let [[_ values-to-set] (data/diff original-model updated-model)]
     (when (seq values-to-set)
-      (log/debug (format "Based on classification, updating these values of %s: %s"
-                         (sync-util/name-for-logging original-model)
-                         values-to-set)))
+      (log/debugf "Based on classification, updating these values of %s: %s"
+                  (sync-util/name-for-logging original-model)
+                  values-to-set))
     ;; Check that we're not trying to set anything that we're not allowed to
     (doseq [k (keys values-to-set)]
       (when-not (contains? (updateable-columns (mi/model original-model)) k)
diff --git a/src/metabase/sync/sync_metadata/fields/sync_metadata.clj b/src/metabase/sync/sync_metadata/fields/sync_metadata.clj
index 4ee659c5cf181033bf2c6b953907ef8f242f56f8..8a2cbc22a528209f740576a2f5d3f5d1617ba2c6 100644
--- a/src/metabase/sync/sync_metadata/fields/sync_metadata.clj
+++ b/src/metabase/sync/sync_metadata/fields/sync_metadata.clj
@@ -73,13 +73,13 @@
         updates
         (merge
          (when new-db-type?
-           (log/infof "Database type of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Database type of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-database-type
                       new-database-type)
            {:database_type new-database-type})
          (when new-base-type?
-           (log/infof "Base type of %s has changed from ''%s'' to ''%s''. This field will be refingerprinted and analyzed."
+           (log/infof "Base type of %s has changed from '%s' to '%s'. This field will be refingerprinted and analyzed."
                      (common/field-metadata-name-for-logging table metabase-field)
                      old-base-type
                      new-base-type)
@@ -92,7 +92,7 @@
             ;; semantic type needs to be set to nil so that the fingerprinter can re-infer it during analysis
             :semantic_type       nil})
          (when new-semantic-type?
-           (log/infof "Semantic type of {0} has changed from ''%s'' to ''%s''."
+           (log/infof "Semantic type of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-semantic-type
                       new-semantic-type)
@@ -102,38 +102,38 @@
                       (common/field-metadata-name-for-logging table metabase-field))
            {:description new-field-comment})
          (when new-database-position?
-           (log/infof "Database position of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Database position of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-database-position
                       new-database-position)
            {:database_position new-database-position})
          (when (and (= (:field_order table) :database)
                     (not= old-position new-database-position))
-           (log/infof "Position of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Position of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-position
                       new-database-position)
            {:position new-database-position})
          (when new-name?
-           (log/infof "Name of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Name of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-database-name
                       new-database-name)
            {:name new-database-name})
          (when new-db-auto-incremented?
-           (log/infof "Database auto incremented of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Database auto incremented of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-database-is-auto-increment
                       new-database-is-auto-increment)
            {:database_is_auto_increment new-database-is-auto-increment})
          (when new-db-partitioned?
-           (log/infof "Database partitioned of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Database partitioned of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-db-partitioned
                       new-db-partitioned)
            {:database_partitioned new-db-partitioned})
          (when new-db-required?
-           (log/infof "Database required of %s has changed from ''%s'' to ''%s''."
+           (log/infof "Database required of %s has changed from '%s' to '%s'."
                       (common/field-metadata-name-for-logging table metabase-field)
                       old-db-required
                       new-db-required)
diff --git a/src/metabase/task.clj b/src/metabase/task.clj
index 211f977e351c514de942ff891a9fb32550263867..80f53d006f6b163e7d4f00edf6eb69f2be1fec78 100644
--- a/src/metabase/task.clj
+++ b/src/metabase/task.clj
@@ -76,10 +76,10 @@
     (try
       ;; don't bother logging namespace for now, maybe in the future if there's tasks of the same name in multiple
       ;; namespaces we can log it
-      (log/infof "Initializing task %s" (u/format-color 'green (name k)) (u/emoji "📆"))
+      (log/info "Initializing task" (u/format-color 'green (name k)) (u/emoji "📆"))
       (f k)
       (catch Throwable e
-        (log/error e "Error initializing task {0}" k)))))
+        (log/errorf e "Error initializing task %s" k)))))
 
 ;;; +----------------------------------------------------------------------------------------------------------------+
 ;;; |                                      Quartz Scheduler Connection Provider                                      |
diff --git a/src/metabase/task/index_values.clj b/src/metabase/task/index_values.clj
index fc1c8c4e9179d9782797cf70b992b8b7274a7002..33f2adc68bd7a6e5887fea7b2ba2d055a62139e9 100644
--- a/src/metabase/task/index_values.clj
+++ b/src/metabase/task/index_values.clj
@@ -10,7 +10,6 @@
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.task :as task]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [toucan2.core :as t2])
   (:import
@@ -88,16 +87,12 @@
   "Public API to start indexing a model."
   [model-index]
   (let [trigger (refresh-trigger model-index)]
-    (log/info
-     (u/format-color :green (trs "Scheduling indexing for model: {0}" (:model_id model-index))))
+    (log/info (u/format-color :green "Scheduling indexing for model: %s" (:model_id model-index)))
     (try (task/add-trigger! trigger)
          (catch ObjectAlreadyExistsException _e
-           (log/info (u/format-color :red (trs "Index already present for model: {0}"
-                                                 (:model_id model-index)))))
+           (log/info (u/format-color :red "Index already present for model: %s" (:model_id model-index))))
          (catch Exception e
-           (log/warn (trs "Error scheduling indexing for model: {0}"
-                          (:model_id model-index))
-                     e)))))
+           (log/warnf e "Error scheduling indexing for model: %s" (:model_id model-index))))))
 
 (defn remove-indexing-job
   "Public API to remove an indexing job on a model."
diff --git a/src/metabase/task/persist_refresh.clj b/src/metabase/task/persist_refresh.clj
index 26ddcde5cadc692b7b9accbd748b01f7e3417f1f..e85f41dfab6be273d9238ee43e69646c209098c2 100644
--- a/src/metabase/task/persist_refresh.clj
+++ b/src/metabase/task/persist_refresh.clj
@@ -23,7 +23,6 @@
    [metabase.query-processor.timezone :as qp.timezone]
    [metabase.task :as task]
    [metabase.util :as u]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]
    [potemkin.types :as p]
    [toucan2.core :as t2])
@@ -59,7 +58,7 @@
 (defn- refresh-with-stats! [refresher database stats persisted-info]
   ;; Since this could be long running, double check state just before refreshing
   (when (contains? (persisted-info/refreshable-states) (t2/select-one-fn :state PersistedInfo :id (:id persisted-info)))
-    (log/info (trs "Attempting to refresh persisted model {0}." (:card_id persisted-info)))
+    (log/infof "Attempting to refresh persisted model %s." (:card_id persisted-info))
     (let [card (t2/select-one Card :id (:card_id persisted-info))
           definition (persisted-info/metadata->definition (:result_metadata card)
                                                           (:table_name persisted-info))
@@ -74,8 +73,8 @@
           {:keys [state error]} (try
                                   (refresh! refresher database definition card)
                                   (catch Exception e
-                                    (log/info e (trs "Error refreshing persisting model with card-id {0}"
-                                                     (:card_id persisted-info)))
+                                    (log/infof e "Error refreshing persisting model with card-id %s"
+                                               (:card_id persisted-info))
                                     {:state :error :error (ex-message e)}))]
       (t2/update! PersistedInfo (u/the-id persisted-info)
                   {:active (= state :success),
@@ -130,14 +129,14 @@
                                              (:archived card-info)
                                              (not= (:type card-info) :model))
                                        (let [database (-> persisted-info :database_id db-id->db)]
-                                         (log/info (trs "Unpersisting model with card-id {0}" (:card_id persisted-info)))
+                                         (log/infof "Unpersisting model with card-id %s" (:card_id persisted-info))
                                          (try
                                            (unpersist! refresher database persisted-info)
                                            (when-not (= "off" current-state)
                                              (t2/delete! PersistedInfo :id (:id persisted-info)))
                                            (update stats :success inc)
                                            (catch Exception e
-                                             (log/info e (trs "Error unpersisting model with card-id {0}" (:card_id persisted-info)))
+                                             (log/infof e "Error unpersisting model with card-id %s" (:card_id persisted-info))
                                              (update stats :error inc))))
                                        (update stats :skipped inc))))
                                  {:success 0, :error 0, :skipped 0}
@@ -189,7 +188,7 @@
   "Refresh tables backing the persisted models. Updates all persisted tables with that database id which are in a state
   of \"persisted\"."
   [database-id refresher]
-  (log/info (trs "Starting persisted model refresh task for Database {0}." database-id))
+  (log/infof "Starting persisted model refresh task for Database %s." database-id)
   (persisted-info/ready-unpersisted-models! database-id)
   (let [database  (t2/select-one Database :id database-id)
         persisted (refreshable-models database-id)
@@ -198,8 +197,8 @@
                             {:success 0, :error 0, :trigger "Scheduled"}
                             persisted))
         {:keys [error success]} (save-task-history! "persist-refresh" database-id thunk)]
-    (log/info
-      (trs "Finished persisted model refresh task for Database {0} with {1} successes and {2} errors." database-id success error))))
+    (log/infof "Finished persisted model refresh task for Database %s with %s successes and %s errors."
+               database-id success error)))
 
 (defn- refresh-individual!
   "Refresh an individual model based on [[PersistedInfo]]."
@@ -215,10 +214,9 @@
                                      database
                                      {:success 0 :error 0, :trigger "Manual"}
                                      persisted-info))
-        (log/info (trs "Finished updated model-id {0} from persisted-info {1}."
-                       (:card_id persisted-info)
-                       (u/the-id persisted-info))))
-      (log/info (trs "Unable to refresh model with card-id {0}" (:card_id persisted-info))))))
+        (log/infof "Finished updated model-id %s from persisted-info %s."
+                   (:card_id persisted-info) (u/the-id persisted-info)))
+      (log/infof "Unable to refresh model with card-id %s" (:card_id persisted-info)))))
 
 (defn- refresh-job-fn!
   "Refresh tables. Gets the database id from the job context and calls `refresh-tables!'`."
@@ -227,7 +225,7 @@
     (case type
       "database"   (refresh-tables!     db-id        dispatching-refresher)
       "individual" (refresh-individual! persisted-id dispatching-refresher)
-      (log/info (trs "Unknown payload type {0}" type)))))
+      (log/infof "Unknown payload type %s" type))))
 
 (defn- prune-job-fn!
   [_job-context]
@@ -365,7 +363,7 @@
     (try (task/add-trigger! tggr)
          (catch ObjectAlreadyExistsException _e
            (log/info
-            (u/format-color 'green "Persistence already present for model %d"
+            (u/format-color :green "Persistence already present for model %d %s"
                             (:card_id persisted-info)
                             (.. ^Trigger tggr getKey getName)))))))
          ;; other errors?
diff --git a/src/metabase/task/refresh_slack_channel_user_cache.clj b/src/metabase/task/refresh_slack_channel_user_cache.clj
index cca21c4ab9704aaa4bbf924a34f5429343c46305..d5ee36aef308c660423fc2e876de04c144404601 100644
--- a/src/metabase/task/refresh_slack_channel_user_cache.clj
+++ b/src/metabase/task/refresh_slack_channel_user_cache.clj
@@ -6,7 +6,6 @@
    [clojurewerkz.quartzite.triggers :as triggers]
    [metabase.integrations.slack :as slack]
    [metabase.task :as task]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log]))
 
 (set! *warn-on-reflection* true)
@@ -16,10 +15,10 @@
     (let [_        (log/info "Starting Slack user/channel startup cache refresh...")
           start-ms (System/currentTimeMillis)
           _        (slack/refresh-channels-and-usernames!)]
-      (log/info (trs "Slack user/channel startup cache refreshed with {0} entries, took {1}ms."
-                     (count (:channels (slack/slack-cached-channels-and-usernames)))
-                     (- (System/currentTimeMillis) start-ms))))
-    (log/info (trs "Slack is not configured, not refreshing slack user/channel cache."))))
+      (log/infof "Slack user/channel startup cache refreshed with %s entries, took %sms."
+                 (count (:channels (slack/slack-cached-channels-and-usernames)))
+                 (- (System/currentTimeMillis) start-ms)))
+    (log/info "Slack is not configured, not refreshing slack user/channel cache.")))
 
 (def ^:private job-key "metabase.task.refresh-channel-cache.job")
 (def ^:private trigger-key "metabase.task.refresh-channel-cache.trigger")
diff --git a/src/metabase/task/sync_databases.clj b/src/metabase/task/sync_databases.clj
index eb0f24877d0c6369229b15639a6f087289fea138..5e11877129cfc051eb6e7ea86c9b5fc4bccddfb9 100644
--- a/src/metabase/task/sync_databases.clj
+++ b/src/metabase/task/sync_databases.clj
@@ -320,18 +320,16 @@
              (fn
                ([] 0)
                ([counter]
-                (log/info "Updated default schedules for %d databases" counter)
+                (log/infof "Updated default schedules for %d databases" counter)
                 counter)
                ([counter db]
                 (try
                   (t2/update! Database (u/the-id db)
-                    (sync.schedules/schedule-map->cron-strings
-                     (sync.schedules/default-randomized-schedule)))
+                              (sync.schedules/schedule-map->cron-strings
+                               (sync.schedules/default-randomized-schedule)))
                   (inc counter)
                   (catch Exception e
-                    (log/warnf e
-                               "Error updating database %d for randomized schedules"
-                               (u/the-id db))
+                    (log/warnf e "Error updating database %d for randomized schedules" (u/the-id db))
                     counter))))
              (mdb.query/reducible-query
               {:select [:id :details]
diff --git a/src/metabase/util.cljc b/src/metabase/util.cljc
index 2da4c4ddca41d9de9cb1c1f01a701ae7307d37e5..2f1234ab9131dc1fd4a9287f4be61044e17c990d 100644
--- a/src/metabase/util.cljc
+++ b/src/metabase/util.cljc
@@ -266,7 +266,7 @@
 ;; Log the maximum memory available to the JVM at launch time as well since it is very handy for debugging things
 #?(:clj
    (when-not *compile-files*
-     (log/info (i18n/trs "Maximum memory available to JVM: {0}" (u.format/format-bytes (.maxMemory (Runtime/getRuntime)))))))
+     (log/infof "Maximum memory available to JVM: %s" (u.format/format-bytes (.maxMemory (Runtime/getRuntime))))))
 
 ;; Set the default width for pprinting to 120 instead of 72. The default width is too narrow and wastes a lot of space
 #?(:clj  (alter-var-root #'pprint/*print-right-margin* (constantly 120))
diff --git a/src/metabase/util/encryption.clj b/src/metabase/util/encryption.clj
index 9c18fa6a05c0f88dd76db1f4c0c862d40b117226..ff918949841f5b9780b08c50f41b57f81eb9f462 100644
--- a/src/metabase/util/encryption.clj
+++ b/src/metabase/util/encryption.clj
@@ -41,12 +41,11 @@
 (when-not *compile-files*
   (log/info
    (if default-secret-key
-     (trs "Saved credentials encryption is ENABLED for this Metabase instance.")
-     (trs "Saved credentials encryption is DISABLED for this Metabase instance."))
+     "Saved credentials encryption is ENABLED for this Metabase instance."
+     "Saved credentials encryption is DISABLED for this Metabase instance.")
    (u/emoji (if default-secret-key "🔐" "🔓"))
    "\n"
-   (trs "For more information, see")
-   "https://metabase.com/docs/latest/operations-guide/encrypting-database-details-at-rest.html"))
+   "For more information, see https://metabase.com/docs/latest/operations-guide/encrypting-database-details-at-rest.html"))
 
 (defn encrypt-bytes
   "Encrypt bytes `b` using a `secret-key` (a 64-byte byte array), by default is the hashed value of
diff --git a/src/metabase/util/files.clj b/src/metabase/util/files.clj
index d1a8a3cd21708837e9950db3abee9ec793bb3a44..6ec0d5fb01ebec208e3416fe167f3baab0246762 100644
--- a/src/metabase/util/files.clj
+++ b/src/metabase/util/files.clj
@@ -90,7 +90,7 @@
   [^Path source ^Path dest]
   (when (or (not (exists? dest))
             (not= (last-modified-timestamp source) (last-modified-timestamp dest)))
-    (log/info (trs "Extract file {0} -> {1}" source dest))
+    (log/infof "Extract file %s -> %s" source dest)
     (Files/copy source dest (u/varargs CopyOption [StandardCopyOption/REPLACE_EXISTING
                                                    StandardCopyOption/COPY_ATTRIBUTES]))))
 
@@ -103,7 +103,7 @@
     (try
       (copy-file! source target)
       (catch Throwable e
-        (log/error e (trs "Failed to copy file"))))))
+        (log/error e "Failed to copy file")))))
 
 
 ;;; ------------------------------------------ Opening filesystems for URLs ------------------------------------------
diff --git a/src/metabase/util/yaml.clj b/src/metabase/util/yaml.clj
index 675629737d6baa503cd9baf707532e9ffd21de75..4805a3ff147868aa8705c0d5f4307939608e7d79 100644
--- a/src/metabase/util/yaml.clj
+++ b/src/metabase/util/yaml.clj
@@ -9,7 +9,6 @@
    [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
    [metabase.util.files :as u.files]
-   [metabase.util.i18n :refer [trs]]
    [metabase.util.log :as log])
   (:import
    (java.nio.file Files Path)
@@ -56,13 +55,13 @@
    (try
      (-> f .toUri slurp parse-string constructor)
      (catch Exception e
-       (log/error (trs "Error parsing {0}:\n{1}"
-                       (.getFileName f)
-                       (or (some-> e
-                                   ex-data
-                                   (select-keys [:error :value])
-                                   u/pprint-to-str)
-                           e)))
+       (log/errorf "Error parsing %s:\n%s"
+                   (.getFileName f)
+                   (or (some-> e
+                               ex-data
+                               (select-keys [:error :value])
+                               u/pprint-to-str)
+                       e))
        (throw e)))))
 
 (defn load-dir
diff --git a/test/metabase/http_client.clj b/test/metabase/http_client.clj
index 50f781e3ef44f3f57ff89e95aedcfd235fe058d4..b9df013847155f4876c272fc3f9539667e094689 100644
--- a/test/metabase/http_client.clj
+++ b/test/metabase/http_client.clj
@@ -159,7 +159,7 @@
       (or (:id response)
           (throw (ex-info "Unexpected response" {:response response}))))
     (catch Throwable e
-      (log/errorf "Failed to authenticate with credentials %s %s" credentials e)
+      (log/errorf e "Failed to authenticate with credentials %s" credentials)
       (throw (ex-info "Failed to authenticate with credentials"
                       {:credentials credentials}
                       e)))))
diff --git a/test/metabase/server/middleware/session_test.clj b/test/metabase/server/middleware/session_test.clj
index 0e6bd4184c29e3a612eb9275d5124dbc83b42cb8..8d96790eb889eb6542554364a191410251f78332 100644
--- a/test/metabase/server/middleware/session_test.clj
+++ b/test/metabase/server/middleware/session_test.clj
@@ -92,13 +92,13 @@
                              (map (fn [[_log-level _error message]] message))
                              (mt/with-log-messages-for-level :warn
                                (mw.session/set-session-cookies {:headers {"x-forwarded-proto" "http"}} {} session request-time)))
-                       "Session cookies SameSite is configured to \"None\", but site is served over an insecure connection. Some browsers will reject cookies under these conditions. https://www.chromestatus.com/feature/5633521622188032")))
+                       "Session cookie's SameSite is configured to \"None\", but site is served over an insecure connection. Some browsers will reject cookies under these conditions. https://www.chromestatus.com/feature/5633521622188032")))
       (testing "should not log a warning over a secure connection."
         (is (not (contains? (into #{}
                                   (map (fn [[_log-level _error message]] message))
                                   (mt/with-log-messages-for-level :warn
                                     (mw.session/set-session-cookies {:headers {"x-forwarded-proto" "https"}} {} session request-time)))
-                            "Session cookies SameSite is configured to \"None\", but site is served over an insecure connection. Some browsers will reject cookies under these conditions. https://www.chromestatus.com/feature/5633521622188032")))))))
+                            "Session cookie's SameSite is configured to \"None\", but site is served over an insecure connection. Some browsers will reject cookies under these conditions. https://www.chromestatus.com/feature/5633521622188032")))))))
 
 ;; if request is an HTTPS request then we should set `:secure true`. There are several different headers we check for
 ;; this. Make sure they all work.
@@ -562,28 +562,29 @@
         (is (= [[:warn nil "Session timeout must be less than 100 years."]]
                (mt/with-log-messages-for-level :warn (set-and-get timeout))))))))
 
-(deftest session-timeout-test
+(deftest ^:parallel session-timeout-test
+  (testing "`session-timeout` setting conversion to seconds"
+    (is (= 10800
+           (mw.session/session-timeout->seconds {:amount 180
+                                                 :unit   "minutes"})))
+    (is (= 60
+           (mw.session/session-timeout->seconds {:amount 60
+                                                 :unit   "seconds"})))
+    (is (= 3600
+           (mw.session/session-timeout->seconds {:amount 1
+                                                 :unit   "hours"})))))
+
+(deftest ^:parallel session-timeout-test-2
+  (testing "The session timeout should be a minimum of 30 seconds"
+    (is (= 60
+           (mw.session/session-timeout->seconds {:amount 0
+                                                 :unit   "minutes"})))))
+
+(deftest session-timeout-test-3
   (let [request-time (t/zoned-date-time "2022-01-01T00:00:00.000Z")
         session-id   "8df268ab-00c0-4b40-9413-d66b966b696a"
         response     {:body    "some body",
                       :cookies {}}]
-
-    (testing "`session-timeout` setting conversion to seconds"
-      (is (= 10800
-             (mw.session/session-timeout->seconds {:amount 180
-                                                   :unit   "minutes"})))
-      (is (= 60
-             (mw.session/session-timeout->seconds {:amount 60
-                                                   :unit   "seconds"})))
-      (is (= 3600
-             (mw.session/session-timeout->seconds {:amount 1
-                                                   :unit   "hours"}))))
-
-    (testing "The session timeout should be a minimum of 30 seconds"
-      (is (= 60
-             (mw.session/session-timeout->seconds {:amount 0
-                                                   :unit   "minutes"}))))
-
     (testing "non-nil `session-timeout-seconds` should set the expiry of the timeout cookie relative to the request time"
       (mt/with-temporary-setting-values [session-timeout {:amount 60
                                                           :unit   "minutes"}]
@@ -608,15 +609,24 @@
                     :cookies {session-timeout-cookie {:value     "alive"
                                                       :path      "/"
                                                       :expires   "Sat, 1 Jan 2022 01:00:00 GMT"}}}
-                   (mw.session/reset-session-timeout* request response request-time)))))))
+                   (mw.session/reset-session-timeout* request response request-time)))))))))
 
+(deftest session-timeout-test-4
+  (let [request-time (t/zoned-date-time "2022-01-01T00:00:00.000Z")
+        response     {:body    "some body",
+                      :cookies {}}]
     (testing "If the request does not have session cookies (because they have expired), they should not be reset."
       (mt/with-temporary-setting-values [session-timeout {:amount 60
                                                           :unit   "minutes"}]
         (let [request {:cookies {}}]
           (is (= response
-                 (mw.session/reset-session-timeout* request response request-time))))))
+                 (mw.session/reset-session-timeout* request response request-time))))))))
 
+(deftest session-timeout-test-5
+  (let [request-time (t/zoned-date-time "2022-01-01T00:00:00.000Z")
+        session-id   "8df268ab-00c0-4b40-9413-d66b966b696a"
+        response     {:body    "some body",
+                      :cookies {}}]
     (testing "If [[public-settings/session-cookies]] is false and the `:remember` flag is set, then the session cookie
               should have a max age attribute."
       (with-redefs [env/env (assoc env/env :max-session-age "1")]
@@ -639,8 +649,13 @@
                                                   :path      "/"
                                                   :max-age   60
                                                   :http-only true}}}
-                   (mw.session/set-session-cookies request response session request-time)))))))
+                   (mw.session/set-session-cookies request response session request-time)))))))))
 
+(deftest session-timeout-test-6
+  (let [request-time (t/zoned-date-time "2022-01-01T00:00:00.000Z")
+        session-id   "8df268ab-00c0-4b40-9413-d66b966b696a"
+        response     {:body    "some body",
+                      :cookies {}}]
     (testing "If [[public-settings/session-cookies]] is true and the `:remember` flag is set, then the session cookie
               shouldn't have a max age attribute."
       (with-redefs [env/env (assoc env/env :max-session-age "1")]
diff --git a/test/metabase/test/data/impl/verify.clj b/test/metabase/test/data/impl/verify.clj
index be5fcc26e3f41af8b6aac26614890eec4b7415b5..9afb532c35766910c882998a34c88268589620e9 100644
--- a/test/metabase/test/data/impl/verify.clj
+++ b/test/metabase/test/data/impl/verify.clj
@@ -80,7 +80,7 @@
     (log/debugf "Found Table %s.%s" (pr-str actual-schema) (pr-str actual-name))
     (let [params (assoc params :actual-schema actual-schema, :actual-table-name actual-name)
           params (assoc params :actual-field-names (loaded-fields params))]
-      (log/debugf "Verifying fields...")
+      (log/debug "Verifying fields...")
       (doseq [fielddef field-definitions
               :let     [params (assoc params :field-definition fielddef)]]
         (try
@@ -88,7 +88,7 @@
           (catch Throwable e
             (throw (ex-info "Error verifying Field." (params->ex-data params) e)))))
       (log/debugf "All Fields for Table %s.%s loaded correctly." (pr-str actual-schema) (pr-str actual-name))
-      (log/debugf "Verifying rows...")
+      (log/debug "Verifying rows...")
       (let [table-id           (or (t2/select-one-pk Table :db_id (u/the-id database), :name actual-name)
                                    (throw (ex-info (format "Cannot find %s.%s after sync." (pr-str actual-schema) (pr-str actual-name))
                                                    (params->ex-data params))))
diff --git a/test/metabase/test/initialize/web_server.clj b/test/metabase/test/initialize/web_server.clj
index 2b51ac9e740e3df4b48c5a26f37d809fd9d8e12d..816e50b7bc2f23c6d28ab27b3436ddb4da158508 100644
--- a/test/metabase/test/initialize/web_server.clj
+++ b/test/metabase/test/initialize/web_server.clj
@@ -35,7 +35,7 @@
     (server/start-web-server! test-handler)
     (log/infof "Started test server on port %d" (config/config-int :mb-jetty-port))
     (catch Throwable e
-      (log/fatalf e "Web server failed to start")
+      (log/fatal e "Web server failed to start")
       (when config/is-test?
         (System/exit -2))))
   (init-status/set-complete!)