[gnome-shell] js: Use templates for non-translatable strings



commit a1dd1b25d8f78d3037d553010f6dee792ad4bd20
Author: Florian Müllner <fmuellner gnome org>
Date:   Mon Feb 7 15:14:06 2022 +0100

    js: Use templates for non-translatable strings
    
    This reverts commit 9d941f8202125fa and replaces all additional
    instances of .format() that have been added since.
    
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2160>

 js/gdm/loginDialog.js                 |  8 ++++----
 js/gdm/util.js                        | 12 +++++++-----
 js/misc/ibusManager.js                |  6 +++---
 js/misc/systemActions.js              | 10 +++++-----
 js/misc/util.js                       | 18 +++++++++---------
 js/portalHelper/main.js               |  3 ++-
 js/ui/accessDialog.js                 |  2 +-
 js/ui/appDisplay.js                   | 12 ++++++------
 js/ui/appFavorites.js                 |  2 +-
 js/ui/audioDeviceSelection.js         |  2 +-
 js/ui/background.js                   |  2 +-
 js/ui/calendar.js                     | 22 +++++++++++-----------
 js/ui/components/automountManager.js  |  6 +++---
 js/ui/components/autorunManager.js    |  4 ++--
 js/ui/components/networkAgent.js      | 20 ++++++++++----------
 js/ui/components/polkitAgent.js       |  6 +++---
 js/ui/components/telepathyClient.js   |  6 +++---
 js/ui/dateMenu.js                     | 18 +++++++++---------
 js/ui/endSessionDialog.js             |  8 ++++----
 js/ui/extensionDownloader.js          | 17 ++++++++---------
 js/ui/extensionSystem.js              | 32 ++++++++++++++++----------------
 js/ui/keyboard.js                     |  3 ++-
 js/ui/lookingGlass.js                 | 35 +++++++++++++++--------------------
 js/ui/main.js                         | 28 ++++++++++++++--------------
 js/ui/messageList.js                  |  4 ++--
 js/ui/messageTray.js                  |  6 +++---
 js/ui/mpris.js                        | 20 ++++++++++----------
 js/ui/notificationDaemon.js           | 11 ++++++-----
 js/ui/overview.js                     |  2 +-
 js/ui/padOsd.js                       | 30 +++++++++++++++---------------
 js/ui/panel.js                        |  2 +-
 js/ui/panelMenu.js                    |  2 +-
 js/ui/popupMenu.js                    |  4 ++--
 js/ui/remoteSearch.js                 |  6 +++---
 js/ui/runDialog.js                    |  4 ++--
 js/ui/screenShield.js                 |  4 ++--
 js/ui/screenshot.js                   | 14 +++++++-------
 js/ui/scripting.js                    |  6 +++---
 js/ui/search.js                       |  8 ++++----
 js/ui/shellMountOperation.js          |  2 +-
 js/ui/status/accessibility.js         |  6 +++---
 js/ui/status/dwellClick.js            |  4 ++--
 js/ui/status/keyboard.js              | 20 ++++++++++----------
 js/ui/status/location.js              |  6 +++---
 js/ui/status/network.js               | 31 ++++++++++++++-----------------
 js/ui/status/power.js                 |  4 ++--
 js/ui/status/thunderbolt.js           |  7 +++----
 js/ui/status/volume.js                |  2 +-
 js/ui/unlockDialog.js                 |  6 +++---
 js/ui/windowManager.js                | 12 +++++-------
 subprojects/extensions-app/js/main.js | 10 +++++-----
 51 files changed, 254 insertions(+), 261 deletions(-)
---
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 3294d65566..4e2c948dc9 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -425,13 +425,13 @@ var LoginDialog = GObject.registerClass({
 
         this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
 
-        this._settings.connect('changed::%s'.format(GdmUtil.BANNER_MESSAGE_KEY),
+        this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`,
                                this._updateBanner.bind(this));
-        this._settings.connect('changed::%s'.format(GdmUtil.BANNER_MESSAGE_TEXT_KEY),
+        this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`,
                                this._updateBanner.bind(this));
-        this._settings.connect('changed::%s'.format(GdmUtil.DISABLE_USER_LIST_KEY),
+        this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`,
                                this._updateDisableUserList.bind(this));
-        this._settings.connect('changed::%s'.format(GdmUtil.LOGO_KEY),
+        this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`,
                                this._updateLogo.bind(this));
 
         this._textureCache = St.TextureCache.get_default();
diff --git a/js/gdm/util.js b/js/gdm/util.js
index d310099a61..771cd18fbb 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -572,14 +572,16 @@ var ShellUserVerifier = class {
             if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                 return;
             if (!this.serviceIsForeground(serviceName)) {
-                logError(e, 'Failed to start %s for %s'.format(serviceName, this._userName));
+                logError(e,
+                    `Failed to start ${serviceName} for ${this._userName}`);
                 this._hold.release();
                 return;
             }
-            this._reportInitError(this._userName
-                ? 'Failed to start %s verification for user'.format(serviceName)
-                : 'Failed to start %s verification'.format(serviceName), e,
-            serviceName);
+            this._reportInitError(
+                this._userName
+                    ? `Failed to start ${serviceName} verification for user`
+                    : `Failed to start ${serviceName} verification`,
+                e, serviceName);
             return;
         }
         this._hold.release();
diff --git a/js/misc/ibusManager.js b/js/misc/ibusManager.js
index 45387877c7..55c0d308b4 100644
--- a/js/misc/ibusManager.js
+++ b/js/misc/ibusManager.js
@@ -29,9 +29,9 @@ function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
          IBus.MICRO_VERSION >= requiredMicro))
         return;
 
