How can I custom format the lock screen date in Ubuntu 20.04 without extensions?

Solution 1:

BLUF: This is a permanent and clean way to alter formatting of the date on the "lock screen" aka screen shield/unlock dialog without the use of extensions.

First, a bit of background on the use of .po and .mo files in Gnome localization/internationalization can be found here:

https://wiki.gnome.org/TranslationProject/LocalisationGuide

Basically, at runtime, Gnome unlock dialog takes the current time and applies localization/internationalization string formatting. It uses a string key to look up a formatting string to use for a given locale to determine what to actually display -- it does not rely on the locale file formatting strings. If you modify the value returned for a given key in the localization/internationalization file, the lock screen/unlock dialog date display will reflect the change. Localization/internationalization uses two files. The first is the human-readable .po file that translators populate for each locale and this is where the mapping from lookup keys to formatting strings can be found. The second is the .mo file that is generated from the .po file... more on this and how it relates in just a bit...

Below is a link to the source for the Gnome unlock dialog version used in Ubuntu 20.04:

https://github.com/GNOME/gnome-shell/blob/gnome-3-36/js/ui/unlockDialog.js

If you examine the function 'updateClock' beginning at line 365, you'll see the localization/internationalization lookup key in use. What you see in quotations below is not the formatting string itself but rather the key to look up the actual formatting string. The N( that surrounds the key performs the lookup:

_updateClock() {
        this._time.text = this._wallClock.clock;

        let date = new Date();
        /* Translators: This is a time format for a date in
           long format */
        let dateFormat = Shell.util_translate_time_string(N_('%A %B %-d'));
        this._date.text = date.toLocaleFormat(dateFormat);
    }

I wanted a custom format string for displaying day-of-week, month, and day in that order. The string key in the javascript appeared to be OK and accomplish what I wanted but I needed to find the actual mapping to be sure.

let dateFormat = Shell.util_translate_time_string(N_('%A %B %-d'));

So the key I needed to find in the localization/internationalization .po file was:

'%A %B %-d'

Unfortunately, I couldn't find the 'en' locale file I needed so I grabbed the en_GB file.

https://github.com/GNOME/gnome-shell/blob/gnome-3-36/po/en_GB.po

Then, I searched for unlockDialog.js in hopes of finding the mapping... and I did on line 2174:

#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:371
msgid "%A %B %-d"
msgstr "%A %-d %B"

This mapping would provide the day-of-week, day, and month instead of day-of-week, month, day that I wanted.

To obtain the desired date format I changed the mapping to:

msgid "%A %B %-d"
msgstr "%A %B %-d"

The localization/internationalization .mo files are binary in format but easily generated from a human-readable plain-text mapping .po files that maps a given lookup key to formatting string. Gnome unlock dialog uses a file with the specific name of gnome-shell.mo for localization/internationalization. It was not present on my system under the prescribed location for any locale:

/usr/share/locale/XX/LC_MESSAGES

So, I didn't need to worry about replacing it but rather creating it anew. Regardless, you need to first obtain the .po file for your locale:

https://github.com/GNOME/gnome-shell/tree/gnome-3-36/po

Prior to the change reflected in the above 'msgstr' the lock screen date would have displayed as:

Monday 4 Feb

But after the above change(see the end of this answer for the formatting specifiers):

Monday Feb 4

Next, take this .po file and run it through the following on the command line to obtain the messages.mo file where XX is your locale. The binary msgfmt can be installed via 'sudo apt install gettext' in 20.04:

msgfmt -cv XX.po

Next, rename the resulting messages.mo file to gnome-shell.mo and copy it to your specific locale LC_MESSAGE directory:

/usr/share/locale/XX/LC_MESSAGES/gnome-shell.mo

Then, to effect the change, reboot.

Finally, here are some formatting string specifiers to help you along. I borrowed these from another site so no guarantees that these all work in Gnome:

The % sign indicating a directive may be immediately followed by a padding modifier, e.g. %-d:

0 - zero-padding
_ - space-padding
- - disable padding

%a - abbreviated weekday name.*
%A - full weekday name.*
%b - abbreviated month name.*
%B - full month name.*
%d - zero-padded day of the month as a decimal number [01,31].
%e - space-padded day of the month as a decimal number [ 1,31]; equivalent to %_d.
%f - microseconds as a decimal number [000000, 999999].
%H - hour (24-hour clock) as a decimal number [00,23].
%I - hour (12-hour clock) as a decimal number [01,12].
%j - day of the year as a decimal number [001,366].
%m - month as a decimal number [01,12].
%M - minute as a decimal number [00,59].
%L - milliseconds as a decimal number [000, 999].
%p - either AM or PM.*
%Q - milliseconds since UNIX epoch.
%s - seconds since UNIX epoch.
%S - second as a decimal number [00,61].
%u - Monday-based (ISO 8601) weekday as a decimal number [1,7].
%U - Sunday-based week of the year as a decimal number [00,53].
%V - ISO 8601 week of the year as a decimal number [01, 53].
%w - Sunday-based weekday as a decimal number [0,6].
%W - Monday-based week of the year as a decimal number [00,53].
%x - the locale’s date, such as %-m/%-d/%Y.*
%X - the locale’s time, such as %-I:%M:%S %p.*
%y - year without century as a decimal number [00,99].
%Y - year with century as a decimal number.
%Z - time zone offset, such as -0700, -07:00, -07, or Z.
%% - a literal percent sign (%).