2
0
Эх сурвалжийг харах

Replace l18n library with Intl-based LocaleController

Sage Abdullah 2 сар өмнө
parent
commit
944fd02dc3

+ 0 - 4
.github/workflows/test.yml

@@ -167,10 +167,6 @@ jobs:
           tee -a testproject/settings/local.py << EOF
           from warnings import filterwarnings
           SILENCED_SYSTEM_CHECKS = ["wagtailadmin.W001"]
-          # Remove when l18n dependency is updated or removed
-          filterwarnings(
-              "ignore", "'locale.getdefaultlocale' is deprecated .*"
-          )
           # Remove when all experimental jobs use Django >= 6.0
           filterwarnings(
               "ignore", "The FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated."

+ 137 - 0
client/src/controllers/LocaleController.test.js

@@ -0,0 +1,137 @@
+import { Application } from '@hotwired/stimulus';
+import { LocaleController } from './LocaleController';
+import { InitController } from './InitController';
+
+describe('LocaleController', () => {
+  let app;
+  let select;
+
+  const setup = async (html) => {
+    document.body.innerHTML = `<main>${html}</main>`;
+    select = document.querySelector('select');
+    select.innerHTML = /* html */ `
+      <option value="" selected>Use server time zone</option>
+      <option value="Africa/Abidjan">Africa/Abidjan</option>
+      <option value="America/Argentina/Jujuy">America/Argentina/Jujuy</option>
+      <option value="America/Indiana/Knox">America/Indiana/Knox</option>
+      <option value="Antarctica/Rothera">Antarctica/Rothera</option>
+      <option value="Arctic/Longyearbyen">Arctic/Longyearbyen</option>
+      <option value="Asia/Katmandu">Asia/Katmandu</option>
+      <option value="Atlantic/Canary">Atlantic/Canary</option>
+      <option value="Australia/South">Australia/South</option>
+      <option value="Brazil/East">Brazil/East</option>
+      <option value="Canada/Atlantic">Canada/Atlantic</option>
+      <option value="Chile/Continental">Chile/Continental</option>
+      <option value="EST">EST</option>
+      <option value="Etc/GMT-7">Etc/GMT-7</option>
+      <option value="Europe/Brussels">Europe/Brussels</option>
+      <option value="GMT">GMT</option>
+      <option value="Indian/Maldives">Indian/Maldives</option>
+      <option value="Pacific/Tarawa">Pacific/Tarawa</option>
+      <option value="UTC">UTC</option>
+      <option value="Universal">Universal</option>
+      <option value="Zulu">Zulu</option>
+    `;
+
+    app = Application.start();
+    app.register('w-locale', LocaleController);
+    app.register('w-init', InitController);
+
+    await Promise.resolve();
+  };
+
+  afterEach(() => {
+    app?.stop();
+    jest.clearAllMocks();
+  });
+
+  describe('localizing time zone options', () => {
+    it('should append localized time zone labels to the options', async () => {
+      document.documentElement.lang = 'en-US';
+      await setup(/* html */ `
+        <select
+          name="locale-current_time_zone"
+          data-controller="w-init w-locale"
+          data-action="w-init:ready->w-locale#localizeTimeZoneOptions"
+          data-w-locale-server-time-zone-param="Europe/London"
+        >
+        </select>
+      `);
+
+      expect(select.getAttribute('data-controller')).toEqual('w-locale');
+      const selected = select.selectedOptions[0];
+      expect(selected).toBeTruthy();
+      expect(selected.value).toEqual('');
+      expect(selected.textContent).toEqual(
+        'Use server time zone: GMT (Greenwich Mean Time)',
+      );
+      expect(select).toMatchSnapshot();
+    });
+  });
+
+  it('should localize to the current HTML locale and use the server time zone param for the default', async () => {
+    document.documentElement.lang = 'id-ID';
+    await setup(/* html */ `
+      <select
+        name="locale-current_time_zone"
+        data-controller="w-init w-locale"
+        data-action="w-init:ready->w-locale#localizeTimeZoneOptions"
+        data-w-locale-server-time-zone-param="Asia/Jakarta"
+      >
+      </select>
+    `);
+
+    expect(select.getAttribute('data-controller')).toEqual('w-locale');
+    const selected = select.selectedOptions[0];
+    expect(selected).toBeTruthy();
+    expect(selected.value).toEqual('');
+    expect(selected.textContent).toEqual(
+      'Use server time zone: WIB (Waktu Indonesia Barat)',
+    );
+    expect(select).toMatchSnapshot();
+  });
+
+  it('should skip updating the default option if server time zone is not provided', async () => {
+    document.documentElement.lang = 'ar';
+    await setup(/* html */ `
+      <select
+        name="locale-current_time_zone"
+        data-controller="w-init w-locale"
+        data-action="w-init:ready->w-locale#localizeTimeZoneOptions"
+      >
+      </select>
+    `);
+
+    expect(select.getAttribute('data-controller')).toEqual('w-locale');
+    const selected = select.selectedOptions[0];
+    expect(selected).toBeTruthy();
+    expect(selected.value).toEqual('');
+    expect(selected.textContent).toEqual('Use server time zone');
+    expect(select).toMatchSnapshot();
+  });
+
+  it('should allow updating the time zone options on an uncontrolled select element via events', async () => {
+    document.documentElement.lang = 'id-ID';
+    await setup(/* html */ `
+      <form data-controller="w-locale">
+        <select
+          name="locale-current_time_zone"
+          data-action="custom:event->w-locale#localizeTimeZoneOptions"
+          data-w-locale-server-time-zone-param="Asia/Tokyo"
+        >
+        </select>
+      </form>
+    `);
+    select.dispatchEvent(new CustomEvent('custom:event'));
+    await Promise.resolve();
+
+    expect(select.hasAttribute('data-controller')).toBe(false);
+    const selected = select.selectedOptions[0];
+    expect(selected).toBeTruthy();
+    expect(selected.value).toEqual('');
+    expect(selected.textContent).toEqual(
+      'Use server time zone: GMT+9 (Waktu Standar Jepang)',
+    );
+    expect(select).toMatchSnapshot();
+  });
+});

+ 55 - 0
client/src/controllers/LocaleController.ts

@@ -0,0 +1,55 @@
+import { Controller } from '@hotwired/stimulus';
+
+/**
+ * Localizes elements in the current locale.
+ */
+export class LocaleController extends Controller<HTMLSelectElement> {
+  /**
+   * Localize an IANA time zone in the current locale.
+   *
+   * @param timeZone An IANA time zone string
+   * @param format Time zone name formatting option
+   * @returns formatted time zone name in the current locale
+   */
+  static localizeTimeZone(
+    timeZone: string,
+    format: Intl.DateTimeFormatOptions['timeZoneName'],
+  ) {
+    const df = new Intl.DateTimeFormat(document.documentElement.lang, {
+      timeZone,
+      timeZoneName: format,
+    });
+    const parts = df.formatToParts(new Date());
+    return parts.find((part) => part.type === 'timeZoneName')!.value;
+  }
+
+  /**
+   *
+   * @param timeZone An IANA time zone string
+   * @returns formatted time zone name in the current locale with short and long
+   * labels, e.g. `"GMT+7 (Western Indonesia Time)"`
+   */
+  static getTZLabel(timeZone: string) {
+    const shortLabel = LocaleController.localizeTimeZone(timeZone, 'short');
+    const longLabel = LocaleController.localizeTimeZone(timeZone, 'long');
+    return `${shortLabel} (${longLabel})`;
+  }
+
+  /**
+   * Localize the time zone `<options>` of a `<select>` element in the current
+   * locale.
+   */
+  localizeTimeZoneOptions(
+    event?: Event & { params?: { serverTimeZone?: string } },
+  ) {
+    const element = (event?.target as HTMLSelectElement) || this.element;
+    const serverTimeZone = event?.params?.serverTimeZone;
+    Array.from(element.options).forEach((opt) => {
+      const timeZone = opt.value || serverTimeZone;
+      if (!timeZone) return;
+      const localized = LocaleController.getTZLabel(timeZone);
+      const option = opt;
+      option.textContent = `${option.textContent}: ${localized}`;
+    });
+  }
+}

+ 639 - 0
client/src/controllers/__snapshots__/LocaleController.test.js.snap

@@ -0,0 +1,639 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`LocaleController localizing time zone options should append localized time zone labels to the options 1`] = `
+<select
+  data-action="w-init:ready->w-locale#localizeTimeZoneOptions"
+  data-controller="w-locale"
+  data-w-locale-server-time-zone-param="Europe/London"
+  name="locale-current_time_zone"
+>
+  
+      
+  <option
+    selected=""
+    value=""
+  >
+    Use server time zone: GMT (Greenwich Mean Time)
+  </option>
+  
+      
+  <option
+    value="Africa/Abidjan"
+  >
+    Africa/Abidjan: GMT (Greenwich Mean Time)
+  </option>
+  
+      
+  <option
+    value="America/Argentina/Jujuy"
+  >
+    America/Argentina/Jujuy: GMT-3 (Argentina Standard Time)
+  </option>
+  
+      
+  <option
+    value="America/Indiana/Knox"
+  >
+    America/Indiana/Knox: CST (Central Standard Time)
+  </option>
+  
+      
+  <option
+    value="Antarctica/Rothera"
+  >
+    Antarctica/Rothera: GMT-3 (Rothera Time)
+  </option>
+  
+      
+  <option
+    value="Arctic/Longyearbyen"
+  >
+    Arctic/Longyearbyen: GMT+1 (Central European Standard Time)
+  </option>
+  
+      
+  <option
+    value="Asia/Katmandu"
+  >
+    Asia/Katmandu: GMT+5:45 (Nepal Time)
+  </option>
+  
+      
+  <option
+    value="Atlantic/Canary"
+  >
+    Atlantic/Canary: GMT (Western European Standard Time)
+  </option>
+  
+      
+  <option
+    value="Australia/South"
+  >
+    Australia/South: GMT+10:30 (Australian Central Daylight Time)
+  </option>
+  
+      
+  <option
+    value="Brazil/East"
+  >
+    Brazil/East: GMT-3 (Brasilia Standard Time)
+  </option>
+  
+      
+  <option
+    value="Canada/Atlantic"
+  >
+    Canada/Atlantic: AST (Atlantic Standard Time)
+  </option>
+  
+      
+  <option
+    value="Chile/Continental"
+  >
+    Chile/Continental: GMT-3 (Chile Summer Time)
+  </option>
+  
+      
+  <option
+    value="EST"
+  >
+    EST: EST (Eastern Standard Time)
+  </option>
+  
+      
+  <option
+    value="Etc/GMT-7"
+  >
+    Etc/GMT-7: GMT+7 (GMT+07:00)
+  </option>
+  
+      
+  <option
+    value="Europe/Brussels"
+  >
+    Europe/Brussels: GMT+1 (Central European Standard Time)
+  </option>
+  
+      
+  <option
+    value="GMT"
+  >
+    GMT: UTC (Coordinated Universal Time)
+  </option>
+  
+      
+  <option
+    value="Indian/Maldives"
+  >
+    Indian/Maldives: GMT+5 (Maldives Time)
+  </option>
+  
+      
+  <option
+    value="Pacific/Tarawa"
+  >
+    Pacific/Tarawa: GMT+12 (Gilbert Islands Time)
+  </option>
+  
+      
+  <option
+    value="UTC"
+  >
+    UTC: UTC (Coordinated Universal Time)
+  </option>
+  
+      
+  <option
+    value="Universal"
+  >
+    Universal: UTC (Coordinated Universal Time)
+  </option>
+  
+      
+  <option
+    value="Zulu"
+  >
+    Zulu: UTC (Coordinated Universal Time)
+  </option>
+  
+    
+</select>
+`;
+
+exports[`LocaleController should allow updating the time zone options on an uncontrolled select element via events 1`] = `
+<select
+  data-action="custom:event->w-locale#localizeTimeZoneOptions"
+  data-w-locale-server-time-zone-param="Asia/Tokyo"
+  name="locale-current_time_zone"
+>
+  
+      
+  <option
+    selected=""
+    value=""
+  >
+    Use server time zone: GMT+9 (Waktu Standar Jepang)
+  </option>
+  
+      
+  <option
+    value="Africa/Abidjan"
+  >
+    Africa/Abidjan: GMT (Greenwich Mean Time)
+  </option>
+  
+      
+  <option
+    value="America/Argentina/Jujuy"
+  >
+    America/Argentina/Jujuy: GMT-3 (Waktu Standar Argentina)
+  </option>
+  
+      
+  <option
+    value="America/Indiana/Knox"
+  >
+    America/Indiana/Knox: CST (Waktu Standar Tengah)
+  </option>
+  
+      
+  <option
+    value="Antarctica/Rothera"
+  >
+    Antarctica/Rothera: GMT-3 (Waktu Rothera)
+  </option>
+  
+      
+  <option
+    value="Arctic/Longyearbyen"
+  >
+    Arctic/Longyearbyen: GMT+1 (Waktu Standar Eropa Tengah)
+  </option>
+  
+      
+  <option
+    value="Asia/Katmandu"
+  >
+    Asia/Katmandu: GMT+5.45 (Waktu Nepal)
+  </option>
+  
+      
+  <option
+    value="Atlantic/Canary"
+  >
+    Atlantic/Canary: GMT (Waktu Standar Eropa Barat)
+  </option>
+  
+      
+  <option
+    value="Australia/South"
+  >
+    Australia/South: GMT+10.30 (Waktu Musim Panas Tengah Australia)
+  </option>
+  
+      
+  <option
+    value="Brazil/East"
+  >
+    Brazil/East: GMT-3 (Waktu Standar Brasil)
+  </option>
+  
+      
+  <option
+    value="Canada/Atlantic"
+  >
+    Canada/Atlantic: AST (Waktu Standar Atlantik)
+  </option>
+  
+      
+  <option
+    value="Chile/Continental"
+  >
+    Chile/Continental: GMT-3 (Waktu Musim Panas Cile)
+  </option>
+  
+      
+  <option
+    value="EST"
+  >
+    EST: EST (Waktu Standar Timur)
+  </option>
+  
+      
+  <option
+    value="Etc/GMT-7"
+  >
+    Etc/GMT-7: GMT+7 (GMT+07.00)
+  </option>
+  
+      
+  <option
+    value="Europe/Brussels"
+  >
+    Europe/Brussels: GMT+1 (Waktu Standar Eropa Tengah)
+  </option>
+  
+      
+  <option
+    value="GMT"
+  >
+    GMT: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+      
+  <option
+    value="Indian/Maldives"
+  >
+    Indian/Maldives: GMT+5 (Waktu Maladewa)
+  </option>
+  
+      
+  <option
+    value="Pacific/Tarawa"
+  >
+    Pacific/Tarawa: GMT+12 (Waktu Kep. Gilbert)
+  </option>
+  
+      
+  <option
+    value="UTC"
+  >
+    UTC: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+      
+  <option
+    value="Universal"
+  >
+    Universal: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+      
+  <option
+    value="Zulu"
+  >
+    Zulu: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+    
+</select>
+`;
+
+exports[`LocaleController should localize to the current HTML locale and use the server time zone param for the default 1`] = `
+<select
+  data-action="w-init:ready->w-locale#localizeTimeZoneOptions"
+  data-controller="w-locale"
+  data-w-locale-server-time-zone-param="Asia/Jakarta"
+  name="locale-current_time_zone"
+>
+  
+      
+  <option
+    selected=""
+    value=""
+  >
+    Use server time zone: WIB (Waktu Indonesia Barat)
+  </option>
+  
+      
+  <option
+    value="Africa/Abidjan"
+  >
+    Africa/Abidjan: GMT (Greenwich Mean Time)
+  </option>
+  
+      
+  <option
+    value="America/Argentina/Jujuy"
+  >
+    America/Argentina/Jujuy: GMT-3 (Waktu Standar Argentina)
+  </option>
+  
+      
+  <option
+    value="America/Indiana/Knox"
+  >
+    America/Indiana/Knox: CST (Waktu Standar Tengah)
+  </option>
+  
+      
+  <option
+    value="Antarctica/Rothera"
+  >
+    Antarctica/Rothera: GMT-3 (Waktu Rothera)
+  </option>
+  
+      
+  <option
+    value="Arctic/Longyearbyen"
+  >
+    Arctic/Longyearbyen: GMT+1 (Waktu Standar Eropa Tengah)
+  </option>
+  
+      
+  <option
+    value="Asia/Katmandu"
+  >
+    Asia/Katmandu: GMT+5.45 (Waktu Nepal)
+  </option>
+  
+      
+  <option
+    value="Atlantic/Canary"
+  >
+    Atlantic/Canary: GMT (Waktu Standar Eropa Barat)
+  </option>
+  
+      
+  <option
+    value="Australia/South"
+  >
+    Australia/South: GMT+10.30 (Waktu Musim Panas Tengah Australia)
+  </option>
+  
+      
+  <option
+    value="Brazil/East"
+  >
+    Brazil/East: GMT-3 (Waktu Standar Brasil)
+  </option>
+  
+      
+  <option
+    value="Canada/Atlantic"
+  >
+    Canada/Atlantic: AST (Waktu Standar Atlantik)
+  </option>
+  
+      
+  <option
+    value="Chile/Continental"
+  >
+    Chile/Continental: GMT-3 (Waktu Musim Panas Cile)
+  </option>
+  
+      
+  <option
+    value="EST"
+  >
+    EST: EST (Waktu Standar Timur)
+  </option>
+  
+      
+  <option
+    value="Etc/GMT-7"
+  >
+    Etc/GMT-7: GMT+7 (GMT+07.00)
+  </option>
+  
+      
+  <option
+    value="Europe/Brussels"
+  >
+    Europe/Brussels: GMT+1 (Waktu Standar Eropa Tengah)
+  </option>
+  
+      
+  <option
+    value="GMT"
+  >
+    GMT: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+      
+  <option
+    value="Indian/Maldives"
+  >
+    Indian/Maldives: GMT+5 (Waktu Maladewa)
+  </option>
+  
+      
+  <option
+    value="Pacific/Tarawa"
+  >
+    Pacific/Tarawa: GMT+12 (Waktu Kep. Gilbert)
+  </option>
+  
+      
+  <option
+    value="UTC"
+  >
+    UTC: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+      
+  <option
+    value="Universal"
+  >
+    Universal: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+      
+  <option
+    value="Zulu"
+  >
+    Zulu: UTC (Waktu Universal Terkoordinasi)
+  </option>
+  
+    
+</select>
+`;
+
+exports[`LocaleController should skip updating the default option if server time zone is not provided 1`] = `
+<select
+  data-action="w-init:ready->w-locale#localizeTimeZoneOptions"
+  data-controller="w-locale"
+  name="locale-current_time_zone"
+>
+  
+      
+  <option
+    selected=""
+    value=""
+  >
+    Use server time zone
+  </option>
+  
+      
+  <option
+    value="Africa/Abidjan"
+  >
+    Africa/Abidjan: غرينتش (توقيت غرينتش)
+  </option>
+  
+      
+  <option
+    value="America/Argentina/Jujuy"
+  >
+    America/Argentina/Jujuy: غرينتش-٣ (توقيت الأرجنتين الرسمي)
+  </option>
+  
+      
+  <option
+    value="America/Indiana/Knox"
+  >
+    America/Indiana/Knox: غرينتش-٦ (التوقيت الرسمي المركزي لأمريكا الشمالية)
+  </option>
+  
+      
+  <option
+    value="Antarctica/Rothera"
+  >
+    Antarctica/Rothera: غرينتش-٣ (توقيت روثيرا)
+  </option>
+  
+      
+  <option
+    value="Arctic/Longyearbyen"
+  >
+    Arctic/Longyearbyen: غرينتش+١ (توقيت وسط أوروبا الرسمي)
+  </option>
+  
+      
+  <option
+    value="Asia/Katmandu"
+  >
+    Asia/Katmandu: غرينتش+٥:٤٥ (توقيت نيبال)
+  </option>
+  
+      
+  <option
+    value="Atlantic/Canary"
+  >
+    Atlantic/Canary: غرينتش (توقيت غرب أوروبا الرسمي)
+  </option>
+  
+      
+  <option
+    value="Australia/South"
+  >
+    Australia/South: غرينتش+١٠:٣٠ (توقيت وسط أستراليا الصيفي)
+  </option>
+  
+      
+  <option
+    value="Brazil/East"
+  >
+    Brazil/East: غرينتش-٣ (توقيت برازيليا الرسمي)
+  </option>
+  
+      
+  <option
+    value="Canada/Atlantic"
+  >
+    Canada/Atlantic: غرينتش-٤ (التوقيت الرسمي الأطلسي)
+  </option>
+  
+      
+  <option
+    value="Chile/Continental"
+  >
+    Chile/Continental: غرينتش-٣ (توقيت تشيلي الصيفي)
+  </option>
+  
+      
+  <option
+    value="EST"
+  >
+    EST: غرينتش-٥ (التوقيت الرسمي الشرقي لأمريكا الشمالية)
+  </option>
+  
+      
+  <option
+    value="Etc/GMT-7"
+  >
+    Etc/GMT-7: غرينتش+٧ (غرينتش+٠٧:٠٠)
+  </option>
+  
+      
+  <option
+    value="Europe/Brussels"
+  >
+    Europe/Brussels: غرينتش+١ (توقيت وسط أوروبا الرسمي)
+  </option>
+  
+      
+  <option
+    value="GMT"
+  >
+    GMT: UTC (التوقيت العالمي المنسق)
+  </option>
+  
+      
+  <option
+    value="Indian/Maldives"
+  >
+    Indian/Maldives: غرينتش+٥ (توقيت جزر المالديف)
+  </option>
+  
+      
+  <option
+    value="Pacific/Tarawa"
+  >
+    Pacific/Tarawa: غرينتش+١٢ (توقيت جزر جيلبرت)
+  </option>
+  
+      
+  <option
+    value="UTC"
+  >
+    UTC: UTC (التوقيت العالمي المنسق)
+  </option>
+  
+      
+  <option
+    value="Universal"
+  >
+    Universal: UTC (التوقيت العالمي المنسق)
+  </option>
+  
+      
+  <option
+    value="Zulu"
+  >
+    Zulu: UTC (التوقيت العالمي المنسق)
+  </option>
+  
+    
+</select>
+`;