-    throw "Found IBus version %d.%d.%d but required is %d.%d.%d"
-        .format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MICRO_VERSION,
-                requiredMajor, requiredMinor, requiredMicro);
+    throw new Error(`Found IBus version ${
+        IBus.MAJOR_VERSION}.${IBus.MINOR_VERSION}.${IBus.MINOR_VERSION} ` +
+        `but required is ${requiredMajor}.${requiredMinor}.${requiredMicro}`);
 }
 
 function getIBusManager() {
diff --git a/js/misc/systemActions.js b/js/misc/systemActions.js
index a45a21c165..48e8d75d86 100644
--- a/js/misc/systemActions.js
+++ b/js/misc/systemActions.js
@@ -162,17 +162,17 @@ const SystemActions = GObject.registerClass({
         this._userManager.connect('user-removed',
                                   () => this._updateMultiUser());
 
-        this._lockdownSettings.connect('changed::%s'.format(DISABLE_USER_SWITCH_KEY),
+        this._lockdownSettings.connect(`changed::${DISABLE_USER_SWITCH_KEY}`,
                                        () => this._updateSwitchUser());
-        this._lockdownSettings.connect('changed::%s'.format(DISABLE_LOG_OUT_KEY),
+        this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
                                        () => this._updateLogout());
-        global.settings.connect('changed::%s'.format(ALWAYS_SHOW_LOG_OUT_KEY),
+        global.settings.connect(`changed::${ALWAYS_SHOW_LOG_OUT_KEY}`,
                                 () => this._updateLogout());
 
-        this._lockdownSettings.connect('changed::%s'.format(DISABLE_LOCK_SCREEN_KEY),
+        this._lockdownSettings.connect(`changed::${DISABLE_LOCK_SCREEN_KEY}`,
                                        () => this._updateLockScreen());
 
-        this._lockdownSettings.connect('changed::%s'.format(DISABLE_LOG_OUT_KEY),
+        this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
                                        () => this._updateHaveShutdown());
 
         this.forceUpdate();
diff --git a/js/misc/util.js b/js/misc/util.js
index bea2cfe852..389fdde28e 100644
--- a/js/misc/util.js
+++ b/js/misc/util.js
@@ -22,7 +22,7 @@ const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
 const _notTrailingJunk = 
'[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u200E\u200F\u201C\u201D\u2018\u2019\u202A\u202C]';
 
 const _urlRegexp = new RegExp(
-    '(^|%s)'.format(_leadingJunk) +
+    `(^|${_leadingJunk})` +
     '(' +
         '(?:' +
             '(?:http|https|ftp)://' +             // scheme://
@@ -34,12 +34,12 @@ const _urlRegexp = new RegExp(
         '(?:' +                                   // one or more:
             '[^\\s()<>]+' +                       // run of non-space non-()
             '|' +                                 // or
-            '%s'.format(_balancedParens) +        // balanced parens
+            `${_balancedParens}` +                // balanced parens
         ')+' +
         '(?:' +                                   // end with:
-            '%s'.format(_balancedParens) +        // balanced parens
+            `${_balancedParens}` +                // balanced parens
             '|' +                                 // or
-            '%s'.format(_notTrailingJunk) +       // last non-junk char
+            `${_notTrailingJunk}` +               // last non-junk char
         ')' +
     ')', 'gi');
 
@@ -161,7 +161,7 @@ function trySpawnCommandLine(commandLine) {
     } catch (err) {
         // Replace "Error invoking GLib.shell_parse_argv: " with
         // something nicer
-        err.message = err.message.replace(/[^:]*: /, '%s\n'.format(_('Could not parse command:')));
+        err.message = err.message.replace(/[^:]*: /, `${_('Could not parse command:')}\n`);
         throw err;
     }
 
@@ -550,7 +550,7 @@ var DBusSenderChecker = class {
 
         throw new GLib.Error(Gio.DBusError,
             Gio.DBusError.ACCESS_DENIED,
-            '%s is not allowed'.format(invocation.get_method_name()));
+            `${invocation.get_method_name()} is not allowed`);
     }
 
     /**
@@ -579,8 +579,8 @@ var Highlighter = class {
         if (escapedTerms.length === 0)
             return;
 
-        this._highlightRegex = new RegExp('(%s)'.format(
-            escapedTerms.join('|')), 'gi');
+        this._highlightRegex = new RegExp(
+            `(${escapedTerms.join('|')})`, 'gi');
     }
 
     /**
@@ -604,7 +604,7 @@ var Highlighter = class {
                 escaped.push(unmatched);
             }
             let matched = GLib.markup_escape_text(match[0], -1);
-            escaped.push('<b>%s</b>'.format(matched));
+            escaped.push(`<b>${matched}</b>`);
             lastMatchEnd = match.index + match[0].length;
         }
         let unmatched = GLib.markup_escape_text(
diff --git a/js/portalHelper/main.js b/js/portalHelper/main.js
index f876a48b14..9f9b987184 100644
--- a/js/portalHelper/main.js
+++ b/js/portalHelper/main.js
@@ -31,6 +31,7 @@ const HTTP_URI_FLAGS =
     GLib.UriFlags.PARSE_RELAXED;
 
 const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
+const CONNECTIVITY_CHECK_URI = `http://${CONNECTIVITY_CHECK_HOST}`;
 const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
 
 const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper');
@@ -110,7 +111,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
         this._headerBar.show();
 
         if (!url) {
-            url = 'http://%s'.format(CONNECTIVITY_CHECK_HOST);
+            url = CONNECTIVITY_CHECK_URI;
             this._originalUrlWasGnome = true;
         } else {
             this._originalUrlWasGnome = false;
diff --git a/js/ui/accessDialog.js b/js/ui/accessDialog.js
index 7c8d69b806..4c2aa238fa 100644
--- a/js/ui/accessDialog.js
+++ b/js/ui/accessDialog.js
@@ -140,7 +140,7 @@ var AccessDialogDBus = class {
         let [handle, appId, parentWindow_, title, description, body, options] = params;
         // We probably want to use parentWindow and global.display.focus_window
         // for this check in the future
-        if (appId && '%s.desktop'.format(appId) != this._windowTracker.focus_app.id) {
+        if (appId && `${appId}.desktop` !== this._windowTracker.focus_app.id) {
             invocation.return_error_literal(Gio.DBusError,
                                             Gio.DBusError.ACCESS_DENIED,
                                             'Only the focused app is allowed to show a system access 
dialog');
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index c8f60493d5..95bba64020 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -119,7 +119,7 @@ function _findBestFolderName(apps) {
     }, commonCategories);
 
     for (let category of commonCategories) {
-        const directory = '%s.directory'.format(category);
+        const directory = `${category}.directory`;
         const translated = Shell.util_get_translated_folder_name(directory);
         if (translated !== null)
             return translated;
@@ -870,7 +870,7 @@ var BaseAppView = GObject.registerClass({
         if (this._items.has(id))
             this._items.get(id).navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
         else
-            log('No such application %s'.format(id));
+            log(`No such application ${id}`);
     }
 
     selectApp(id) {
@@ -1533,7 +1533,7 @@ class AppDisplay extends BaseAppView {
 
         let folders = this._folderSettings.get_strv('folder-children');
         folders.forEach(id => {
-            let path = '%sfolders/%s/'.format(this._folderSettings.path, id);
+            let path = `${this._folderSettings.path}folders/${id}/`;
             let icon = this._items.get(id);
             if (!icon) {
                 icon = new FolderIcon(id, path, this);
@@ -2213,7 +2213,7 @@ class FolderView extends BaseAppView {
         let icon = new St.Widget({
             layout_manager: layout,
             x_align: Clutter.ActorAlign.CENTER,
-            style: 'width: %dpx; height: %dpx;'.format(size, size),
+            style: `width: ${size}px; height: ${size}px;`,
         });
 
         let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size);
@@ -2221,7 +2221,7 @@ class FolderView extends BaseAppView {
         let numItems = this._orderedItems.length;
         let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL;
         for (let i = 0; i < 4; i++) {
-            const style = 'width: %dpx; height: %dpx;'.format(subSize, subSize);
+            const style = `width: ${subSize}px; height: ${subSize}px;`;
             let bin = new St.Bin({ style });
             if (i < numItems)
                 bin.child = this._orderedItems[i].app.create_icon_texture(subSize);
@@ -3219,7 +3219,7 @@ var AppIcon = GObject.registerClass({
 
     shellWorkspaceLaunch(params) {
         let { stack } = new Error();
-        log('shellWorkspaceLaunch is deprecated, use app.open_new_window() instead\n%s'.format(stack));
+        log(`shellWorkspaceLaunch is deprecated, use app.open_new_window() instead\n${stack}`);
 
         params = Params.parse(params, { workspace: -1,
                                         timestamp: 0 });
diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js
index 4e372c2138..18fc3d020e 100644
--- a/js/ui/appFavorites.js
+++ b/js/ui/appFavorites.js
@@ -75,7 +75,7 @@ class AppFavorites {
 
         this.FAVORITE_APPS_KEY = 'favorite-apps';
         this._favorites = {};
-        global.settings.connect('changed::%s'.format(this.FAVORITE_APPS_KEY), 
this._onFavsChanged.bind(this));
+        global.settings.connect(`changed::${this.FAVORITE_APPS_KEY}`, this._onFavsChanged.bind(this));
         this.reload();
     }
 
diff --git a/js/ui/audioDeviceSelection.js b/js/ui/audioDeviceSelection.js
index 8660663f92..fb78b79225 100644
--- a/js/ui/audioDeviceSelection.js
+++ b/js/ui/audioDeviceSelection.js
@@ -125,7 +125,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
         let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
 
         if (!app) {
-            log('Settings panel for desktop file %s could not be loaded!'.format(desktopFile));
+            log(`Settings panel for desktop file ${desktopFile} could not be loaded!`);
             return;
         }
 
diff --git a/js/ui/background.js b/js/ui/background.js
index 9c6a1636d2..21359d0a83 100644
--- a/js/ui/background.js
+++ b/js/ui/background.js
@@ -271,7 +271,7 @@ var Background = GObject.registerClass({
             this._settings.connect('changed', this._emitChangedSignal.bind(this));
 
         this._colorSchemeChangedSignalId =
-            this._interfaceSettings.connect('changed::%s'.format(COLOR_SCHEME_KEY),
+            this._interfaceSettings.connect(`changed::${COLOR_SCHEME_KEY}`,
                 this._emitChangedSignal.bind(this));
 
         this._load();
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index 54e8e9f150..9535178188 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -16,7 +16,7 @@ var SHOW_WEEKDATE_KEY = 'show-weekdate';
 
 var MESSAGE_ICON_SIZE = -1; // pick up from CSS
 
-var NC_ = (context, str) => '%s\u0004%s'.format(context, str);
+var NC_ = (context, str) => `${context}\u0004${str}`;
 
 function sameYear(dateA, dateB) {
     return dateA.getYear() == dateB.getYear();
@@ -104,26 +104,26 @@ var EventSourceBase = GObject.registerClass({
     Signals: { 'changed': {} },
 }, class EventSourceBase extends GObject.Object {
     get isLoading() {
-        throw new GObject.NotImplementedError('isLoading in %s'.format(this.constructor.name));
+        throw new GObject.NotImplementedError(`isLoading in ${this.constructor.name}`);
     }
 
     get hasCalendars() {
-        throw new GObject.NotImplementedError('hasCalendars in %s'.format(this.constructor.name));
+        throw new GObject.NotImplementedError(`hasCalendars in ${this.constructor.name}`);
     }
 
     destroy() {
     }
 
     requestRange(_begin, _end) {
-        throw new GObject.NotImplementedError('requestRange in %s'.format(this.constructor.name));
+        throw new GObject.NotImplementedError(`requestRange in ${this.constructor.name}`);
     }
 
     getEvents(_begin, _end) {
-        throw new GObject.NotImplementedError('getEvents in %s'.format(this.constructor.name));
+        throw new GObject.NotImplementedError(`getEvents in ${this.constructor.name}`);
     }
 
     hasEvents(_day) {
-        throw new GObject.NotImplementedError('hasEvents in %s'.format(this.constructor.name));
+        throw new GObject.NotImplementedError(`hasEvents in ${this.constructor.name}`);
     }
 });
 
@@ -222,7 +222,7 @@ class DBusEventSource extends EventSourceBase {
             // about the HasCalendars property and would cause an exception trying
             // to read it)
             if (!e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
-                log('Error loading calendars: %s'.format(e.message));
+                log(`Error loading calendars: ${e.message}`);
                 return;
             }
         }
@@ -390,7 +390,7 @@ var Calendar = GObject.registerClass({
         this._weekStart = Shell.util_get_week_start();
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
 
-        this._settings.connect('changed::%s'.format(SHOW_WEEKDATE_KEY), this._onSettingsChange.bind(this));
+        this._settings.connect(`changed::${SHOW_WEEKDATE_KEY}`, this._onSettingsChange.bind(this));
         this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
 
         /**
@@ -664,13 +664,13 @@ var Calendar = GObject.registerClass({
 
             // Hack used in lieu of border-collapse - see gnome-shell.css
             if (row == 2)
-                styleClass = 'calendar-day-top %s'.format(styleClass);
+                styleClass = `calendar-day-top ${styleClass}`;
 
             let leftMost = rtl
                 ? iter.getDay() == (this._weekStart + 6) % 7
                 : iter.getDay() == this._weekStart;
             if (leftMost)
-                styleClass = 'calendar-day-left %s'.format(styleClass);
+                styleClass = `calendar-day-left ${styleClass}`;
 
             if (sameDay(now, iter))
                 styleClass += ' calendar-today';
@@ -1029,7 +1029,7 @@ class CalendarMessageList extends St.Widget {
 
         for (let prop of ['visible', 'empty', 'can-clear']) {
             connectionsIds.push(
-                section.connect('notify::%s'.format(prop), this._sync.bind(this)));
+                section.connect(`notify::${prop}`, this._sync.bind(this)));
         }
         connectionsIds.push(section.connect('message-focused', (_s, messageActor) => {
             Util.ensureActorVisibleInScrollView(this._scrollView, messageActor);
diff --git a/js/ui/components/automountManager.js b/js/ui/components/automountManager.js
index 5f0a8aad50..86c3a824e3 100644
--- a/js/ui/components/automountManager.js
+++ b/js/ui/components/automountManager.js
@@ -112,7 +112,7 @@ var AutomountManager = class {
                     try {
                         drive.stop_finish(res);
                     } catch (e) {
-                        log('Unable to stop the drive after drive-eject-button %s'.format(e.toString()));
+                        log(`Unable to stop the drive after drive-eject-button ${e.toString()}`);
                     }
                 });
         } else if (drive.can_eject()) {
@@ -121,7 +121,7 @@ var AutomountManager = class {
                     try {
                         drive.eject_with_operation_finish(res);
                     } catch (e) {
-                        log('Unable to eject the drive after drive-eject-button %s'.format(e.toString()));
+                        log(`Unable to eject the drive after drive-eject-button ${e.toString()}`);
                     }
                 });
         }
@@ -208,7 +208,7 @@ var AutomountManager = class {
                 }
 
                 if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
-                    log('Unable to mount volume %s: %s'.format(volume.get_name(), e.toString()));
+                    log(`Unable to mount volume ${volume.get_name()}: ${e.toString()}`);
                 this._closeOperation(volume);
             }
         }
diff --git a/js/ui/components/autorunManager.js b/js/ui/components/autorunManager.js
index cc7b41274f..f26a2e5f75 100644
--- a/js/ui/components/autorunManager.js
+++ b/js/ui/components/autorunManager.js
@@ -66,7 +66,7 @@ function startAppForMount(app, mount) {
         retval = app.launch(files,
                             global.create_app_launch_context(0, -1));
     } catch (e) {
-        log('Unable to launch the application %s: %s'.format(app.get_name(), e.toString()));
+        log(`Unable to launch the application ${app.get_name()}: ${e}`);
     }
 
     return retval;
@@ -105,7 +105,7 @@ var ContentTypeDiscoverer = class {
         try {
             contentTypes = mount.guess_content_type_finish(res);
         } catch (e) {
-            log('Unable to guess content types on added mount %s: %s'.format(mount.get_name(), 
e.toString()));
+            log(`Unable to guess content types on added mount ${mount.get_name()}: ${e}`);
         }
 
         if (contentTypes.length) {
diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js
index 94772c0761..1960ad1e73 100644
--- a/js/ui/components/networkAgent.js
+++ b/js/ui/components/networkAgent.js
@@ -216,7 +216,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
         case 'none': // static WEP
             secrets.push({
                 label: _('Key'),
-                key: 'wep-key%s'.format(wirelessSecuritySetting.wep_tx_keyidx),
+                key: `wep-key${wirelessSecuritySetting.wep_tx_keyidx}`,
                 value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
                 wep_key_type: wirelessSecuritySetting.wep_key_type,
                 validate: this._validateStaticWep,
@@ -239,7 +239,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
             this._get8021xSecrets(secrets);
             break;
         default:
-            log('Invalid wireless key management: %s'.format(wirelessSecuritySetting.key_mgmt));
+            log(`Invalid wireless key management: ${wirelessSecuritySetting.key_mgmt}`);
         }
     }
 
@@ -312,7 +312,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
             });
             break;
         default:
-            log('Invalid EAP/IEEE802.1x method: %s'.format(ieee8021xSetting.get_eap_method(0)));
+            log(`Invalid EAP/IEEE802.1x method: ${ieee8021xSetting.get_eap_method(0)}`);
         }
     }
 
@@ -404,7 +404,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
             this._getMobileSecrets(content.secrets, connectionType);
             break;
         default:
-            log('Invalid connection type: %s'.format(connectionType));
+            log(`Invalid connection type: ${connectionType}`);
         }
 
         return content;
@@ -648,12 +648,12 @@ var VPNRequestHandler = class {
 
         try {
             vpnSetting.foreach_data_item((key, value) => {
-                this._stdin.write('DATA_KEY=%s\n'.format(key), null);
-                this._stdin.write('DATA_VAL=%s\n\n'.format(value || ''), null);
+                this._stdin.write(`DATA_KEY=${key}\n`, null);
+                this._stdin.write(`DATA_VAL=${value || ''}\n\n`, null);
             });
             vpnSetting.foreach_secret((key, value) => {
-                this._stdin.write('SECRET_KEY=%s\n'.format(key), null);
-                this._stdin.write('SECRET_VAL=%s\n\n'.format(value || ''), null);
+                this._stdin.write(`SECRET_KEY=${key}\n`, null);
+                this._stdin.write(`SECRET_VAL=${value || ''}\n\n`, null);
             });
             this._stdin.write('DONE\n\n', null);
         } catch (e) {
@@ -768,7 +768,7 @@ var NetworkAgent = class {
             body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
             break;
         default:
-            log('Invalid connection type: %s'.format(connectionType));
+            log(`Invalid connection type: ${connectionType}`);
             this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
             return;
         }
@@ -855,7 +855,7 @@ var NetworkAgent = class {
 
         const fileName = plugin.get_auth_dialog();
         if (!GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
-            log('VPN plugin at %s is not executable'.format(fileName));
+            log(`VPN plugin at ${fileName} is not executable`);
             return null;
         }
 
diff --git a/js/ui/components/polkitAgent.js b/js/ui/components/polkitAgent.js
index 5127ab924d..eda2e237c1 100644
--- a/js/ui/components/polkitAgent.js
+++ b/js/ui/components/polkitAgent.js
@@ -44,7 +44,7 @@ var AuthenticationDialog = GObject.registerClass({
         let bodyContent = new Dialog.MessageDialogContent();
 
         if (userNames.length > 1) {
-            log('polkitAuthenticationAgent: Received %d '.format(userNames.length) +
+            log(`polkitAuthenticationAgent: Received ${userNames.length} ` +
                 'identities that can be used for authentication. Only ' +
                 'considering one.');
         }
@@ -193,8 +193,8 @@ var AuthenticationDialog = GObject.registerClass({
             // We could add retrying if this turns out to be a problem
 
             log('polkitAuthenticationAgent: Failed to show modal dialog. ' +
-                'Dismissing authentication request for action-id %s '.format(this.actionId) +
-                'cookie %s'.format(this._cookie));
+                `Dismissing authentication request for action-id ${this.actionId} ` +
+                `cookie ${this._cookie}`);
             this._emitDone(true);
         }
     }
diff --git a/js/ui/components/telepathyClient.js b/js/ui/components/telepathyClient.js
index 859a7e64fb..90c0cbdf42 100644
--- a/js/ui/components/telepathyClient.js
+++ b/js/ui/components/telepathyClient.js
@@ -114,7 +114,7 @@ var TelepathyComponent = class {
         try {
             this._client.register();
         } catch (e) {
-            throw new Error('Could not register Telepathy client. Error: %s'.format(e.toString()));
+            throw new Error(`Could not register Telepathy client. Error: ${e}`);
         }
 
         if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
@@ -282,7 +282,7 @@ class TelepathyClient extends Tp.BaseClient {
             await dispatchOp.claim_with_async(this);
             this._handlingChannels(account, conn, [channel], false);
         } catch (err) {
-            log('Failed to Claim channel: %s'.format(err.toString()));
+            log(`Failed to claim channel: ${err}`);
         }
     }
 
@@ -702,7 +702,7 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
 
         if (message.messageType == Tp.ChannelTextMessageType.ACTION) {
             let senderAlias = GLib.markup_escape_text(message.sender, -1);
-            messageBody = '<i>%s</i> %s'.format(senderAlias, messageBody);
+            messageBody = `<i>${senderAlias}</i> ${messageBody}`;
             styles.push('chat-action');
         }
 
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
index 89289179ba..50a9118da9 100644
--- a/js/ui/dateMenu.js
+++ b/js/ui/dateMenu.js
@@ -13,7 +13,7 @@ const System = imports.system;
 
 const { loadInterfaceXML } = imports.misc.fileUtils;
 
-const NC_ = (context, str) => '%s\u0004%s'.format(context, str);
+const NC_ = (context, str) => `${context}\u0004${str}`;
 const T_ = Shell.util_translate_time_string;
 
 const MAX_FORECASTS = 5;
@@ -187,15 +187,15 @@ class EventsSection extends St.Button {
         const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
         if (event.date < this._startDate) {
             if (rtl)
-                title = '%s%s'.format(title, ELLIPSIS_CHAR);
+                title = `${title}${ELLIPSIS_CHAR}`;
             else
-                title = '%s%s'.format(ELLIPSIS_CHAR, title);
+                title = `${ELLIPSIS_CHAR}${title}`;
         }
         if (event.end > this._endDate) {
             if (rtl)
-                title = '%s%s'.format(ELLIPSIS_CHAR, title);
+                title = `${ELLIPSIS_CHAR}${title}`;
             else
-                title = '%s%s'.format(title, ELLIPSIS_CHAR);
+                title = `${title}${ELLIPSIS_CHAR}`;
         }
         return title;
     }
@@ -427,8 +427,8 @@ class WorldClocksSection extends St.Button {
 
         const prefix = offsetCurrentTz >= 0 ? '+' : '-';
         const text = offsetMinutes === 0
-            ? '%s%d'.format(prefix, offsetHours)
-            : '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
+            ? `${prefix}${offsetHours}`
+            : `${prefix}${offsetHours}\u2236${offsetMinutes}`;
         return text;
     }
 
@@ -449,7 +449,7 @@ class WorldClocksSection extends St.Button {
 
     _onProxyReady(proxy, error) {
         if (error) {
-            log('Failed to create GNOME Clocks proxy: %s'.format(error));
+            log(`Failed to create GNOME Clocks proxy: ${error}`);
             return;
         }
 
@@ -583,7 +583,7 @@ class WeatherSection extends St.Button {
             });
             let temp = new St.Label({
                 style_class: 'weather-forecast-temp',
-                text: '%s%d°'.format(tempPrefix, Math.round(tempValue)),
+                text: `${tempPrefix}${Math.round(tempValue)}°`,
                 x_align: Clutter.ActorAlign.CENTER,
             });
 
diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js
index 9f8bcb1ba1..f4227c2e09 100644
--- a/js/ui/endSessionDialog.js
+++ b/js/ui/endSessionDialog.js
@@ -169,7 +169,7 @@ function findAppFromInhibitor(inhibitor) {
     } catch (e) {
         // XXX -- sometimes JIT inhibitors generated by gnome-session
         // get removed too soon. Don't fail in this case.
-        log('gnome-session gave us a dead inhibitor: %s'.format(inhibitor.get_object_path()));
+        log(`gnome-session gave us a dead inhibitor: ${inhibitor.get_object_path()}`);
         return null;
     }
 
@@ -322,7 +322,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
             this._updatesPermission = await Polkit.Permission.new(
                 'org.freedesktop.packagekit.trigger-offline-update', null, null);
         } catch (e) {
-            log('No permission to trigger offline updates: %s'.format(e.toString()));
+            log(`No permission to trigger offline updates: ${e}`);
         }
     }
 
@@ -662,7 +662,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
                 if (!sessionId) {
                     this._loginManager.getCurrentSessionProxy(currentSessionProxy => {
                         sessionId = currentSessionProxy.Id;
-                        log('endSessionDialog: No XDG_SESSION_ID, fetched from logind: 
%d'.format(sessionId));
+                        log(`endSessionDialog: No XDG_SESSION_ID, fetched from logind: ${sessionId}`);
                     });
                 }
 
@@ -731,7 +731,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
             this._updateInfo = await this._getUpdateInfo();
         } catch (e) {
             if (this._pkOfflineProxy !== null)
-                log('Failed to get update info from PackageKit: %s'.format(e.message));
+                log(`Failed to get update info from PackageKit: ${e.message}`);
 
             this._updateInfo = {
                 UpdateTriggered: false,
diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js
index a3cfbf3f55..94ba8fad59 100644
--- a/js/ui/extensionDownloader.js
+++ b/js/ui/extensionDownloader.js
@@ -92,7 +92,7 @@ function checkResponse(message) {
     const { statusCode } = message;
     const phrase = Soup.Status.get_phrase(statusCode);
     if (statusCode !== Soup.Status.OK)
-        throw new Error('Unexpected response: %s'.format(phrase));
+        throw new Error(`Unexpected response: ${phrase}`);
 }
 
 /**
@@ -141,8 +141,7 @@ async function downloadExtensionUpdate(uuid) {
         await extractExtensionArchive(bytes, dir);
         Main.extensionManager.notifyExtensionUpdate(uuid);
     } catch (e) {
-        log('Error while downloading update for extension %s: %s'
-            .format(uuid, e.message));
+        log(`Error while downloading update for extension ${uuid}: (${e.message})`);
     }
 }
 
@@ -174,12 +173,12 @@ async function checkForUpdates() {
         'disable-extension-version-validation');
     const params = {
         shell_version: Config.PACKAGE_VERSION,
-        disable_version_validation: versionCheck.toString(),
+        disable_version_validation: `${versionCheck}`,
     };
     const requestBody = new GLib.Bytes(JSON.stringify(metadatas));
 
     const message = Soup.Message.new('POST',
-        '%s?%s'.format(REPOSITORY_URL_UPDATE, Soup.form_encode_hash(params)));
+        `${REPOSITORY_URL_UPDATE}?${Soup.form_encode_hash(params)}`);
     message.set_request_body_from_bytes('application/json', requestBody);
 
     let json;
@@ -191,7 +190,7 @@ async function checkForUpdates() {
         checkResponse(message);
         json = new TextDecoder().decode(bytes.get_data());
     } catch (e) {
-        log('Update check failed: %s'.format(e.message));
+        log(`Update check failed: ${e.message}`);
         return;
     }
 
@@ -207,7 +206,7 @@ async function checkForUpdates() {
         await Promise.allSettled(
             updates.map(uuid => downloadExtensionUpdate(uuid)));
     } catch (e) {
-        log('Some extension updates failed to download: %s'.format(e.message));
+        log(`Some extension updates failed to download: ${e.message}`);
     }
 }
 
@@ -267,11 +266,11 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
                 this._uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
             Main.extensionManager.loadExtension(extension);
             if (!Main.extensionManager.enableExtension(this._uuid))
-                throw new Error('Cannot enable %s'.format(this._uuid));
+                throw new Error(`Cannot enable ${this._uuid}`);
 
             this._invocation.return_value(new GLib.Variant('(s)', ['successful']));
         } catch (e) {
-            log('Error while installing %s: %s'.format(this._uuid, e.message));
+            log(`Error while installing ${this._uuid}: ${e.message}`);
             this._invocation.return_dbus_error(
                 'org.gnome.Shell.ExtensionError', e.message);
         }
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index eec3693a46..41a03fdf3a 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -43,7 +43,7 @@ var ExtensionManager = class {
         try {
             disableFile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, null);
         } catch (e) {
-            log('Failed to create file %s: %s'.format(disableFilename, e.message));
+            log(`Failed to create file ${disableFilename}: ${e.message}`);
         }
 
         GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
@@ -161,7 +161,7 @@ var ExtensionManager = class {
         if (extension.state != ExtensionState.DISABLED)
             return;
 
-        let stylesheetNames = ['%s.css'.format(global.session_mode), 'stylesheet.css'];
+        let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
         let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
         for (let i = 0; i < stylesheetNames.length; i++) {
             try {
@@ -286,7 +286,7 @@ var ExtensionManager = class {
             extension.errors = [];
         extension.errors.push(message);
 
-        logError(error, 'Extension %s'.format(uuid));
+        logError(error, `Extension ${uuid}`);
         this._updateCanChange(extension);
         this.emit('extension-state-changed', extension);
     }
@@ -301,24 +301,24 @@ var ExtensionManager = class {
             [success_, metadataContents] = metadataFile.load_contents(null);
             metadataContents = new TextDecoder().decode(metadataContents);
         } catch (e) {
-            throw new Error('Failed to load metadata.json: %s'.format(e.toString()));
+            throw new Error(`Failed to load metadata.json: ${e}`);
         }
         let meta;
         try {
             meta = JSON.parse(metadataContents);
         } catch (e) {
-            throw new Error('Failed to parse metadata.json: %s'.format(e.toString()));
+            throw new Error(`Failed to parse metadata.json: ${e}`);
         }
 
         let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
         for (let i = 0; i < requiredProperties.length; i++) {
             let prop = requiredProperties[i];
             if (!meta[prop])
-                throw new Error('missing "%s" property in metadata.json'.format(prop));
+                throw new Error(`missing "${prop}" property in metadata.json`);
         }
 
         if (uuid != meta.uuid)
-            throw new Error('uuid "%s" from metadata.json does not match directory name 
"%s"'.format(meta.uuid, uuid));
+            throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name 
"${uuid}"`);
 
         let extension = {
             metadata: meta,
@@ -561,7 +561,7 @@ var ExtensionManager = class {
                 FileUtils.recursivelyDeleteDir(extensionDir, false);
                 FileUtils.recursivelyMoveDir(dir, extensionDir);
             } catch (e) {
-                log('Failed to install extension updates for %s'.format(uuid));
+                log(`Failed to install extension updates for ${uuid}`);
             } finally {
                 FileUtils.recursivelyDeleteDir(dir, true);
             }
@@ -569,17 +569,17 @@ var ExtensionManager = class {
     }
 
     _loadExtensions() {
-        global.settings.connect('changed::%s'.format(ENABLED_EXTENSIONS_KEY),
+        global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`,
             this._onEnabledExtensionsChanged.bind(this));
-        global.settings.connect('changed::%s'.format(DISABLED_EXTENSIONS_KEY),
+        global.settings.connect(`changed::${DISABLED_EXTENSIONS_KEY}`,
             this._onEnabledExtensionsChanged.bind(this));
-        global.settings.connect('changed::%s'.format(DISABLE_USER_EXTENSIONS_KEY),
+        global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`,
             this._onUserExtensionsEnabledChanged.bind(this));
-        global.settings.connect('changed::%s'.format(EXTENSION_DISABLE_VERSION_CHECK_KEY),
+        global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`,
             this._onVersionValidationChanged.bind(this));
-        global.settings.connect('writable-changed::%s'.format(ENABLED_EXTENSIONS_KEY),
+        global.settings.connect(`writable-changed::${ENABLED_EXTENSIONS_KEY}`,
             this._onSettingsWritableChanged.bind(this));
-        global.settings.connect('writable-changed::%s'.format(DISABLED_EXTENSIONS_KEY),
+        global.settings.connect(`writable-changed::${DISABLED_EXTENSIONS_KEY}`,
             this._onSettingsWritableChanged.bind(this));
 
         this._onVersionValidationChanged();
@@ -594,7 +594,7 @@ var ExtensionManager = class {
             let uuid = info.get_name();
             let existing = this.lookup(uuid);
             if (existing) {
-                log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, 
existing.path, dir.get_path()));
+                log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be 
loaded`);
                 return;
             }
 
@@ -605,7 +605,7 @@ var ExtensionManager = class {
             try {
                 extension = this.createExtensionObject(uuid, dir, type);
             } catch (e) {
-                logError(e, 'Could not load extension %s'.format(uuid));
+                logError(e, `Could not load extension ${uuid}`);
                 return;
             }
             this.loadExtension(extension);
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index cff4a6f8e1..75df02de66 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -555,7 +555,8 @@ var KeyboardModel = class {
     }
 
     _loadModel(groupName) {
-        let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(groupName));
+        const file = Gio.File.new_for_uri(
+            `resource:///org/gnome/shell/osk-layouts/${groupName}.json`);
         let [success_, contents] = file.load_contents(null);
 
         const decoder = new TextDecoder();
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index f2c7874781..bff753ec50 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -252,13 +252,7 @@ function objectToString(o) {
         // special case this since the default is way, way too verbose
         return '<js function>';
     } else {
-        if (o === undefined)
-            return 'undefined';
-
-        if (o === null)
-            return 'null';
-
-        return o.toString();
+        return `${o}`;
     }
 }
 
@@ -305,7 +299,7 @@ class Result extends St.BoxLayout {
         this.add(cmdTxt);
         let box = new St.BoxLayout({});
         this.add(box);
-        let resultTxt = new St.Label({ text: 'r(%d) = '.format(index) });
+        let resultTxt = new St.Label({ text: `r(${index}) = ` });
         resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
         box.add(resultTxt);
         let objLink = new ObjLink(this._lookingGlass, o);
@@ -345,7 +339,7 @@ var WindowList = GObject.registerClass({
             box.add_child(windowLink);
             let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
             box.add(propsBox);
-            propsBox.add(new St.Label({ text: 'wmclass: %s'.format(metaWindow.get_wm_class()) }));
+            propsBox.add(new St.Label({ text: `wmclass: ${metaWindow.get_wm_class()}` }));
             let app = tracker.get_window_app(metaWindow);
             if (app != null && !app.is_window_backed()) {
                 let icon = app.create_icon_texture(22);
@@ -403,7 +397,7 @@ class ObjInspector extends St.ScrollView {
         let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' });
         this._container.add_actor(hbox);
         let label = new St.Label({
-            text: 'Inspecting: %s: %s'.format(typeof obj, objectToString(obj)),
+            text: `Inspecting: ${typeof obj}: ${objectToString(obj)}`,
             x_expand: true,
         });
         label.single_line_mode = true;
@@ -438,7 +432,7 @@ class ObjInspector extends St.ScrollView {
                     link = new St.Label({ text: '<error>' });
                 }
                 let box = new St.BoxLayout();
-                box.add(new St.Label({ text: '%s: '.format(propName) }));
+                box.add(new St.Label({ text: `${propName}: ` }));
                 box.add(link);
                 this._container.add_actor(box);
             }
@@ -665,9 +659,9 @@ var Inspector = GObject.registerClass({
             this._target = target;
         this._pointerTarget = target;
 
-        let position = '[inspect x: %d y: %d]'.format(stageX, stageY);
+        let position = `[inspect x: ${stageX} y: ${stageY}]`;
         this._displayText.text = '';
-        this._displayText.text = '%s %s'.format(position, this._target);
+        this._displayText.text = `${position} ${this._target}`;
 
         this._lookingGlass.setBorderPaintTarget(this._target);
     }
@@ -1176,7 +1170,7 @@ class DebugFlags extends St.BoxLayout {
 
         // Clutter debug flags
         for (const [categoryName, props] of CLUTTER_DEBUG_FLAG_CATEGORIES.entries()) {
-            this._addHeader('Clutter%s'.format(categoryName));
+            this._addHeader(`Clutter${categoryName}`);
             for (const flagName of this._getFlagNames(Clutter[categoryName])) {
                 if (props.exclude.includes(flagName))
                     continue;
@@ -1274,7 +1268,7 @@ class LookingGlass extends St.BoxLayout {
         inspectButton.connect('clicked', () => {
             let inspector = new Inspector(this);
             inspector.connect('target', (i, target, stageX, stageY) => {
-                this._pushResult('inspect(%d, %d)'.format(Math.round(stageX), Math.round(stageY)), target);
+                this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target);
             });
             inspector.connect('closed', () => {
                 this.show();
@@ -1388,8 +1382,9 @@ class LookingGlass extends St.BoxLayout {
         // monospace font to be bold/oblique/etc. Could easily be added here.
         let size = fontDesc.get_size() / 1024.;
         let unit = fontDesc.get_size_is_absolute() ? 'px' : 'pt';
-        this.style = 'font-size: %d%s; font-family: "%s";'.format(
-            size, unit, fontDesc.get_family());
+        this.style = `
+            font-size: ${size}${unit};
+            font-family: "${fontDesc.get_family()}";`;
     }
 
     setBorderPaintTarget(obj) {
@@ -1472,7 +1467,7 @@ class LookingGlass extends St.BoxLayout {
             return;
 
         let lines = command.split(';');
-        lines.push('return %s'.format(lines.pop()));
+        lines.push(`return ${lines.pop()}`);
 
         let fullCmd = commandHeader + lines.join(';');
 
@@ -1480,7 +1475,7 @@ class LookingGlass extends St.BoxLayout {
         try {
             resultObj = Function(fullCmd)();
         } catch (e) {
-            resultObj = '<exception %s>'.format(e.toString());
+            resultObj = `<exception ${e}>`;
         }
 
         this._pushResult(command, resultObj);
@@ -1499,7 +1494,7 @@ class LookingGlass extends St.BoxLayout {
         try {
             return this._resultsArea.get_child_at_index(idx - this._offset).o;
         } catch (e) {
-            throw new Error('Unknown result at index %d'.format(idx));
+            throw new Error(`Unknown result at index ${idx}`);
         }
     }
 
diff --git a/js/ui/main.js b/js/ui/main.js
index ce019471b5..908688c5a6 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -303,7 +303,7 @@ function _initializeUI() {
         if (sessionMode.currentMode != 'gdm' &&
             sessionMode.currentMode != 'initial-setup') {
             GLib.log_structured(LOG_DOMAIN, GLib.LogLevelFlags.LEVEL_MESSAGE, {
-                'MESSAGE': 'GNOME Shell started at %s'.format(_startDate),
+                'MESSAGE': `GNOME Shell started at ${_startDate}`,
                 'MESSAGE_ID': GNOMESHELL_STARTED_MESSAGE_ID,
             });
         }
@@ -325,7 +325,7 @@ function _initializeUI() {
         let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
         if (perfModuleName) {
             let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
-            let module = eval('imports.perf.%s;'.format(perfModuleName));
+            let module = eval(`imports.perf.${perfModuleName};`);
             Scripting.runPerfScript(module, perfOutput);
         }
     });
@@ -340,7 +340,7 @@ function _handleShowWelcomeScreen() {
 }
 
 async function _handleLockScreenWarning() {
-    const path = '%s/lock-warning-shown'.format(global.userdatadir);
+    const path = `${global.userdatadir}/lock-warning-shown`;
     const file = Gio.File.new_for_path(path);
 
     const hasLockScreen = screenShield !== null;
@@ -368,7 +368,7 @@ async function _handleLockScreenWarning() {
 function _getStylesheet(name) {
     let stylesheet;
 
-    stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/%s'.format(name));
+    stylesheet = Gio.File.new_for_uri(`resource:///org/gnome/shell/theme/${name}`);
     if (stylesheet.query_exists(null))
         return stylesheet;
 
@@ -380,7 +380,7 @@ function _getStylesheet(name) {
             return stylesheet;
     }
 
-    stylesheet = Gio.File.new_for_path('%s/theme/%s'.format(global.datadir, name));
+    stylesheet = Gio.File.new_for_path(`${global.datadir}/theme/${name}`);
     if (stylesheet.query_exists(null))
         return stylesheet;
 
@@ -437,19 +437,19 @@ function reloadThemeResource() {
     if (_themeResource)
         _themeResource._unregister();
 
-    _themeResource = Gio.Resource.load('%s/%s'.format(global.datadir,
-        sessionMode.themeResourceName));
+    _themeResource = Gio.Resource.load(
+        `${global.datadir}/${sessionMode.themeResourceName}`);
     _themeResource._register();
 }
 
 /** @private */
 function _loadIcons() {
-    _iconResource = Gio.Resource.load('%s/gnome-shell-icons.gresource'.format(global.datadir));
+    _iconResource = Gio.Resource.load(`${global.datadir}/gnome-shell-icons.gresource`);
     _iconResource._register();
 }
 
 function _loadOskLayouts() {
-    _oskResource = Gio.Resource.load('%s/gnome-shell-osk-layouts.gresource'.format(global.datadir));
+    _oskResource = Gio.Resource.load(`${global.datadir}/gnome-shell-osk-layouts.gresource`);
     _oskResource._register();
 }
 
@@ -468,7 +468,7 @@ function loadTheme() {
     });
 
     if (theme.default_stylesheet == null)
-        throw new Error("No valid stylesheet found for '%s'".format(sessionMode.stylesheetName));
+        throw new Error(`No valid stylesheet found for '${sessionMode.stylesheetName}'`);
 
     if (previousTheme) {
         let customStylesheets = previousTheme.get_custom_stylesheets();
@@ -503,9 +503,9 @@ function notify(msg, details) {
 function notifyError(msg, details) {
     // Also print to stderr so it's logged somewhere
     if (details)
-        log('error: %s: %s'.format(msg, details));
+        log(`error: ${msg}: ${details}`);
     else
-        log('error: %s'.format(msg));
+        log(`error: ${msg}`);
 
     notify(msg, details);
 }
@@ -787,7 +787,7 @@ function _queueBeforeRedraw(workId) {
  */
 function initializeDeferredWork(actor, callback) {
     // Turn into a string so we can use as an object property
-    let workId = (++_deferredWorkSequence).toString();
+    let workId = `${++_deferredWorkSequence}`;
     _deferredWorkData[workId] = { actor,
                                   callback };
     actor.connect('notify::mapped', () => {
@@ -817,7 +817,7 @@ function initializeDeferredWork(actor, callback) {
 function queueDeferredWork(workId) {
     let data = _deferredWorkData[workId];
     if (!data) {
-        let message = 'Invalid work id %d'.format(workId);
+        let message = `Invalid work id ${workId}`;
         logError(new Error(message), message);
         return;
     }
diff --git a/js/ui/messageList.js b/js/ui/messageList.js
index 77672a5928..45ebbf53d0 100644
--- a/js/ui/messageList.js
+++ b/js/ui/messageList.js
@@ -78,7 +78,7 @@ class URLHighlighter extends St.Label {
         if (urlId != -1) {
             let url = this._urls[urlId].url;
             if (!url.includes(':'))
-                url = 'http://%s'.format(url);
+                url = `http://${url}`;
 
             Gio.app_info_launch_default_for_uri(
                 url, global.create_app_launch_context(0, -1));
@@ -131,7 +131,7 @@ class URLHighlighter extends St.Label {
         for (let i = 0; i < urls.length; i++) {
             let url = urls[i];
             let str = this._text.substr(pos, url.pos - pos);
-            markup += '%s<span foreground="%s"><u>%s</u></span>'.format(str, this._linkColor, url.url);
+            markup += `${str}<span foreground="${this._linkColor}"><u>${url.url}</u></span>`;
             pos = url.pos + url.url.length;
         }
         markup += this._text.substr(pos);
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index de30767e5f..562d55636f 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -229,7 +229,7 @@ var NotificationApplicationPolicy = GObject.registerClass({
         this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
         this._settings = new Gio.Settings({
             schema_id: 'org.gnome.desktop.notifications.application',
-            path: '/org/gnome/desktop/notifications/application/%s/'.format(this._canonicalId),
+            path: `/org/gnome/desktop/notifications/application/${this._canonicalId}/`,
         });
 
         this._masterSettings.connect('changed', this._changed.bind(this));
@@ -237,7 +237,7 @@ var NotificationApplicationPolicy = GObject.registerClass({
     }
 
     store() {
-        this._settings.set_string('application-id', '%s.desktop'.format(this.id));
+        this._settings.set_string('application-id', `${this.id}.desktop`);
 
         let apps = this._masterSettings.get_strv('application-children');
         if (!apps.includes(this._canonicalId)) {
@@ -966,7 +966,7 @@ var MessageTray = GObject.registerClass({
 
     add(source) {
         if (this.contains(source)) {
-            log('Trying to re-add source %s'.format(source.title));
+            log(`Trying to re-add source ${source.title}`);
             return;
         }
 
diff --git a/js/ui/mpris.js b/js/ui/mpris.js
index b7cc8ea190..c672dcb900 100644
--- a/js/ui/mpris.js
+++ b/js/ui/mpris.js
@@ -150,7 +150,7 @@ var MprisPlayer = class MprisPlayer {
         // so prefer activating the app via .desktop file if possible
         let app = null;
         if (this._mprisProxy.DesktopEntry) {
-            let desktopId = '%s.desktop'.format(this._mprisProxy.DesktopEntry);
+            let desktopId = `${this._mprisProxy.DesktopEntry}.desktop`;
             app = Shell.AppSystem.get_default().lookup_app(desktopId);
         }
 
@@ -200,9 +200,9 @@ var MprisPlayer = class MprisPlayer {
         if (!Array.isArray(this._trackArtists) ||
             !this._trackArtists.every(artist => typeof artist === 'string')) {
             if (typeof this._trackArtists !== 'undefined') {
-                log(('Received faulty track artist metadata from %s; ' +
-                    'expected an array of strings, got %s (%s)').format(
-                    this._busName, this._trackArtists, typeof this._trackArtists));
+                log(`Received faulty track artist metadata from ${
+                    this._busName}; expected an array of strings, got ${
+                    this._trackArtists} (${typeof this._trackArtists})`);
             }
             this._trackArtists =  [_("Unknown artist")];
         }
@@ -210,9 +210,9 @@ var MprisPlayer = class MprisPlayer {
         this._trackTitle = metadata['xesam:title'];
         if (typeof this._trackTitle !== 'string') {
             if (typeof this._trackTitle !== 'undefined') {
-                log(('Received faulty track title metadata from %s; ' +
-                    'expected a string, got %s (%s)').format(
-                    this._busName, this._trackTitle, typeof this._trackTitle));
+                log(`Received faulty track title metadata from ${
+                    this._busName}; expected a string, got ${
+                    this._trackTitle} (${typeof this._trackTitle})`);
             }
             this._trackTitle = _("Unknown title");
         }
@@ -220,9 +220,9 @@ var MprisPlayer = class MprisPlayer {
         this._trackCoverUrl = metadata['mpris:artUrl'];
         if (typeof this._trackCoverUrl !== 'string') {
             if (typeof this._trackCoverUrl !== 'undefined') {
-                log(('Received faulty track cover art metadata from %s; ' +
-                    'expected a string, got %s (%s)').format(
-                    this._busName, this._trackCoverUrl, typeof this._trackCoverUrl));
+                log(`Received faulty track cover art metadata from ${
+                    this._busName}; expected a string, got ${
+                    this._trackCoverUrl} (${typeof this._trackCoverUrl})`);
             }
             this._trackCoverUrl = '';
         }
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
index 954ce80687..c2645586f9 100644
--- a/js/ui/notificationDaemon.js
+++ b/js/ui/notificationDaemon.js
@@ -412,10 +412,10 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
             return app;
 
         if (appId)
-            app = appSys.lookup_app('%s.desktop'.format(appId));
+            app = appSys.lookup_app(`${appId}.desktop`);
 
         if (!app)
-            app = appSys.lookup_app('%s.desktop'.format(this.initialTitle));
+            app = appSys.lookup_app(`${this.initialTitle}.desktop`);
 
         return app;
     }
@@ -549,7 +549,7 @@ function objectPathFromAppId(appId) {
 }
 
 function getPlatformData() {
-    let startupId = GLib.Variant.new('s', '_TIME%s'.format(global.get_current_time()));
+    let startupId = GLib.Variant.new('s', `_TIME${global.get_current_time()}`);
     return { "desktop-startup-id": startupId };
 }
 
@@ -562,7 +562,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
         if (!GLib.Variant.is_object_path(objectPath))
             throw new InvalidAppError();
 
-        let app = Shell.AppSystem.get_default().lookup_app('%s.desktop'.format(appId));
+        let app = Shell.AppSystem.get_default().lookup_app(`${appId}.desktop`);
         if (!app)
             throw new InvalidAppError();
 
@@ -738,7 +738,8 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
             source = this._ensureAppSource(appId);
         } catch (e) {
             if (e instanceof InvalidAppError) {
-                invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could 
not be found'.format(appId));
+                invocation.return_dbus_error('org.gtk.Notifications.InvalidApp',
+                    `The app by ID "${appId}" could not be found`);
                 return;
             }
             throw e;
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 2a603ba02f..bea0935729 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -390,7 +390,7 @@ var Overview = class {
             this._shown = false;
             this._visibleTarget = false;
             this.emit('hiding');
-            Main.panel.style = 'transition-duration: %dms;'.format(duration);
+            Main.panel.style = `transition-duration: ${duration}ms;`;
             onComplete = () => this._hideDone();
         } else {
             onComplete = () => this._showDone();
diff --git a/js/ui/padOsd.js b/js/ui/padOsd.js
index 8362b101d5..b58e4eeb46 100644
--- a/js/ui/padOsd.js
+++ b/js/ui/padOsd.js
@@ -354,7 +354,7 @@ var PadDiagram = GObject.registerClass({
         return '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
                '<svg version="1.1" xmlns="http://www.w3.org/2000/svg"; ' +
                'xmlns:xi="http://www.w3.org/2001/XInclude"; ' +
-               'width="%d" height="%d">'.format(this._imageWidth, this._imageHeight) +
+               `width="${this._imageWidth}" height="${this._imageHeight}"> ` +
                '<style type="text/css">';
     }
 
@@ -369,8 +369,8 @@ var PadDiagram = GObject.registerClass({
 
         for (let i = 0; i < this._activeButtons.length; i++) {
             let ch = String.fromCharCode('A'.charCodeAt() + this._activeButtons[i]);
-            css += '.%s.Leader { stroke: %s !important; }'.format(ch, ACTIVE_COLOR);
-            css += '.%s.Button { stroke: %s !important; fill: %s !important; }'.format(ch, ACTIVE_COLOR, 
ACTIVE_COLOR);
+            css += `.${ch}.Leader { stroke: ${ACTIVE_COLOR} !important; }`;
+            css += `.${ch}.Button { stroke: ${ACTIVE_COLOR} !important; fill: ${ACTIVE_COLOR} !important; }`;
         }
 
         return css;
@@ -471,12 +471,12 @@ var PadDiagram = GObject.registerClass({
         let leaderPos, leaderSize, pos;
         let found, direction;
 
-        [found, pos] = this._handle.get_position_sub('#%s'.format(labelName));
+        [found, pos] = this._handle.get_position_sub(`#${labelName}`);
         if (!found)
             return [false];
 
-        [found, leaderPos] = this._handle.get_position_sub('#%s'.format(leaderName));
-        [found, leaderSize] = this._handle.get_dimensions_sub('#%s'.format(leaderName));
+        [found, leaderPos] = this._handle.get_position_sub(`#${leaderName}`);
+        [found, leaderSize] = this._handle.get_dimensions_sub(`#${leaderName}`);
         if (!found)
             return [false];
 
@@ -496,24 +496,24 @@ var PadDiagram = GObject.registerClass({
 
     _getButtonLabels(button) {
         let ch = String.fromCharCode('A'.charCodeAt() + button);
-        let labelName = 'Label%s'.format(ch);
-        let leaderName = 'Leader%s'.format(ch);
+        const labelName = `Label${ch}`;
+        const leaderName = `Leader${ch}`;
         return [labelName, leaderName];
     }
 
     _getRingLabels(number, dir) {
         let numStr = number > 0 ? (number + 1).toString() : '';
         let dirStr = dir == CW ? 'CW' : 'CCW';
-        let labelName = 'LabelRing%s%s'.format(numStr, dirStr);
-        let leaderName = 'LeaderRing%s%s'.format(numStr, dirStr);
+        const labelName = `LabelRing${numStr}${dirStr}`;
+        const leaderName = `LeaderRing${numStr}${dirStr}`;
         return [labelName, leaderName];
     }
 
     _getStripLabels(number, dir) {
         let numStr = number > 0 ? (number + 1).toString() : '';
         let dirStr = dir == UP ? 'Up' : 'Down';
-        let labelName = 'LabelStrip%s%s'.format(numStr, dirStr);
-        let leaderName = 'LeaderStrip%s%s'.format(numStr, dirStr);
+        const labelName = `LabelStrip${numStr}${dirStr}`;
+        const leaderName = `LeaderStrip${numStr}${dirStr}`;
         return [labelName, leaderName];
     }
 
@@ -894,19 +894,19 @@ var PadOsd = GObject.registerClass({
 
     _startButtonActionEdition(button) {
         let ch = String.fromCharCode('A'.charCodeAt() + button);
-        let key = 'button%s'.format(ch);
+        let key = `button${ch}`;
         this._startActionEdition(key, Meta.PadActionType.BUTTON, button);
     }
 
     _startRingActionEdition(ring, dir, mode) {
         let ch = String.fromCharCode('A'.charCodeAt() + ring);
-        let key = 'ring%s-%s-mode-%d'.format(ch, dir == CCW ? 'ccw' : 'cw', mode);
+        const key = `ring${ch}-${dir === CCW ? 'ccw' : 'cw'}-mode-${mode}`;
         this._startActionEdition(key, Meta.PadActionType.RING, ring, dir, mode);
     }
 
     _startStripActionEdition(strip, dir, mode) {
         let ch = String.fromCharCode('A'.charCodeAt() + strip);
-        let key = 'strip%s-%s-mode-%d'.format(ch, dir == UP ? 'up' : 'down', mode);
+        const key = `strip${ch}-${dir === UP ? 'up' : 'down'}-mode-${mode}`;
         this._startActionEdition(key, Meta.PadActionType.STRIP, strip, dir, mode);
     }
 
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 1530946434..ea40998a51 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -755,7 +755,7 @@ class Panel extends St.Widget {
 
     addToStatusArea(role, indicator, position, box) {
         if (this.statusArea[role])
-            throw new Error('Extension point conflict: there is already a status indicator for role 
%s'.format(role));
+            throw new Error(`Extension point conflict: there is already a status indicator for role 
${role}`);
 
         if (!(indicator instanceof PanelMenu.Button))
             throw new TypeError('Status indicator must be an instance of PanelMenu.Button');
diff --git a/js/ui/panelMenu.js b/js/ui/panelMenu.js
index 0c2478f8db..75b6ba5f5d 100644
--- a/js/ui/panelMenu.js
+++ b/js/ui/panelMenu.js
@@ -181,7 +181,7 @@ var Button = GObject.registerClass({
         // measures are in logical pixels, so make sure to consider the scale
         // factor when computing max-height
         let maxHeight = Math.round((workArea.height - verticalMargins) / scaleFactor);
-        this.menu.actor.style = 'max-height: %spx;'.format(maxHeight);
+        this.menu.actor.style = `max-height: ${maxHeight}px;`;
     }
 
     _onDestroy() {
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index f3e014667e..f30c011468 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -477,7 +477,7 @@ class PopupImageMenuItem extends PopupBaseMenuItem {
 var PopupMenuBase = class {
     constructor(sourceActor, styleClass) {
         if (this.constructor === PopupMenuBase)
-            throw new TypeError('Cannot instantiate abstract class %s'.format(this.constructor.name));
+            throw new TypeError(`Cannot instantiate abstract class ${this.constructor.name}`);
 
         this.sourceActor = sourceActor;
         this.focusActor = sourceActor;
@@ -557,7 +557,7 @@ var PopupMenuBase = class {
             let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
 
             if (!app) {
-                log('Settings panel for desktop file %s could not be loaded!'.format(desktopFile));
+                log(`Settings panel for desktop file ${desktopFile} could not be loaded!`);
                 return;
             }
 
diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js
index cfcf1e89d6..368afc5dae 100644
--- a/js/ui/remoteSearch.js
+++ b/js/ui/remoteSearch.js
@@ -126,7 +126,7 @@ function loadRemoteSearchProviders(searchSettings, callback) {
             objectPaths[objectPath] = remoteProvider;
             loadedProviders.push(remoteProvider);
         } catch (e) {
-            log('Failed to add search provider %s: %s'.format(path, e.toString()));
+            log(`Failed to add search provider ${path}: ${e}`);
         }
     }
 
@@ -247,7 +247,7 @@ var RemoteSearchProvider = class {
             if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                 return;
 
-            log('Received error from D-Bus search provider %s: %s'.format(this.id, String(error)));
+            log(`Received error from D-Bus search provider ${this.id}: ${error}`);
             callback([]);
             return;
         }
@@ -274,7 +274,7 @@ var RemoteSearchProvider = class {
     _getResultMetasFinished(results, error, callback) {
         if (error) {
             if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
-                log('Received error from D-Bus search provider %s during GetResultMetas: %s'.format(this.id, 
String(error)));
+                log(`Received error from D-Bus search provider ${this.id} during GetResultMetas: ${error}`);
             callback([]);
             return;
         }
diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js
index 4d1bac142a..2fda4e2082 100644
--- a/js/ui/runDialog.js
+++ b/js/ui/runDialog.js
@@ -194,7 +194,7 @@ class RunDialog extends ModalDialog.ModalDialog {
                 if (inTerminal) {
                     let exec = this._terminalSettings.get_string(EXEC_KEY);
                     let execArg = this._terminalSettings.get_string(EXEC_ARG_KEY);
-                    command = '%s %s %s'.format(exec, execArg, input);
+                    command = `${exec} ${execArg} ${input}`;
                 }
                 Util.trySpawnCommandLine(command);
             } catch (e) {
@@ -205,7 +205,7 @@ class RunDialog extends ModalDialog.ModalDialog {
                 } else if (input) {
                     if (input.charAt(0) == '~')
                         input = input.slice(1);
-                    path = '%s/%s'.format(GLib.get_home_dir(), input);
+                    path = `${GLib.get_home_dir()}/${input}`;
                 }
 
                 if (path && GLib.file_test(path, GLib.FileTest.EXISTS)) {
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 3d1a6eb1ad..bf4bf04a8c 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -112,10 +112,10 @@ var ScreenShield = class {
         });
 
         this._settings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA });
-        this._settings.connect('changed::%s'.format(LOCK_ENABLED_KEY), this._syncInhibitor.bind(this));
+        this._settings.connect(`changed::${LOCK_ENABLED_KEY}`, this._syncInhibitor.bind(this));
 
         this._lockSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
-        this._lockSettings.connect('changed::%s'.format(DISABLE_LOCK_KEY), this._syncInhibitor.bind(this));
+        this._lockSettings.connect(`changed::${DISABLE_LOCK_KEY}`, this._syncInhibitor.bind(this));
 
         this._isModal = false;
         this._isGreeter = false;
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index c7ae64949a..11f8199dd1 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -1488,7 +1488,7 @@ var ScreenshotUI = GObject.registerClass({
 
                 this._stageScreenshotContainer.show();
             } catch (e) {
-                log('Error capturing screenshot: %s'.format(e.message));
+                log(`Error capturing screenshot: ${e.message}`);
             }
             this._openingCoroutineInProgress = false;
         }
@@ -1835,7 +1835,7 @@ var ScreenshotUI = GObject.registerClass({
                 ([success, path], error) => {
                     if (error !== null) {
                         this._setScreencastInProgress(false);
-                        log('Error starting screencast: %s'.format(error.message));
+                        log(`Error starting screencast: ${error.message}`);
                         return;
                     }
 
@@ -1884,7 +1884,7 @@ var ScreenshotUI = GObject.registerClass({
 
         this._screencastProxy.StopScreencastRemote((success, error) => {
             if (error !== null) {
-                log('Error stopping screencast: %s'.format(error.message));
+                log(`Error stopping screencast: ${error.message}`);
                 return;
             }
 
@@ -2046,7 +2046,7 @@ function _storeScreenshot(bytes, pixbuf) {
         yield '';
 
         for (let i = 1; ; i++)
-            yield '-%s'.format(i);
+            yield `-${i}`;
     }
 
     const lockdownSettings =
@@ -2077,7 +2077,7 @@ function _storeScreenshot(bytes, pixbuf) {
         // increasing number to it.
         for (const suffix of suffixes()) {
             file = Gio.File.new_for_path(GLib.build_filenamev([
-                dir.get_path(), '%s%s.png'.format(name, suffix),
+                dir.get_path(), `${name}${suffix}.png`,
             ]));
 
             try {
@@ -2289,11 +2289,11 @@ var ScreenshotService = class {
             return null;
 
         yield Gio.File.new_for_path(
-            GLib.build_filenamev([path, '%s.png'.format(filename)]));
+            GLib.build_filenamev([path, `${filename}.png`]));
 
         for (let idx = 1; ; idx++) {
             yield Gio.File.new_for_path(
-                GLib.build_filenamev([path, '%s-%s.png'.format(filename, idx)]));
+                GLib.build_filenamev([path, `${filename}-${idx}.png`]));
         }
     }
 
diff --git a/js/ui/scripting.js b/js/ui/scripting.js
index e4b29a4cc6..3601130760 100644
--- a/js/ui/scripting.js
+++ b/js/ui/scripting.js
@@ -222,9 +222,9 @@ function _collect(scriptModule, outputFile) {
             let monitor = monitors[i];
             if (i != 0)
                 Shell.write_string_to_stream(out, ', ');
-            Shell.write_string_to_stream(out, '"%s%dx%d+%d+%d"'.format(i == primary ? "*" : "",
-                                                                       monitor.width, monitor.height,
-                                                                       monitor.x, monitor.y));
+            const prefix = i === primary ? '*' : '';
+            Shell.write_string_to_stream(out,
+                `"${prefix}${monitor.width}x${monitor.height}+${monitor.x}+${monitor.y}"`);
         }
         Shell.write_string_to_stream(out, ' ]');
 
diff --git a/js/ui/search.js b/js/ui/search.js
index b1e76c46d5..1e8aeb6c70 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -232,18 +232,18 @@ var SearchResultsBase = GObject.registerClass({
             this.provider.getResultMetas(metasNeeded, metas => {
                 if (this._cancellable.is_cancelled()) {
                     if (metas.length > 0)
-                        log('Search provider %s returned results after the request was 
canceled'.format(this.provider.id));
+                        log(`Search provider ${this.provider.id} returned results after the request was 
canceled`);
                     callback(false);
                     return;
                 }
                 if (metas.length != metasNeeded.length) {
-                    log('Wrong number of result metas returned by search provider %s: 
'.format(this.provider.id) +
-                        'expected %d but got %d'.format(metasNeeded.length, metas.length));
+                    log(`Wrong number of result metas returned by search provider ${this.provider.id}: ` +
+                        `expected ${metasNeeded.length} but got ${metas.length}`);
                     callback(false);
                     return;
                 }
                 if (metas.some(meta => !meta.name || !meta.id)) {
-                    log('Invalid result meta returned from search provider %s'.format(this.provider.id));
+                    log(`Invalid result meta returned from search provider ${this.provider.id}`);
                     callback(false);
                     return;
                 }
diff --git a/js/ui/shellMountOperation.js b/js/ui/shellMountOperation.js
index dd8eb5f77c..0ef383d582 100644
--- a/js/ui/shellMountOperation.js
+++ b/js/ui/shellMountOperation.js
@@ -564,7 +564,7 @@ var GnomeShellMountOpHandler = class {
     _setCurrentRequest(invocation, id, type) {
         let oldId = this._currentId;
         let oldType = this._currentType;
-        let requestId = '%s@%s'.format(id, invocation.get_sender());
+        let requestId = `${id}@${invocation.get_sender()}`;
 
         this._clearCurrentRequest(Gio.MountOperationResult.UNHANDLED, {});
 
diff --git a/js/ui/status/accessibility.js b/js/ui/status/accessibility.js
index 14f4702413..a4bad14fd2 100644
--- a/js/ui/status/accessibility.js
+++ b/js/ui/status/accessibility.js
@@ -39,7 +39,7 @@ class ATIndicator extends PanelMenu.Button {
         }));
 
         this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
-        this._a11ySettings.connect('changed::%s'.format(KEY_ALWAYS_SHOW), 
this._queueSyncMenuVisibility.bind(this));
+        this._a11ySettings.connect(`changed::${KEY_ALWAYS_SHOW}`, this._queueSyncMenuVisibility.bind(this));
 
         let highContrast = this._buildItem(_('High Contrast'), A11Y_INTERFACE_SCHEMA, KEY_HIGH_CONTRAST);
         this.menu.addMenuItem(highContrast);
@@ -115,7 +115,7 @@ class ATIndicator extends PanelMenu.Button {
             settings.is_writable(key),
             enabled => settings.set_boolean(key, enabled));
 
-        settings.connect('changed::%s'.format(key), () => {
+        settings.connect(`changed::${key}`, () => {
             widget.setToggleState(settings.get_boolean(key));
 
             this._queueSyncMenuVisibility();
@@ -140,7 +140,7 @@ class ATIndicator extends PanelMenu.Button {
                 }
             });
 
-        settings.connect('changed::%s'.format(KEY_TEXT_SCALING_FACTOR), () => {
+        settings.connect(`changed::${KEY_TEXT_SCALING_FACTOR}`, () => {
             factor = settings.get_double(KEY_TEXT_SCALING_FACTOR);
             let active = factor > 1.0;
             widget.setToggleState(active);
diff --git a/js/ui/status/dwellClick.js b/js/ui/status/dwellClick.js
index 4b1d8a2c13..d82a465037 100644
--- a/js/ui/status/dwellClick.js
+++ b/js/ui/status/dwellClick.js
@@ -40,8 +40,8 @@ class DwellClickIndicator extends PanelMenu.Button {
         this.add_child(this._icon);
 
         this._a11ySettings = new Gio.Settings({ schema_id: MOUSE_A11Y_SCHEMA });
-        this._a11ySettings.connect('changed::%s'.format(KEY_DWELL_CLICK_ENABLED), 
this._syncMenuVisibility.bind(this));
-        this._a11ySettings.connect('changed::%s'.format(KEY_DWELL_MODE), 
this._syncMenuVisibility.bind(this));
+        this._a11ySettings.connect(`changed::${KEY_DWELL_CLICK_ENABLED}`, 
this._syncMenuVisibility.bind(this));
+        this._a11ySettings.connect(`changed::${KEY_DWELL_MODE}`, this._syncMenuVisibility.bind(this));
 
         this._seat = Clutter.get_default_backend().get_default_seat();
         this._seat.connect('ptr-a11y-dwell-click-type-changed', this._updateClickType.bind(this));
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index bc50f3d376..0466395323 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -64,7 +64,7 @@ var InputSource = class {
             return this.id;
 
         if (engineDesc.variant && engineDesc.variant.length > 0)
-            return '%s+%s'.format(engineDesc.layout, engineDesc.variant);
+            return `${engineDesc.layout}+${engineDesc.variant}`;
         else
             return engineDesc.layout;
     }
@@ -138,7 +138,7 @@ class InputSourceSwitcher extends SwitcherPopup.SwitcherList {
 var InputSourceSettings = class {
     constructor() {
         if (this.constructor === InputSourceSettings)
-            throw new TypeError('Cannot instantiate abstract class %s'.format(this.constructor.name));
+            throw new TypeError(`Cannot instantiate abstract class ${this.constructor.name}`);
     }
 
     _emitInputSourcesChanged() {
@@ -211,7 +211,7 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
                 null, Gio.DBusCallFlags.NONE, -1, null);
             [props] = result.deep_unpack();
         } catch (e) {
-            log('Could not get properties from %s'.format(this._BUS_NAME));
+            log(`Could not get properties from ${this._BUS_NAME}`);
             return;
         }
 
@@ -239,7 +239,7 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
         for (let i = 0; i < layouts.length && !!layouts[i]; i++) {
             let id = layouts[i];
             if (variants[i])
-                id += '+%s'.format(variants[i]);
+                id += `+${variants[i]}`;
             sourcesList.push({ type: INPUT_SOURCE_TYPE_XKB, id });
         }
         return sourcesList;
@@ -261,9 +261,9 @@ var InputSourceSessionSettings = class extends InputSourceSettings {
         this._KEY_PER_WINDOW = 'per-window';
 
         this._settings = new Gio.Settings({ schema_id: this._DESKTOP_INPUT_SOURCES_SCHEMA });
-        this._settings.connect('changed::%s'.format(this._KEY_INPUT_SOURCES), 
this._emitInputSourcesChanged.bind(this));
-        this._settings.connect('changed::%s'.format(this._KEY_KEYBOARD_OPTIONS), 
this._emitKeyboardOptionsChanged.bind(this));
-        this._settings.connect('changed::%s'.format(this._KEY_PER_WINDOW), 
this._emitPerWindowChanged.bind(this));
+        this._settings.connect(`changed::${this._KEY_INPUT_SOURCES}`, 
this._emitInputSourcesChanged.bind(this));
+        this._settings.connect(`changed::${this._KEY_KEYBOARD_OPTIONS}`, 
this._emitKeyboardOptionsChanged.bind(this));
+        this._settings.connect(`changed::${this._KEY_PER_WINDOW}`, this._emitPerWindowChanged.bind(this));
     }
 
     _getSourcesList(key) {
@@ -564,7 +564,7 @@ var InputSourceManager = class {
                     if (textdomain != '')
                         longName = Gettext.dgettext(textdomain, longName);
                     exists = true;
-                    displayName = '%s (%s)'.format(language, longName);
+                    displayName = `${language} (${longName})`;
                     shortName = this._makeEngineShortName(engineDesc);
                 }
             }
@@ -1039,7 +1039,7 @@ class InputSourceIndicator extends PanelMenu.Button {
                 break;
 
             default:
-                log('IBus property %s has invalid type %d'.format(prop.get_key(), type));
+                log(`IBus property ${prop.get_key()} has invalid type ${type}`);
                 continue;
             }
 
@@ -1078,7 +1078,7 @@ class InputSourceIndicator extends PanelMenu.Button {
 
         let description = xkbLayout;
         if (xkbVariant.length > 0)
-            description = '%s\t%s'.format(description, xkbVariant);
+            description = `${description}\t${xkbVariant}`;
 
         Util.spawn(['gkbd-keyboard-display', '-l', description]);
     }
diff --git a/js/ui/status/location.js b/js/ui/status/location.js
index f4b425c022..7f00292181 100644
--- a/js/ui/status/location.js
+++ b/js/ui/status/location.js
@@ -69,9 +69,9 @@ var GeoclueAgent = GObject.registerClass({
         super._init();
 
         this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA });
-        this._settings.connect('changed::%s'.format(ENABLED),
+        this._settings.connect(`changed::${ENABLED}`,
             () => this.notify('enabled'));
-        this._settings.connect('changed::%s'.format(MAX_ACCURACY_LEVEL),
+        this._settings.connect(`changed::${MAX_ACCURACY_LEVEL}`,
             this._onMaxAccuracyLevelChanged.bind(this));
 
         this._agent = Gio.DBusExportedObject.wrapJSObject(AgentIface, this);
@@ -287,7 +287,7 @@ var AppAuthorizer = class {
         this._onAuthDone = onAuthDone;
 
         let appSystem = Shell.AppSystem.get_default();
-        this._app = appSystem.lookup_app('%s.desktop'.format(this.desktopId));
+        this._app = appSystem.lookup_app(`${this.desktopId}.desktop`);
         if (this._app == null || this._permStoreProxy == null) {
             this._completeAuth();
 
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index 7e5b63c6f5..f7db379395 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -88,7 +88,7 @@ function launchSettingsPanel(panel, ...args) {
         [panel, args.map(s => new GLib.Variant('s', s))]);
     const platformData = {
         'desktop-startup-id': new GLib.Variant('s',
-            '_TIME%s'.format(global.get_current_time())),
+            `_TIME${global.get_current_time()}`),
     };
     try {
         Gio.DBus.session.call(
@@ -103,7 +103,7 @@ function launchSettingsPanel(panel, ...args) {
             -1,
             null);
     } catch (e) {
-        log('Failed to launch Settings panel: %s'.format(e.message));
+        log(`Failed to launch Settings panel: ${e.message}`);
     }
 }
 
@@ -208,7 +208,7 @@ Signals.addSignalMethods(NMConnectionItem.prototype);
 var NMConnectionSection = class NMConnectionSection {
     constructor(client) {
         if (this.constructor === NMConnectionSection)
-            throw new TypeError('Cannot instantiate abstract type %s'.format(this.constructor.name));
+            throw new TypeError(`Cannot instantiate abstract type ${this.constructor.name}`);
 
         this._client = client;
 
@@ -340,7 +340,7 @@ var NMConnectionDevice = class NMConnectionDevice extends NMConnectionSection {
         super(client);
 
         if (this.constructor === NMConnectionDevice)
-            throw new TypeError('Cannot instantiate abstract type %s'.format(this.constructor.name));
+            throw new TypeError(`Cannot instantiate abstract type ${this.constructor.name}`);
 
         this._device = device;
         this._description = '';
@@ -489,7 +489,7 @@ var NMConnectionDevice = class NMConnectionDevice extends NMConnectionSection {
             /* Translators: %s is a network identifier */
             return _("%s Connection Failed").format(this._getDescription());
         default:
-            log('Device state invalid, is %d'.format(this._device.state));
+            log(`Device state invalid, is ${this._device.state}`);
             return 'invalid';
         }
     }
@@ -639,8 +639,7 @@ var NMDeviceModem = class extends NMConnectionDevice {
     }
 
     _getSignalIcon() {
-        return 'network-cellular-signal-%s-symbolic'.format(
-            signalToIcon(this._mobileDevice.signal_quality));
+        return `network-cellular-signal-${signalToIcon(this._mobileDevice.signal_quality)}-symbolic`;
     }
 };
 
@@ -743,12 +742,10 @@ var NMWirelessDialogItem = GObject.registerClass({
     }
 
     _getSignalIcon() {
-        if (this._ap.mode == NM80211Mode.ADHOC) {
+        if (this._ap.mode === NM80211Mode.ADHOC)
             return 'network-workgroup-symbolic';
-        } else {
-            return 'network-wireless-signal-%s-symbolic'.format(
-                signalToIcon(this._ap.strength));
-        }
+        else
+            return `network-wireless-signal-${signalToIcon(this._ap.strength)}-symbolic`;
     }
 });
 
@@ -1460,7 +1457,7 @@ var NMDeviceWireless = class {
         }
 
         if (this._canReachInternet())
-            return 'network-wireless-signal-%s-symbolic'.format(signalToIcon(ap.strength));
+            return `network-wireless-signal-${signalToIcon(ap.strength)}-symbolic`;
         else
             return 'network-wireless-no-route-symbolic';
     }
@@ -1768,7 +1765,7 @@ class Indicator extends PanelMenu.SystemIndicator {
             this._configPermission = await Polkit.Permission.new(
                 'org.freedesktop.NetworkManager.network-control', null, null);
         } catch (e) {
-            log('No permission to control network connections: %s'.format(e.toString()));
+            log(`No permission to control network connections: ${e}`);
             this._configPermission = null;
         }
 
@@ -1800,7 +1797,7 @@ class Indicator extends PanelMenu.SystemIndicator {
             try {
                 this._deviceAdded(this._client, devices[i], true);
             } catch (e) {
-                log('Failed to add device %s: %s'.format(devices[i], e.toString()));
+                log(`Failed to add device ${devices[i]}: ${e}`);
             }
         }
         this._syncDeviceNames();
@@ -2095,7 +2092,7 @@ class Indicator extends PanelMenu.SystemIndicator {
                     this._closeConnectivityCheck(path);
             } catch (e) { }
         } else {
-            log('Invalid result from portal helper: %s'.format(result));
+            log(`Invalid result from portal helper: ${result}`);
         }
     }
 
@@ -2132,7 +2129,7 @@ class Indicator extends PanelMenu.SystemIndicator {
                 '/org/gnome/Shell/PortalHelper',
                 (proxy, error) => {
                     if (error) {
-                        log('Error launching the portal helper: %s'.format(error));
+                        log(`Error launching the portal helper: ${error}`);
                         return;
                     }
 
diff --git a/js/ui/status/power.js b/js/ui/status/power.js
index c79ff798e9..5d23006f59 100644
--- a/js/ui/status/power.js
+++ b/js/ui/status/power.js
@@ -26,7 +26,7 @@ class Indicator extends PanelMenu.SystemIndicator {
             schema_id: 'org.gnome.desktop.interface',
         });
         this._desktopSettings.connect(
-            'changed::%s'.format(SHOW_BATTERY_PERCENTAGE), this._sync.bind(this));
+            `changed::${SHOW_BATTERY_PERCENTAGE}`, this._sync.bind(this));
 
         this._indicator = this._addIndicator();
         this._percentageLabel = new St.Label({
@@ -125,7 +125,7 @@ class Indicator extends PanelMenu.SystemIndicator {
             (this._proxy.State === UPower.DeviceState.CHARGING && fillLevel === 100);
         const icon = charged
             ? 'battery-level-100-charged-symbolic'
-            : 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
+            : `battery-level-${fillLevel}${chargingState}-symbolic`;
 
         // Make sure we fall back to fallback-icon-name and not GThemedIcon's
         // default fallbacks
diff --git a/js/ui/status/thunderbolt.js b/js/ui/status/thunderbolt.js
index e30a4222fa..de87b9d5ba 100644
--- a/js/ui/status/thunderbolt.js
+++ b/js/ui/status/thunderbolt.js
@@ -68,7 +68,7 @@ var Client = class {
                 BOLT_DBUS_CLIENT_IFACE,
                 null);
         } catch (e) {
-            log('error creating bolt proxy: %s'.format(e.message));
+            log(`error creating bolt proxy: ${e.message}`);
             return;
         }
         this._propsChangedId = this._proxy.connect('g-properties-changed', 
this._onPropertiesChanged.bind(this));
@@ -248,7 +248,7 @@ class Indicator extends PanelMenu.SystemIndicator {
         try {
             this._perm = await Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null);
         } catch (e) {
-            log('Failed to get PolKit permission: %s'.format(e.toString()));
+            log(`Failed to get PolKit permission: ${e}`);
         }
     }
 
@@ -314,8 +314,7 @@ class Indicator extends PanelMenu.SystemIndicator {
         let auth = unlocked && allowed;
         policy[0] = auth;
 
-        log('thunderbolt: [%s] auto enrollment: %s (allowed: %s)'.format(
-            device.Name, auth ? 'yes' : 'no', allowed ? 'yes' : 'no'));
+        log(`thunderbolt: [${device.Name}] auto enrollment: ${auth ? 'yes' : 'no'} (allowed: ${allowed ? 
'yes' : 'no'})`);
 
         if (auth)
             return; /* we are done */
diff --git a/js/ui/status/volume.js b/js/ui/status/volume.js
index 0b3221f672..5bf08ca7f8 100644
--- a/js/ui/status/volume.js
+++ b/js/ui/status/volume.js
@@ -41,7 +41,7 @@ var StreamSlider = class {
         this._slider = new Slider.Slider(0);
 
         this._soundSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.sound' });
-        this._soundSettings.connect('changed::%s'.format(ALLOW_AMPLIFIED_VOLUME_KEY), 
this._amplifySettingsChanged.bind(this));
+        this._soundSettings.connect(`changed::${ALLOW_AMPLIFIED_VOLUME_KEY}`, 
this._amplifySettingsChanged.bind(this));
         this._amplifySettingsChanged();
 
         this._sliderChangedId = this._slider.connect('notify::value',
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
index 0a5e7f6275..990b1c02fa 100644
--- a/js/ui/unlockDialog.js
+++ b/js/ui/unlockDialog.js
@@ -100,7 +100,7 @@ var NotificationsBox = GObject.registerClass({
 
         let count = source.unseenCount;
         let countLabel = new St.Label({
-            text: count.toString(),
+            text: `${count}`,
             visible: count > 1,
             style_class: 'unlock-dialog-notification-count-text',
         });
@@ -140,7 +140,7 @@ var NotificationsBox = GObject.registerClass({
             }
 
             let label = new St.Label({ style_class: 'unlock-dialog-notification-count-text' });
-            label.clutter_text.set_markup('<b>%s</b> %s'.format(n.title, body));
+            label.clutter_text.set_markup(`<b>${n.title}</b> ${body}`);
             textBox.add(label);
 
             visible = true;
@@ -272,7 +272,7 @@ var NotificationsBox = GObject.registerClass({
             this._showSource(source, obj, obj.sourceBox);
         } else {
             let count = source.unseenCount;
-            obj.countLabel.text = count.toString();
+            obj.countLabel.text = `${count}`;
             obj.countLabel.visible = count > 1;
         }
 
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 8f102baffb..64f6d734a7 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -132,8 +132,7 @@ class WindowDimmer extends Clutter.BrightnessContrastEffect {
     }
 
     _syncEnabled() {
-        let transitionName = '@effects.%s.brightness'.format(this.name);
-        let animating = this.actor.get_transition(transitionName) != null;
+        let animating = this.actor.get_transition(`@effects.${this.name}.brightness`) !== null;
         let dimmed = this.brightness.red != 127;
         this.enabled = this._enabled && (animating || dimmed);
     }
@@ -147,8 +146,7 @@ class WindowDimmer extends Clutter.BrightnessContrastEffect {
         let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS);
         let color = Clutter.Color.new(val, val, val, 255);
 
-        let transitionName = '@effects.%s.brightness'.format(this.name);
-        this.actor.ease_property(transitionName, color, {
+        this.actor.ease_property(`@effects.${this.name}.brightness`, color, {
             mode: Clutter.AnimationMode.LINEAR,
             duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0),
             onComplete: () => this._syncEnabled(),
@@ -976,7 +974,7 @@ var WindowManager = class {
             // already.
             // Note that we do log cancellation from here.
             if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_SUPPORTED)) {
-                log('Error starting X11 services: %s'.format(e.message));
+                log(`Error starting X11 services: ${e.message}`);
                 status = false;
             }
         } finally {
@@ -994,7 +992,7 @@ var WindowManager = class {
             // already.
             // Note that we do log cancellation from here.
             if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_SUPPORTED))
-                log('Error stopping X11 services: %s'.format(e.message));
+                log(`Error stopping X11 services: ${e.message}`);
         }
     }
 
@@ -1292,7 +1290,7 @@ var WindowManager = class {
         actor.freeze();
 
         if (this._clearAnimationInfo(actor)) {
-            log('Old animationInfo removed from actor %s'.format(actor));
+            log(`Old animationInfo removed from actor ${actor}`);
             this._shellwm.completed_size_change(actor);
         }
 
diff --git a/subprojects/extensions-app/js/main.js b/subprojects/extensions-app/js/main.js
index 09047a939a..c32707b615 100644
--- a/subprojects/extensions-app/js/main.js
+++ b/subprojects/extensions-app/js/main.js
@@ -18,14 +18,14 @@ Gio._promisify(Gio.DBusConnection.prototype, 'call');
 Gio._promisify(Shew.WindowExporter.prototype, 'export');
 
 function loadInterfaceXML(iface) {
-    const uri = 'resource:///org/gnome/Extensions/dbus-interfaces/%s.xml'.format(iface);
+    const uri = `resource:///org/gnome/Extensions/dbus-interfaces/${iface}.xml`;
     const f = Gio.File.new_for_uri(uri);
 
     try {
         let [ok_, bytes] = f.load_contents(null);
         return new TextDecoder().decode(bytes);
     } catch (e) {
-        log('Failed to load D-Bus interface %s'.format(iface));
+        log(`Failed to load D-Bus interface ${iface}`);
     }
 
     return null;
@@ -186,7 +186,7 @@ var ExtensionsWindow = GObject.registerClass({
             try {
                 this._exportedHandle = await this._exporter.export();
             } catch (e) {
-                log('Failed to export window: %s'.format(e.message));
+                log(`Failed to export window: ${e.message}`);
             }
         }
 
@@ -278,7 +278,7 @@ var ExtensionsWindow = GObject.registerClass({
         this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => {
             if (e) {
                 if (e instanceof Gio.DBusError) {
-                    log('Failed to connect to shell proxy: %s'.format(e.toString()));
+                    log(`Failed to connect to shell proxy: ${e}`);
                     this._mainStack.visible_child_name = 'noshell';
                 } else {
                     throw e;
@@ -536,7 +536,7 @@ function initEnvironment() {
         },
 
         logError(s) {
-            log('ERROR: %s'.format(s));
+            log(`ERROR: ${s}`);
         },
 
         userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]