diff --git a/.gitignore b/.gitignore index a807c71..c1f4e54 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ !*.h !*.rst !samples/tests/*.sh +!*.po !LICENSE !HEADER diff --git a/.travis.yml b/.travis.yml index 95ce90a..55f5f64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ compiler: before_install: - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get -qq update - - sudo apt-get -qq install -y check gcc-4.9 + - sudo apt-get -qq install -y check gcc-4.9 gettext autopoint - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 90 - sudo pip install cpp-coveralls script: diff --git a/Makefile.am b/Makefile.am index 482175a..bcc7f94 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = dependencies/csptr samples +AM_CPPFLAGS = -DLOCALEDIR='"$(localedir)"' +SUBDIRS = po dependencies/csptr samples lib_LTLIBRARIES = libcriterion.la @@ -19,7 +20,7 @@ libcriterion_la_LDFLAGS = $(COVERAGE_LDFLAGS) # dirty but unless someone has a better alternative... libcriterion_la_LIBADD = dependencies/csptr/src/libcsptr_la-*.lo -EXTRA_DIST = LICENSE +EXTRA_DIST = config.rpath LICENSE subdirincludedir = $(includedir)/criterion/ subdirinclude_HEADERS = \ @@ -51,6 +52,8 @@ libcriterion_la_SOURCES = \ src/options.c \ src/timer.c \ src/timer.h \ + src/i18n.c \ + src/i18n.h \ src/ordered-set.c \ src/posix-compat.c \ src/main.c diff --git a/autogen.sh b/autogen.sh index 491727c..886e91f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,3 +1,4 @@ #!/bin/sh git submodule update --init --recursive +autopoint autoreconf -i diff --git a/configure.ac b/configure.ac index e8de7d2..0951dab 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,9 @@ AC_SUBST([LIBTOOL_DEPS]) AC_FUNC_FNMATCH +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.18]) + AC_ARG_ENABLE([gcov], [AS_HELP_STRING([--enable-gcov], [Compile the project with converage enabled])], @@ -33,7 +36,7 @@ AC_ARG_ENABLE([gcov], []) AC_CONFIG_HEADERS([src/config.h]) -AC_CONFIG_FILES([Makefile samples/Makefile]) +AC_CONFIG_FILES([Makefile samples/Makefile po/Makefile.in]) AC_CONFIG_SUBDIRS([dependencies/csptr]) diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 776361a..86aed5a 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -25,6 +25,7 @@ # define CRITERION_LOGGING_H_ # include +# include # include "common.h" # include "ordered-set.h" # include "stats.h" @@ -34,12 +35,61 @@ enum criterion_logging_level { CRITERION_IMPORTANT, }; +enum criterion_logging_prefix { + CRITERION_LOGGING_PREFIX_DASHES, + CRITERION_LOGGING_PREFIX_EQUALS, + CRITERION_LOGGING_PREFIX_RUN, + CRITERION_LOGGING_PREFIX_SKIP, + CRITERION_LOGGING_PREFIX_PASS, + CRITERION_LOGGING_PREFIX_FAIL, +}; + +struct criterion_prefix_data { + const char *prefix; + const char *color; +}; + +# ifdef CRITERION_LOGGING_COLORS +# define CRIT_COLOR_NORMALIZE(Str) (criterion_options.use_ascii ? "" : Str) + +# define CRIT_FG_BOLD "\e[0;1m" +# define CRIT_FG_RED "\e[0;31m" +# define CRIT_FG_GREEN "\e[0;32m" +# define CRIT_FG_GOLD "\e[0;33m" +# define CRIT_FG_BLUE "\e[0;34m" +# define CRIT_RESET "\e[0m" + +# define FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD) +# define FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED) +# define FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN) +# define FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD) +# define FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE) +# define RESET CRIT_COLOR_NORMALIZE(CRIT_RESET) +# endif + +extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; + +# define CRITERION_PREFIX_DASHES (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_DASHES]) +# define CRITERION_PREFIX_EQUALS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_EQUALS]) +# define CRITERION_PREFIX_RUN (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_RUN ]) +# define CRITERION_PREFIX_SKIP (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_SKIP ]) +# define CRITERION_PREFIX_PASS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_PASS ]) +# define CRITERION_PREFIX_FAIL (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_EQUALS]) + +void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); + +FORMAT(printf, 3, 4) +void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); + FORMAT(printf, 2, 3) void criterion_log(enum criterion_logging_level level, const char *msg, ...); # define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__) # define criterion_important(...) criterion_log(CRITERION_IMPORTANT, __VA_ARGS__) +# define criterion_pinfo(...) criterion_plog(CRITERION_INFO, __VA_ARGS__) +# define criterion_pimportant(...) criterion_plog(CRITERION_IMPORTANT, __VA_ARGS__) + struct criterion_output_provider { void (*log_pre_all )(struct criterion_test_set *set); void (*log_pre_suite )(struct criterion_suite_set *set); diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..527e861 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1 @@ +fr diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..70daf30 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,78 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Franklin "Snaipe" Mathieu + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = no + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' +# context. Possible values are "yes" and "no". Set this to yes if the +# package uses functions taking also a message context, like pgettext(), or +# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. +USE_MSGCTXT = no + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages, +# --quiet to reduce the verbosity. +MSGMERGE_OPTIONS = + +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +# This tells whether or not to regenerate a PO file when $(DOMAIN).pot +# has changed. Possible values are "yes" and "no". Set this to no if +# the POT file is checked in the repository and the version control +# program ignores timestamps. +PO_DEPENDS_ON_POT = yes + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = yes diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..d9d2b16 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,2 @@ +# List of source files which contain translatable strings. +src/log/normal.c diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..f2a909b --- /dev/null +++ b/po/fr.po @@ -0,0 +1,68 @@ +# French translations for criterion package +# Traductions françaises du paquet criterion. +# Copyright (C) 2015 Franklin "Snaipe" Mathieu +# This file is distributed under the same license as the criterion package. +# , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: criterion 1.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-03 17:57+0200\n" +"PO-Revision-Date: 2015-04-03 17:58+0200\n" +"Last-Translator: \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: src/log/normal.c:38 +#, c-format +msgid "Criterion v%s\n" +msgstr "Criterion v%s\n" + +#: src/log/normal.c:42 +#, c-format +msgid "%1$s::%2$s\n" +msgstr "%1$s::%2$s\n" + +#: src/log/normal.c:68 +#, c-format +msgid "%1$s::%2$s: Test is disabled\n" +msgstr "%1$s::%2$s: Le test est désactivé\n" + +#: src/log/normal.c:69 +#, c-format +msgid "%1$s::%2$s: Suite is disabled\n" +msgstr "%1$s::%2$s: La suite est désactivée\n" + +#: src/log/normal.c:80 +#, c-format +msgid "" +"%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" +"%9$lu%10$s | Crashing: %11$s%12$lu%13$s %14$s\n" +msgstr "" +"%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s" +"%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n" + +#: src/log/normal.c:99 +#, c-format +msgid "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n" +msgstr "%1$s%2$s%3$s:%4$s%5$d%6$s: Échec d'assertion: %7$s\n" + +#: src/log/normal.c:105 +#, c-format +msgid " %s\n" +msgstr " %s\n" + +#: src/log/normal.c:112 +#, c-format +msgid "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n" +msgstr "%1$s%2$s%3$s:%4$s%5$u%6$s: Un signal inattendu a été reçu après cette ligne!\n" + +#: src/log/normal.c:116 +#, c-format +msgid "%1$s::%2$s: CRASH!\n" +msgstr "%1$s::%2$s: PLANTAGE!\n" diff --git a/src/i18n.c b/src/i18n.c new file mode 100644 index 0000000..9507789 --- /dev/null +++ b/src/i18n.c @@ -0,0 +1,8 @@ +#include "i18n.h" + +#ifdef I18N +__attribute__ ((constructor)) +void init_i18n(void) { + bindtextdomain (PACKAGE, LOCALEDIR); +} +#endif diff --git a/src/i18n.h b/src/i18n.h new file mode 100644 index 0000000..83a62f2 --- /dev/null +++ b/src/i18n.h @@ -0,0 +1,15 @@ +#ifndef I18N_H_ +# define I18N_H_ + +# include "config.h" + +# ifndef I18N +# define _(String) String +# define _s(String, Plural, Quantity) ((Quantity) == 1 ? String : Plural) +# else +# include +# define _(String) dgettext(PACKAGE, String) +# define _s(String, Plural, Quantity) dngettext(PACKAGE, String, Plural, (Quantity)) +# endif + +#endif /* !I18N_H_ */ diff --git a/src/log/logging.c b/src/log/logging.c index f26d1e2..5d2bc8d 100644 --- a/src/log/logging.c +++ b/src/log/logging.c @@ -21,18 +21,54 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#define CRITERION_LOGGING_COLORS #include #include +#include #include "criterion/logging.h" #include "criterion/options.h" +#include "i18n.h" -void criterion_log(enum criterion_logging_level level, const char *msg, ...) { +#define LOG_FORMAT "[%1$s%2$s%3$s] %4$s" + +const struct criterion_prefix_data g_criterion_logging_prefixes[] = { + [CRITERION_LOGGING_PREFIX_DASHES] = { "----", CRIT_FG_BLUE }, + [CRITERION_LOGGING_PREFIX_EQUALS] = { "====", CRIT_FG_BLUE }, + [CRITERION_LOGGING_PREFIX_RUN] = { "RUN ", CRIT_FG_BLUE }, + [CRITERION_LOGGING_PREFIX_SKIP] = { "SKIP", CRIT_FG_GOLD }, + [CRITERION_LOGGING_PREFIX_PASS] = { "PASS", CRIT_FG_GREEN }, + [CRITERION_LOGGING_PREFIX_FAIL] = { "FAIL", CRIT_FG_RED }, + { NULL } +}; + +void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...) { va_list args; if (level < criterion_options.logging_threshold) return; + char formatted_msg[1024]; va_start(args, msg); - vfprintf(stderr, msg, args); + vsnprintf(formatted_msg, sizeof formatted_msg, msg, args); + va_end(args); + + fprintf(stderr, _(LOG_FORMAT), + CRIT_COLOR_NORMALIZE(prefix->color), + prefix->prefix, + RESET, + formatted_msg); +} + +void criterion_log(enum criterion_logging_level level, const char *msg, ...) { + va_list args; + va_start(args, msg); + criterion_vlog(level, msg, args); va_end(args); } + +void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args) { + if (level < criterion_options.logging_threshold) + return; + + vfprintf(stderr, msg, args); +} diff --git a/src/log/normal.c b/src/log/normal.c index 3e65fb4..c961ccb 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #define _GNU_SOURCE +#define CRITERION_LOGGING_COLORS #include #include #include @@ -31,34 +32,27 @@ #include "criterion/ordered-set.h" #include "timer.h" #include "config.h" - -#define NORMALIZE(Str) (criterion_options.use_ascii ? "" : Str) - -#define FG_BOLD NORMALIZE("\e[0;1m") -#define FG_RED NORMALIZE("\e[0;31m") -#define FG_GREEN NORMALIZE("\e[0;32m") -#define FG_GOLD NORMALIZE("\e[0;33m") -#define FG_BLUE NORMALIZE("\e[0;34m") -#define RESET NORMALIZE("\e[0m") +#include "i18n.h" void normal_log_pre_all(UNUSED struct criterion_test_set *set) { - criterion_info("[%s====%s] Criterion v%s\n", FG_BLUE, RESET, VERSION); + criterion_pinfo(CRITERION_PREFIX_DASHES, _("Criterion v%s\n"), VERSION); } void normal_log_pre_init(struct criterion_test *test) { - criterion_info("[%sRUN%s ] %s::%s\n", FG_BLUE, RESET, test->category, test->name); + criterion_pinfo(CRITERION_PREFIX_RUN, _("%1$s::%2$s\n"), test->category, test->name); if (test->data->description) - criterion_info("[%s----%s] %s\n", FG_BLUE, RESET, test->data->description); + criterion_pinfo(CRITERION_PREFIX_RUN, _(" %s\n"), test->data->description); } void normal_log_post_test(struct criterion_test_stats *stats) { - const char *format = can_measure_time() ? "%s::%s: (%3.2fs)\n" : "%s::%s\n"; - const enum criterion_logging_level level = stats->failed ? CRITERION_IMPORTANT - : CRITERION_INFO; - const char *color = stats->failed ? FG_RED : FG_GREEN; + const char *format = can_measure_time() ? "%1$s::%2$s: (%3$3.2fs)\n" : "%1$s::%2$s\n"; - criterion_log(level, "[%s%s%s] ", color, stats->failed ? "FAIL" : "PASS", RESET); - criterion_log(level, format, + const enum criterion_logging_level level + = stats->failed ? CRITERION_IMPORTANT : CRITERION_INFO; + const struct criterion_prefix_data *prefix + = stats->failed ? CRITERION_PREFIX_FAIL : CRITERION_PREFIX_PASS; + + criterion_plog(level, prefix, _(format), stats->test->category, stats->test->name, stats->elapsed_time); @@ -72,28 +66,32 @@ static inline bool is_disabled(struct criterion_test *t, struct criterion_suite void normal_log_post_suite(struct criterion_suite_stats *stats) { for (struct criterion_test_stats *ts = stats->tests; ts; ts = ts->next) { if (is_disabled(ts->test, stats->suite)) { - criterion_info("[%sSKIP%s] %s::%s: %s is disabled\n", - FG_GOLD, - RESET, + const char *format = ts->test->data->disabled + ? _("%1$s::%2$s: Test is disabled\n") + : _("%1$s::%2$s: Suite is disabled\n"); + + criterion_pinfo(CRITERION_PREFIX_SKIP, format, ts->test->category, - ts->test->name, - ts->test->data->disabled ? "test" : "suite"); + ts->test->name); + if (ts->test->data->description) - criterion_info("[%s----%s] %s\n", FG_BLUE, RESET, ts->test->data->description); + criterion_pinfo(CRITERION_PREFIX_DASHES, " %s\n", ts->test->data->description); } } } void normal_log_post_all(struct criterion_global_stats *stats) { - criterion_important("[%s====%s] ", FG_BLUE, RESET); - criterion_important("%sSynthesis: " SIZE_T_FORMAT " test%s run. " SIZE_T_FORMAT " passed, " SIZE_T_FORMAT " failed (with " SIZE_T_FORMAT " crash%s)%s\n", + criterion_pimportant(CRITERION_PREFIX_EQUALS, + _("%1$sSynthesis: Tested: %2$s%3$lu%4$s " + "| Passing: %5$s%6$lu%7$s " + "| Failing: %8$s%9$lu%10$s " + "| Crashing: %11$s%12$lu%13$s " + "%14$s\n"), FG_BOLD, - stats->nb_tests, - stats->nb_tests == 1 ? " was" : "s were", - stats->tests_passed, - stats->tests_failed, - stats->tests_crashed, - stats->tests_crashed == 1 ? "" : "es", + FG_BLUE, stats->nb_tests, FG_BOLD, + FG_GREEN, stats->tests_passed, FG_BOLD, + FG_RED, stats->tests_failed, FG_BOLD, + FG_RED, stats->tests_crashed, FG_BOLD, RESET); } @@ -102,48 +100,36 @@ void normal_log_assert(struct criterion_assert_stats *stats) { char *dup = strdup(*stats->message ? stats->message : stats->condition), *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); - criterion_important("[%s----%s] ", FG_BLUE, RESET); - criterion_important("%s%s%s:%s%d%s: Assertion failed: %s\n", - FG_BOLD, - stats->file, - RESET, - FG_RED, - stats->line, - RESET, + criterion_pimportant(CRITERION_PREFIX_DASHES, + _("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"), + FG_BOLD, stats->file, RESET, + FG_RED, stats->line, RESET, line); while ((line = strtok_r(NULL, "\n", &saveptr))) - criterion_important("[%s----%s] %s\n", FG_BLUE, RESET, line); + criterion_pimportant(CRITERION_PREFIX_DASHES, _(" %s\n"), line); free(dup); } } void normal_log_test_crash(struct criterion_test_stats *stats) { - criterion_important("[%s----%s] ", FG_BLUE, RESET); - criterion_important("%s%s%s:%s%u%s: Unexpected signal caught below this line!\n", - FG_BOLD, - stats->file, - RESET, - FG_RED, - stats->progress, - RESET); - criterion_important("[%sFAIL%s] %s::%s: CRASH!\n", - FG_RED, - RESET, + criterion_pimportant(CRITERION_PREFIX_DASHES, + _("%1$s%2$s%3$s:%4$s%5$u%6$s: " + "Unexpected signal caught below this line!\n"), + FG_BOLD, stats->file, RESET, + FG_RED, stats->progress, RESET); + criterion_pimportant(CRITERION_PREFIX_FAIL, _("%1$s::%2$s: CRASH!\n"), stats->test->category, stats->test->name); } void normal_log_pre_suite(struct criterion_suite_set *set) { - criterion_info("[%s====%s] ", FG_BLUE, RESET); - criterion_info("Running %s" SIZE_T_FORMAT "%s test%s from %s%s%s:\n", - FG_BLUE, - set->tests->size, - RESET, - set->tests->size == 1 ? "" : "s", - FG_GOLD, - set->suite.name, - RESET); + criterion_pinfo(CRITERION_PREFIX_EQUALS, + _s("Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n", + "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n", + set->tests->size), + FG_BLUE, set->tests->size, RESET, + FG_GOLD, set->suite.name, RESET); } struct criterion_output_provider normal_logging = { diff --git a/src/main.c b/src/main.c index 8cb1f7a..eaaeaa8 100644 --- a/src/main.c +++ b/src/main.c @@ -26,11 +26,16 @@ #include #include #include +#include #include #include #include "runner.h" #include "config.h" +#ifdef I18N +# include +#endif + # define VERSION_MSG "Tests compiled with Criterion v" VERSION "\n" #ifdef HAVE_FNMATCH @@ -130,6 +135,11 @@ int main(int argc, char *argv[]) { bool use_ascii = !strcmp("1", getenv("CRITERION_USE_ASCII") ?: "0") || !strcmp("dumb", getenv("TERM") ?: "dumb"); + setlocale(LC_ALL, ""); +#ifdef I18N + textdomain (PACKAGE "-test"); +#endif + criterion_options = (struct criterion_options) { .always_succeed = !strcmp("1", getenv("CRITERION_ALWAYS_SUCCEED") ?: "0"), .no_early_exit = !strcmp("1", getenv("CRITERION_NO_EARLY_EXIT") ?: "0"),