g_date_time_format: Support nominative/genitive months

Supports %OB (alternative, standalone, nominative) month name along
with the old %B (primary, in a complete date format context, genitive)
month name.  Similarly %Ob and %Oh for abbreviated month names.
Depending on the underlying operating system uses nl_langinfo()
or provides our custom implementation.

(Tweaked by Philip Withnall <withnall@endlessm.com> to add test case
comment and bug reference.)

https://bugzilla.gnome.org/show_bug.cgi?id=749206
This commit is contained in:
Rafal Luzynski 2017-03-24 11:19:13 +01:00 committed by Philip Withnall
parent d933cf99bf
commit be4f96b650
4 changed files with 467 additions and 7 deletions

View File

@ -1274,6 +1274,50 @@ AC_CACHE_CHECK([for nl_langinfo (_NL_CTYPE_OUTDIGITn_MB)], glib_cv_langinfo_outd
if test x$glib_cv_langinfo_outdigit = xyes; then
AC_DEFINE(HAVE_LANGINFO_OUTDIGIT,1,[Have nl_langinfo (_NL_CTYPE_OUTDIGITn_MB)])
fi
dnl Check for nl_langinfo and ALTMON_n
AC_CACHE_CHECK([for nl_langinfo (ALTMON_n)], glib_cv_langinfo_altmon,[
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <langinfo.h>],
[char *str;
str = nl_langinfo (ALTMON_1);
str = nl_langinfo (ALTMON_2);
str = nl_langinfo (ALTMON_3);
str = nl_langinfo (ALTMON_4);
str = nl_langinfo (ALTMON_5);
str = nl_langinfo (ALTMON_6);
str = nl_langinfo (ALTMON_7);
str = nl_langinfo (ALTMON_8);
str = nl_langinfo (ALTMON_9);
str = nl_langinfo (ALTMON_10);
str = nl_langinfo (ALTMON_11);
str = nl_langinfo (ALTMON_12);])],
[glib_cv_langinfo_altmon=yes],
[glib_cv_langinfo_altmon=no])])
if test x$glib_cv_langinfo_altmon = xyes; then
AC_DEFINE(HAVE_LANGINFO_ALTMON,1,[Have nl_langinfo (ALTMON_n)])
fi
dnl Check for nl_langinfo and _NL_ABALTMON_n
AC_CACHE_CHECK([for nl_langinfo (_NL_ABALTMON_n)], glib_cv_langinfo_abaltmon,[
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <langinfo.h>],
[char *str;
str = nl_langinfo (_NL_ABALTMON_1);
str = nl_langinfo (_NL_ABALTMON_2);
str = nl_langinfo (_NL_ABALTMON_3);
str = nl_langinfo (_NL_ABALTMON_4);
str = nl_langinfo (_NL_ABALTMON_5);
str = nl_langinfo (_NL_ABALTMON_6);
str = nl_langinfo (_NL_ABALTMON_7);
str = nl_langinfo (_NL_ABALTMON_8);
str = nl_langinfo (_NL_ABALTMON_9);
str = nl_langinfo (_NL_ABALTMON_10);
str = nl_langinfo (_NL_ABALTMON_11);
str = nl_langinfo (_NL_ABALTMON_12);])],
[glib_cv_langinfo_abaltmon=yes],
[glib_cv_langinfo_abaltmon=no])])
if test x$glib_cv_langinfo_abaltmon = xyes; then
AC_DEFINE(HAVE_LANGINFO_ABALTMON,1,[Have nl_langinfo (_NL_ABALTMON_n)])
fi
AC_LANG_RESTORE
dnl ****************************************

View File

