Ste*_*eve 4

BLUF:这是一种永久且干净的方法,可以根据您的喜好更改 Gnome 顶部栏时钟的格式,而无需使用扩展。

\n

我的目标是简单地执行此操作,无需任何扩展,以便在启动时的初始 gdm 登录屏幕上、在活动的登录会话中以及在会话解锁屏幕上一致地看到自定义时间格式。这需要一些挖掘,但关键在于 Gnome 如何处理本地化/国际化,以及 Gnome 挂钟如何获取实际显示在顶部栏中的字符串。

\n

首先,可以在此处找到有关在 Gnome 本地化/国际化中使用 .po 和 .mo 文件的一些背景信息:

\n

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

\n

基本上,在运行时,Gnome 挂钟会获取当前时间并应用本地化/国际化字符串格式。它使用字符串键来查找用于给定区域设置的格式化字符串,以确定实际显示的内容 - 它不依赖于区域设置文件格式化字符串。如果您修改本地化/国际化文件中给定键的返回值,时钟显示将反映更改。本地化/国际化使用两个文件。第一个是翻译人员为每个语言环境填充的人类可读的 .po 文件,可以在其中找到从查找键到格式化字符串的映射。第二个是从 .po 文件生成的 .mo 文件...更多关于这一点以及它如何关联的一点...

\n

以下是 Ubuntu 20.04 中使用的 Gnome 挂钟版本的源链接:

\n

https://github.com/GNOME/gnome-desktop/blob/gnome-3-36/libgnome-desktop/gnome-wall-clock.c

\n