+ 2 - 0
client/src/controllers/index.ts

@@ -32,6 +32,7 @@ import { TooltipController } from './TooltipController';
 import { UnsavedController } from './UnsavedController';
 import { UpgradeController } from './UpgradeController';
 import { ZoneController } from './ZoneController';
+import { LocaleController } from './LocaleController';
 
 /**
  * Important: Only add default core controllers that should load with the base admin JS bundle.
@@ -53,6 +54,7 @@ export const coreControllerDefinitions: Definition[] = [
   { controllerConstructor: FormsetController, identifier: 'w-formset' },
   { controllerConstructor: InitController, identifier: 'w-init' },
   { controllerConstructor: KeyboardController, identifier: 'w-kbd' },
+  { controllerConstructor: LocaleController, identifier: 'w-locale' },
   { controllerConstructor: OrderableController, identifier: 'w-orderable' },
   { controllerConstructor: PreviewController, identifier: 'w-preview' },
   { controllerConstructor: ProgressController, identifier: 'w-progress' },

+ 0 - 1
setup.py

@@ -31,7 +31,6 @@ install_requires = [
     "beautifulsoup4>=4.8,<4.13",
     "Willow[heif]>=1.8.0,<2",
     "requests>=2.11.1,<3.0",
-    "l18n>=2018.5",
     "openpyxl>=3.0.10,<4.0",
     "anyascii>=0.1.5",
     "telepath>=0.3.1,<1",

+ 0 - 2
wagtail/admin/auth.py

@@ -1,7 +1,6 @@
 import types
 from functools import wraps
 
-import l18n
 from django.conf import settings
 from django.core.exceptions import PermissionDenied
 from django.shortcuts import redirect
@@ -141,7 +140,6 @@ def require_admin_access(view_func):
                     preferred_language = (
                         user.wagtail_userprofile.get_preferred_language()
                     )
-                    l18n.set_language(preferred_language)
                     time_zone = user.wagtail_userprofile.get_current_time_zone()
                 else:
                     time_zone = settings.TIME_ZONE

+ 13 - 8
wagtail/admin/forms/account.py

@@ -1,8 +1,7 @@
 import warnings
-from operator import itemgetter
 
-import l18n
 from django import forms
+from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.db.models.fields import BLANK_CHOICE_DASH
 from django.utils.translation import get_language_info
@@ -59,12 +58,9 @@ def _get_language_choices():
 
 
 def _get_time_zone_choices():
-    time_zones = [
-        (tz, str(l18n.tz_fullnames.get(tz, tz)))
-        for tz in get_available_admin_time_zones()
+    return [("", _("Use server time zone"))] + [
+        (tz, tz) for tz in get_available_admin_time_zones()
     ]
-    time_zones.sort(key=itemgetter(1))
-    return BLANK_CHOICE_DASH + time_zones
 
 
 class LocalePreferencesForm(forms.ModelForm):
@@ -82,7 +78,16 @@ class LocalePreferencesForm(forms.ModelForm):
     )
 
     current_time_zone = forms.ChoiceField(
-        required=False, choices=_get_time_zone_choices, label=_("Current time zone")
+        required=False,
+        choices=_get_time_zone_choices,
+        label=_("Current time zone"),
+        widget=forms.Select(
+            attrs={
+                "data-controller": "w-init w-locale",
+                "data-action": "w-init:ready->w-locale#localizeTimeZoneOptions",
+                "data-w-locale-server-time-zone-param": settings.TIME_ZONE,
+            },
+        ),
     )
 
     class Meta:

+ 16 - 0
wagtail/admin/tests/test_account_management.py

@@ -588,6 +588,22 @@ class TestAccountSection(
             sorted(zoneinfo.available_timezones()),
         )
 
+        response = self.client.get(reverse("wagtailadmin_account"))
+        self.assertEqual(response.status_code, 200)
+        soup = self.get_soup(response.content)
+
+        select = soup.select_one('select[name="locale-current_time_zone"]')
+        self.assertIsNotNone(select)
+        self.assertEqual(select.get("data-controller"), "w-init w-locale")
+        self.assertEqual(
+            select.get("data-action"),
+            "w-init:ready->w-locale#localizeTimeZoneOptions",
+        )
+        self.assertEqual(
+            select.get("data-w-locale-server-time-zone-param"),
+            settings.TIME_ZONE,
+        )
+
     @unittest.skipUnless(settings.USE_TZ, "Timezone support is disabled")
     @override_settings(WAGTAIL_USER_TIME_ZONES=["Europe/London"])
     def test_not_show_options_if_only_one_time_zone_is_permitted(self):