@ -46,6 +46,11 @@
#include "config.h"
/* langinfo.h in glibc 2.27 defines ALTMON_* only if _GNU_SOURCE is defined. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <stdlib.h>
#include <string.h>
@ -212,15 +217,37 @@ static const gint month_item[2][12] =
#define WEEKDAY_ABBR(d) (get_weekday_name_abbr (g_date_time_get_day_of_week (d)))
#define WEEKDAY_FULL(d) (get_weekday_name (g_date_time_get_day_of_week (d)))
#define MONTH_ABBR(d) (get_month_name_abbr (g_date_time_get_month (d)))
#define MONTH_FULL(d) (get_month_name (g_date_time_get_month (d)))
/* We don't yet know if nl_langinfo (MON_n) returns standalone or complete-date
* format forms but if nl_langinfo (ALTMON_n) is not supported then we will
* have to use MONTH_FULL as standalone. The same if nl_langinfo () does not
* exist at all. MONTH_ABBR is similar: if nl_langinfo (_NL_ABALTMON_n) is not
* supported then we will use MONTH_ABBR as standalone.
*/
#define MONTH_ABBR(d) (get_month_name_abbr_standalone (g_date_time_get_month (d)))
#define MONTH_FULL(d) (get_month_name_standalone (g_date_time_get_month (d)))
static const gchar *
get_month_name (gint month)
get_month_name_standalone (gint month)
{
switch (month)
{
case 1:
/* Translators: Some languages (Baltic, Slavic, Greek, and some more)
* need different grammatical forms of month names depending on whether
* they are standalone or in a complete date context, with the day
* number. Some other languages may prefer starting with uppercase when
* they are standalone and with lowercase when they are in a complete
* date context. Here are full month names in a form appropriate when
* they are used standalone. If your system is Linux with the glibc
* version 2.27 (released Feb 1, 2018) or newer or if it is from the BSD
* family (which includes OS X) then you can refer to the date command
* line utility and see what the command `date +%OB' produces. Also in
* the latest Linux the command `locale alt_mon' in your native locale
* produces a complete list of month names almost ready to copy and
* paste here. Note that in most of the languages (western European,
* non-European) there is no difference between the standalone and
* complete date form.
*/
return C_("full month name", "January");
case 2:
return C_("full month name", "February");
@ -253,11 +280,28 @@ get_month_name (gint month)
}
static const gchar *
get_month_name_abbr (gint month)
get_month_name_abbr_standalone (gint month)
{
switch (month)
{
case 1:
/* Translators: Some languages need different grammatical forms of
* month names depending on whether they are standalone or in a complete
* date context, with the day number. Some may prefer starting with
* uppercase when they are standalone and with lowercase when they are
* in a full date context. However, as these names are abbreviated
* the grammatical difference is visible probably only in Belarusian
* and Russian. In other languages there is no difference between
* the standalone and complete date form when they are abbreviated.
* If your system is Linux with the glibc version 2.27 (released
* Feb 1, 2018) or newer then you can refer to the date command line
* utility and see what the command `date +%Ob' produces. Also in
* the latest Linux the command `locale ab_alt_mon' in your native
* locale produces a complete list of month names almost ready to copy
* and paste here. Note that this feature is not yet supported by any
* other platform. Here are abbreviated month names in a form
* appropriate when they are used standalone.
*/
return C_("abbreviated month name", "Jan");
case 2:
return C_("abbreviated month name", "Feb");
@ -345,6 +389,171 @@ get_weekday_name_abbr (gint day)
#endif /* HAVE_LANGINFO_TIME */
#ifdef HAVE_LANGINFO_ALTMON
/* If nl_langinfo () supports ALTMON_n then MON_n returns full date format
* forms and ALTMON_n returns standalone forms.
*/
#define MONTH_FULL_WITH_DAY(d) MONTH_FULL(d)
static const gint alt_month_item[12] =
{
ALTMON_1, ALTMON_2, ALTMON_3, ALTMON_4, ALTMON_5, ALTMON_6,
ALTMON_7, ALTMON_8, ALTMON_9, ALTMON_10, ALTMON_11, ALTMON_12
};
#define MONTH_FULL_STANDALONE(d) nl_langinfo (alt_month_item[g_date_time_get_month (d) - 1])
#else
/* If nl_langinfo () does not support ALTMON_n then either MON_n returns
* standalone forms or nl_langinfo (MON_n) does not work so we have defined
* it as standalone form.
*/
#define MONTH_FULL_STANDALONE(d) MONTH_FULL(d)
#define MONTH_FULL_WITH_DAY(d) (get_month_name_with_day (g_date_time_get_month (d)))
static const gchar *
get_month_name_with_day (gint month)
{
switch (month)
{
case 1:
/* Translators: Some languages need different grammatical forms of
* month names depending on whether they are standalone or in a full
* date context, with the day number. Some may prefer starting with
* uppercase when they are standalone and with lowercase when they are
* in a full date context. Here are full month names in a form
* appropriate when they are used in a full date context, with the
* day number. If your system is Linux with the glibc version 2.27
* (released Feb 1, 2018) or newer or if it is from the BSD family
* (which includes OS X) then you can refer to the date command line
* utility and see what the command `date +%B' produces. Also in
* the latest Linux the command `locale mon' in your native locale
* produces a complete list of month names almost ready to copy and
* paste here. In older Linux systems due to a bug the result is
* incorrect in some languages. Note that in most of the languages
* (western European, non-European) there is no difference between the
* standalone and complete date form.
*/
return C_("full month name with day", "January");
case 2:
return C_("full month name with day", "February");
case 3:
return C_("full month name with day", "March");
case 4:
return C_("full month name with day", "April");
case 5:
return C_("full month name with day", "May");
case 6:
return C_("full month name with day", "June");
case 7:
return C_("full month name with day", "July");
case 8:
return C_("full month name with day", "August");
case 9:
return C_("full month name with day", "September");
case 10:
return C_("full month name with day", "October");
case 11:
return C_("full month name with day", "November");
case 12:
return C_("full month name with day", "December");
default:
g_warning ("Invalid month number %d", month);
}
return NULL;
}
#endif /* HAVE_LANGINFO_ALTMON */
#ifdef HAVE_LANGINFO_ABALTMON
/* If nl_langinfo () supports _NL_ABALTMON_n then ABMON_n returns full
* date format forms and _NL_ABALTMON_n returns standalone forms.
*/
#define MONTH_ABBR_WITH_DAY(d) MONTH_ABBR(d)
static const gint ab_alt_month_item[12] =
{
_NL_ABALTMON_1, _NL_ABALTMON_2, _NL_ABALTMON_3, _NL_ABALTMON_4,
_NL_ABALTMON_5, _NL_ABALTMON_6, _NL_ABALTMON_7, _NL_ABALTMON_8,
_NL_ABALTMON_9, _NL_ABALTMON_10, _NL_ABALTMON_11, _NL_ABALTMON_12
};
#define MONTH_ABBR_STANDALONE(d) nl_langinfo (ab_alt_month_item[g_date_time_get_month (d) - 1])
#else
/* If nl_langinfo () does not support _NL_ABALTMON_n then either ABMON_n
* returns standalone forms or nl_langinfo (ABMON_n) does not work so we
* have defined it as standalone form. Now it's time to swap.
*/
#define MONTH_ABBR_STANDALONE(d) MONTH_ABBR(d)
#define MONTH_ABBR_WITH_DAY(d) (get_month_name_abbr_with_day (g_date_time_get_month (d)))
static const gchar *
get_month_name_abbr_with_day (gint month)
{
switch (month)
{
case 1:
/* Translators: Some languages need different grammatical forms of
* month names depending on whether they are standalone or in a full
* date context, with the day number. Some may prefer starting with
* uppercase when they are standalone and with lowercase when they are
* in a full date context. Here are abbreviated month names in a form
* appropriate when they are used in a full date context, with the
* day number. However, as these names are abbreviated the grammatical
* difference is visible probably only in Belarusian and Russian.
* In other languages there is no difference between the standalone
* and complete date form when they are abbreviated. If your system
* is Linux with the glibc version 2.27 (released Feb 1, 2018) or newer
* then you can refer to the date command line utility and see what the
* command `date +%b' produces. Also in the latest Linux the command
* `locale abmon' in your native locale produces a complete list of
* month names almost ready to copy and paste here. In other systems
* due to a bug the result is incorrect in some languages.
*/
return C_("abbreviated month name with day", "Jan");
case 2:
return C_("abbreviated month name with day", "Feb");
case 3:
return C_("abbreviated month name with day", "Mar");
case 4:
return C_("abbreviated month name with day", "Apr");
case 5:
return C_("abbreviated month name with day", "May");
case 6:
return C_("abbreviated month name with day", "Jun");
case 7:
return C_("abbreviated month name with day", "Jul");
case 8:
return C_("abbreviated month name with day", "Aug");
case 9:
return C_("abbreviated month name with day", "Sep");
case 10:
return C_("abbreviated month name with day", "Oct");
case 11:
return C_("abbreviated month name with day", "Nov");
case 12:
return C_("abbreviated month name with day", "Dec");
default:
g_warning ("Invalid month number %d", month);
}
return NULL;
}
#endif /* HAVE_LANGINFO_ABALTMON */
/* Format AM/PM indicator if the locale does not have a localized version. */
static const gchar *
get_fallback_ampm (gint hour)
@ -2736,7 +2945,8 @@ g_date_time_format_locale (GDateTime *datetime,
}
break;
case 'b':
name = MONTH_ABBR (datetime);
name = alt_digits ? MONTH_ABBR_STANDALONE (datetime)
: MONTH_ABBR_WITH_DAY (datetime);
if (g_strcmp0 (name, "") == 0)
return FALSE;
#if !defined (HAVE_LANGINFO_TIME)
@ -2755,7 +2965,8 @@ g_date_time_format_locale (GDateTime *datetime,
}
break;
case 'B':
name = MONTH_FULL (datetime);
name = alt_digits ? MONTH_FULL_STANDALONE (datetime)
: MONTH_FULL_WITH_DAY (datetime);
if (g_strcmp0 (name, "") == 0)
return FALSE;
#if !defined (HAVE_LANGINFO_TIME)
@ -2809,7 +3020,8 @@ g_date_time_format_locale (GDateTime *datetime,
g_date_time_get_week_numbering_year (datetime));
break;
case 'h':
name = MONTH_ABBR (datetime);
name = alt_digits ? MONTH_ABBR_STANDALONE (datetime)
: MONTH_ABBR_WITH_DAY (datetime);
if (g_strcmp0 (name, "") == 0)
return FALSE;
#if !defined (HAVE_LANGINFO_TIME)
@ -3080,6 +3292,14 @@ g_date_time_format_locale (GDateTime *datetime,
* - 0: Pad a numeric result with zeros. This overrides the default padding
* for the specifier.
*
* Additionally, when O is used with B, b, or h, it produces the alternative
* form of a month name. The alternative form should be used when the month
* name is used without a day number (e.g., standalone). It is required in
* some languages (Baltic, Slavic, Greek, and more) due to their grammatical
* rules. For other languages there is no difference. \%OB is a GNU and BSD
* strftime() extension expected to be added to the future POSIX specification,
* \%Ob and \%Oh are GNU strftime() extensions. Since: 2.56
*
* Returns: a newly allocated string formatted to the requested format
* or %NULL in the case that there was an error (such as a format specifier
* not being supported in the current locale). The string

View File

@ -1552,6 +1552,153 @@ test_modifiers (void)
g_free (oldlocale);
}
/* Test that the `O` modifier for g_date_time_format() works with %B, %b and %h;
* i.e. whether genitive month names are supported. */
static void
test_month_names (void)
{
gchar *oldlocale;
g_test_bug ("749206");
oldlocale = g_strdup (setlocale (LC_ALL, NULL));
/* Make sure that nothing has been changed in western European languages. */
setlocale (LC_ALL, "en_GB.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "en_GB") != NULL)
{
TEST_PRINTF_DATE (2018, 1, 1, "%B", "January");
TEST_PRINTF_DATE (2018, 2, 1, "%OB", "February");
TEST_PRINTF_DATE (2018, 3, 1, "%b", "Mar");
TEST_PRINTF_DATE (2018, 4, 1, "%Ob", "Apr");
TEST_PRINTF_DATE (2018, 5, 1, "%h", "May");
TEST_PRINTF_DATE (2018, 6, 1, "%Oh", "Jun");
}
else
g_test_incomplete ("locale en_GB not available, skipping English month names test");
setlocale (LC_ALL, "de_DE.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "de_DE") != NULL)
{
TEST_PRINTF_DATE (2018, 7, 1, "%B", "Juli");
TEST_PRINTF_DATE (2018, 8, 1, "%OB", "August");
TEST_PRINTF_DATE (2018, 9, 1, "%b", "Sep");
TEST_PRINTF_DATE (2018, 10, 1, "%Ob", "Okt");
TEST_PRINTF_DATE (2018, 11, 1, "%h", "Nov");
TEST_PRINTF_DATE (2018, 12, 1, "%Oh", "Dez");
}
else
g_test_incomplete ("locale de_DE not available, skipping German month names test");
setlocale (LC_ALL, "es_ES.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "es_ES") != NULL)
{
TEST_PRINTF_DATE (2018, 1, 1, "%B", "enero");
TEST_PRINTF_DATE (2018, 2, 1, "%OB", "febrero");
TEST_PRINTF_DATE (2018, 3, 1, "%b", "mar");
TEST_PRINTF_DATE (2018, 4, 1, "%Ob", "abr");
TEST_PRINTF_DATE (2018, 5, 1, "%h", "may");
TEST_PRINTF_DATE (2018, 6, 1, "%Oh", "jun");
}
else
g_test_incomplete ("locale es_ES not available, skipping Spanish month names test");
setlocale (LC_ALL, "fr_FR.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "fr_FR") != NULL)
{
TEST_PRINTF_DATE (2018, 7, 1, "%B", "juillet");
TEST_PRINTF_DATE (2018, 8, 1, "%OB", "août");
TEST_PRINTF_DATE (2018, 9, 1, "%b", "sept.");
TEST_PRINTF_DATE (2018, 10, 1, "%Ob", "oct.");
TEST_PRINTF_DATE (2018, 11, 1, "%h", "nov.");
TEST_PRINTF_DATE (2018, 12, 1, "%Oh", "déc.");
}
else
g_test_incomplete ("locale fr_FR not available, skipping French month names test");
/* Make sure that there are visible changes in some European languages. */
setlocale (LC_ALL, "el_GR.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "el_GR") != NULL)
{
TEST_PRINTF_DATE (2018, 1, 1, "%B", "Ιανουαρίου");
TEST_PRINTF_DATE (2018, 2, 1, "%B", "Φεβρουαρίου");
TEST_PRINTF_DATE (2018, 3, 1, "%B", "Μαρτίου");
TEST_PRINTF_DATE (2018, 4, 1, "%OB", "Απρίλιος");
TEST_PRINTF_DATE (2018, 5, 1, "%OB", "Μάιος");
TEST_PRINTF_DATE (2018, 6, 1, "%OB", "Ιούνιος");
TEST_PRINTF_DATE (2018, 7, 1, "%b", "Ιούλ");
TEST_PRINTF_DATE (2018, 8, 1, "%Ob", "Αύγ");
}
else
g_test_incomplete ("locale el_GR not available, skipping Greek month names test");
setlocale (LC_ALL, "hr_HR.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "hr_HR") != NULL)
{
TEST_PRINTF_DATE (2018, 5, 1, "%B", "svibnja");
TEST_PRINTF_DATE (2018, 6, 1, "%B", "lipnja");
TEST_PRINTF_DATE (2018, 7, 1, "%B", "srpnja");
TEST_PRINTF_DATE (2018, 8, 1, "%OB", "Kolovoz");
TEST_PRINTF_DATE (2018, 9, 1, "%OB", "Rujan");
TEST_PRINTF_DATE (2018, 10, 1, "%OB", "Listopad");
TEST_PRINTF_DATE (2018, 11, 1, "%b", "Stu");
TEST_PRINTF_DATE (2018, 12, 1, "%Ob", "Pro");
}
else
g_test_incomplete ("locale hr_HR not available, skipping Croatian month names test");
setlocale (LC_ALL, "lt_LT.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "lt_LT") != NULL)
{
TEST_PRINTF_DATE (2018, 1, 1, "%B", "sausio");
TEST_PRINTF_DATE (2018, 2, 1, "%B", "vasario");
TEST_PRINTF_DATE (2018, 3, 1, "%B", "kovo");
TEST_PRINTF_DATE (2018, 4, 1, "%OB", "balandis");
TEST_PRINTF_DATE (2018, 5, 1, "%OB", "gegužė");
TEST_PRINTF_DATE (2018, 6, 1, "%OB", "birželis");
TEST_PRINTF_DATE (2018, 7, 1, "%b", "Lie");
TEST_PRINTF_DATE (2018, 8, 1, "%Ob", "Rgp");
}
else
g_test_incomplete ("locale lt_LT not available, skipping Lithuanian month names test");
setlocale (LC_ALL, "pl_PL.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "pl_PL") != NULL)
{
TEST_PRINTF_DATE (2018, 5, 1, "%B", "maja");
TEST_PRINTF_DATE (2018, 6, 1, "%B", "czerwca");
TEST_PRINTF_DATE (2018, 7, 1, "%B", "lipca");
TEST_PRINTF_DATE (2018, 8, 1, "%OB", "sierpień");
TEST_PRINTF_DATE (2018, 9, 1, "%OB", "wrzesień");
TEST_PRINTF_DATE (2018, 10, 1, "%OB", "październik");
TEST_PRINTF_DATE (2018, 11, 1, "%b", "lis");
TEST_PRINTF_DATE (2018, 12, 1, "%Ob", "gru");
}
else
g_test_incomplete ("locale pl_PL not available, skipping Polish month names test");
setlocale (LC_ALL, "ru_RU.utf-8");
if (strstr (setlocale (LC_ALL, NULL), "ru_RU") != NULL)
{
TEST_PRINTF_DATE (2018, 1, 1, "%B", "января");
TEST_PRINTF_DATE (2018, 2, 1, "%B", "февраля");
TEST_PRINTF_DATE (2018, 3, 1, "%B", "марта");
TEST_PRINTF_DATE (2018, 4, 1, "%OB", "Апрель");
TEST_PRINTF_DATE (2018, 5, 1, "%OB", "Май");
TEST_PRINTF_DATE (2018, 6, 1, "%OB", "Июнь");
TEST_PRINTF_DATE (2018, 7, 1, "%b", "июл");
TEST_PRINTF_DATE (2018, 8, 1, "%Ob", "авг");
/* This difference is very important in Russian: */
TEST_PRINTF_DATE (2018, 5, 1, "%b", "мая");
TEST_PRINTF_DATE (2018, 5, 1, "%Ob", "май");
}
else
g_test_incomplete ("locale ru_RU not available, skipping Russian month names test");
setlocale (LC_ALL, oldlocale);
g_free (oldlocale);
}
static void
test_GDateTime_dst (void)
{
@ -2167,6 +2314,7 @@ main (gint argc,
g_test_add_func ("/GDateTime/strftime", test_strftime);
g_test_add_func ("/GDateTime/strftime/error_handling", test_GDateTime_strftime_error_handling);
g_test_add_func ("/GDateTime/modifiers", test_modifiers);
g_test_add_func ("/GDateTime/month_names", test_month_names);
g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local);
g_test_add_func ("/GDateTime/to_unix", test_GDateTime_to_unix);
g_test_add_func ("/GDateTime/to_timeval", test_GDateTime_to_timeval);

View File

@ -769,6 +769,54 @@ if cc.links('''#include <langinfo.h>
glib_conf.set('HAVE_LANGINFO_OUTDIGIT', 1)
endif
# Check for nl_langinfo and alternative month names
if cc.links('''#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <langinfo.h>
int main (int argc, char ** argv) {
char *str;
str = nl_langinfo (ALTMON_1);
str = nl_langinfo (ALTMON_2);
str = nl_langinfo (ALTMON_3);
str = nl_langinfo (ALTMON_4);
str = nl_langinfo (ALTMON_5);
str = nl_langinfo (ALTMON_6);
str = nl_langinfo (ALTMON_7);
str = nl_langinfo (ALTMON_8);
str = nl_langinfo (ALTMON_9);
str = nl_langinfo (ALTMON_10);
str = nl_langinfo (ALTMON_11);
str = nl_langinfo (ALTMON_12);
return 0;
}''', name : 'nl_langinfo (ALTMON_n)')
glib_conf.set('HAVE_LANGINFO_ALTMON', 1)
endif
# Check for nl_langinfo and abbreviated alternative month names
if cc.links('''#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <langinfo.h>
int main (int argc, char ** argv) {
char *str;
str = nl_langinfo (_NL_ALTMON_1);
str = nl_langinfo (_NL_ALTMON_2);
str = nl_langinfo (_NL_ALTMON_3);
str = nl_langinfo (_NL_ALTMON_4);
str = nl_langinfo (_NL_ALTMON_5);
str = nl_langinfo (_NL_ALTMON_6);
str = nl_langinfo (_NL_ALTMON_7);
str = nl_langinfo (_NL_ALTMON_8);
str = nl_langinfo (_NL_ALTMON_9);
str = nl_langinfo (_NL_ALTMON_10);
str = nl_langinfo (_NL_ALTMON_11);
str = nl_langinfo (_NL_ALTMON_12);
return 0;
}''', name : 'nl_langinfo (_NL_ALTMON_n)')
glib_conf.set('HAVE_LANGINFO_ABALTMON', 1)
endif
# Check if C compiler supports the 'signed' keyword
if not cc.compiles('''signed char x;''', name : 'signed')
glib_conf.set('signed', '/* NOOP */')