如果您检查从第 310 行开始的函数“gnome_wall_clock_string_for_datetime”,您将看到正在使用的本地化/国际化查找键。有几个。Ubuntu 有多种挂钟显示设置,具体取决于您是否只想显示时间、日期时间、日期和日期时间等。其中每一个都对应于挂钟使用的给定本地化/国际化查找键。您在下面的引号中看到的不是格式字符串本身,而是查找实际格式字符串的关键。每个键周围的 N_( 执行查找:

\n
char *\ngnome_wall_clock_string_for_datetime (GnomeWallClock      *self,\n                      GDateTime           *now,\n                      GDesktopClockFormat  clock_format,\n                      gboolean             show_weekday,\n                      gboolean             show_full_date,\n                      gboolean             show_seconds)\n{\n    const char *format_string;\n\n    g_debug ("clock_format: %s", clock_format == G_DESKTOP_CLOCK_FORMAT_24H ? "24h" : "12h");\n    g_debug ("show_weekday: %s", show_weekday ? "TRUE" : "FALSE");\n    g_debug ("show_full_date: %s", show_full_date ? "TRUE" : "FALSE");\n    g_debug ("show_seconds: %s", show_seconds ? "TRUE" : "FALSE");\n\n    if (clock_format == G_DESKTOP_CLOCK_FORMAT_24H) {\n        if (show_full_date) {\n            if (show_weekday)\n                /* Translators: This is the time format with full date\n                   plus day used in 24-hour mode. Please keep the under-\n                   score to separate the date from the time. */\n                format_string = show_seconds ? T_(N_("%a %b %-e_%R:%S"))\n                    : T_(N_("%a %b %-e_%R"));\n            else\n                /* Translators: This is the time format with full date\n                   used in 24-hour mode. Please keep the underscore to\n                   separate the date from the time. */\n                format_string = show_seconds ? T_(N_("%b %-e_%R:%S"))\n                    : T_(N_("%b %-e_%R"));\n        } else if (show_weekday) {\n            /* Translators: This is the time format with day used\n               in 24-hour mode. */\n            format_string = show_seconds ? T_(N_("%a %R:%S"))\n                : T_(N_("%a %R"));\n        } else {\n            /* Translators: This is the time format without date used\n               in 24-hour mode. */\n            format_string = show_seconds ? T_(N_("%R:%S"))\n                                : T_(N_("%R"));\n        }\n    } else {\n        if (show_full_date) {\n            if (show_weekday)\n                /* Translators: This is a time format with full date\n                   plus day used for AM/PM. Please keep the under-\n                   score to separate the date from the time. */\n                format_string = show_seconds ? T_(N_("%a %b %-e_%l:%M:%S %p"))\n                    : T_(N_("%a %b %-e_%l:%M %p"));\n            else\n                /* Translators: This is a time format with full date\n                   used for AM/PM. Please keep the underscore to\n                   separate the date from the time. */\n                format_string = show_seconds ? T_(N_("%b %-e_%l:%M:%S %p"))\n                    : T_(N_("%b %-e_%l:%M %p"));\n        } else if (show_weekday) {\n            /* Translators: This is a time format with day used\n               for AM/PM. */\n            format_string = show_seconds ? T_(N_("%a %l:%M:%S %p"))\n                : T_(N_("%a %l:%M %p"));\n        } else {\n            /* Translators: This is a time format without date used\n               for AM/PM. */\n            format_string = show_seconds ? T_(N_("%l:%M:%S %p"))\n                : T_(N_("%l:%M %p"));\n        }\n    }\n\n    g_debug ("format_string: %s", format_string);\n\n    return date_time_format (now, format_string);\n}
Run Code Online (Sandbox Code Playgroud)\n

例如,我想要一个自定义格式字符串,用于以 12 小时 (AM/PM) 格式显示日期、日期和时间。也就是说,在 Ubuntu 中,我将时钟设置为以 12 小时格式显示日期、日期和时间,这对应于上面代码中的“完整日期”。检查该函数,我能够确定此“完整日期”查找键出现在第 361 行:

\n
/* Translators: This is a time format with full date\n                   used for AM/PM. Please keep the underscore to\n                   separate the date from the time. */\n                format_string = show_seconds ? T_(N_("%b %-e_%l:%M:%S %p"))\n                    : T_(N_("%b %-e_%l:%M %p"));\n
Run Code Online (Sandbox Code Playgroud)\n

我对几秒钟不感兴趣,所以我需要在本地化/国际化 .po 文件中找到的关键是:

\n
\'%b %-e_%l:%M %p\'
Run Code Online (Sandbox Code Playgroud)\n

不幸的是,我无法在我的语言环境的 en.po 中找到这个特定的键。自 18.04 LTS 版本以来,Gnome 人员似乎已在格式化字符串中用下划线替换了逗号,区域设置文件(至少对于 en)尚未更新以反映此更改。

\n

https://github.com/GNOME/gnome-desktop/blob/gnome-3-36/po/en.po

\n

因此,我需要将其以及映射添加到我想要的格式。

\n
msgid "%a %b %-e_%l:%M %p"\nmsgstr "%A %b %-d, %l:%M %p"\n
Run Code Online (Sandbox Code Playgroud)\n

本地化/国际化 .mo 文件是二进制格式,但可以轻松地从人类可读的纯文本映射 .po 文件生成,该文件将给定的查找键映射到格式化字符串。Gnome 挂钟使用特定名称为 gnome-desktop-3.0.mo 的文件进行本地化/国际化。它不存在于我的系统中任何区域设置的指定位置下:

\n
/usr/share/locale/XX/LC_MESSAGES
Run Code Online (Sandbox Code Playgroud)\n

因此,我不需要担心替换它,而是重新创建它。无论如何,您需要首先获取适合您的语言环境的 .po 文件:

\n

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

\n

同样,“en”区域设置中不存在许多时钟格式字符串,我需要添加我感兴趣的字符串。

\n

在上述“msgstr”中反映更改之前,时钟将显示:

\n
Mon Feb 4  12:22 PM
Run Code Online (Sandbox Code Playgroud)\n

但在上述更改之后,日期不再缩写,并且分隔日期和时间的空格已替换为逗号(有关格式说明符,请参阅此答案的末尾):

\n
Monday Feb 4, 12:22 PM
Run Code Online (Sandbox Code Playgroud)\n

接下来,获取此 .po 文件并在命令行上通过以下命令运行它,以获取 messages.mo 文件,其中 XX 是您的区域设置。在 20.04 中,可以通过“sudo apt install gettext”安装二进制 msgfmt:

\n
msgfmt -cv XX.po
Run Code Online (Sandbox Code Playgroud)\n

接下来,将生成的 messages.mo 文件重命名为 gnome-desktop-3.0.mo 并将其复制到特定区域设置 LC_MESSAGE 目录:

\n
/usr/share/locale/XX/LC_MESSAGES/gnome-desktop-3.0.mo
Run Code Online (Sandbox Code Playgroud)\n

然后,要使更改生效,请注销并重新登录。如果您发现格式没有更改,请仔细检查您当前的时钟设置是否真正对应于您更改格式字符串的键。

\n

最后,这里有一些格式化字符串说明符可以帮助您。我从另一个网站借用了这些,所以不能保证这些都Gnome 中工作:

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