--- a/src/locale/dcngettext.c 2017-02-06 14:39:17.860482624 +0000 +++ b/src/locale/dcngettext.c 2017-02-06 14:39:17.860482624 +0000 @@ -19,6 +19,7 @@ }; static void *volatile bindings; +char *__strchrnul(const char *, int); static char *gettextdir(const char *domainname, size_t *dirlen) { @@ -143,7 +143,7 @@ catname = catnames[category]; catlen = catlens[category]; - loclen = strlen(locname); + loclen = __strchrnul(locname, '.') - locname; size_t namelen = dirlen+1 + loclen+1 + catlen+1 + domlen+3; char name[namelen+1], *s = name; @@ -157,6 +157,8 @@ +rewrite_loc: memcpy(s, locname, loclen); s[loclen] = '/'; s += loclen + 1; +skip_loc: memcpy(s, catname, catlen); s[catlen] = '/'; s += catlen + 1; @@ -174,7 +175,22 @@ void *old_cats; size_t map_size; const void *map = __map_file(name, &map_size); - if (!map) goto notrans; + if (!map) { + if (s = strchr(name + dirlen + 1, '@')) { + *s++ = '/'; + goto skip_loc; + } + if (locname && (s = strchr(name + dirlen + 1, '_')) && (strchr(name + dirlen +1, '/') > s) ) { + if (locname = strchr(locname, '@')) { + loclen = __strchrnul(lm->name, '.') - locname; + goto rewrite_loc; + } else { + *s++ = '/'; + goto skip_loc; + } + } + goto notrans; + } p = calloc(sizeof *p + namelen + 1, 1); if (!p) { __munmap((void *)map, map_size); --- a/src/locale/locale_map.c 2017-02-06 14:39:17.797148750 +0000 +++ b/src/locale/locale_map.c 2017-02-06 14:39:17.797148750 +0000 @@ -32,6 +32,7 @@ struct __locale_map *new = 0; const char *path = 0, *z; char buf[256]; + char *dotp; size_t l, n; if (!*val) { @@ -40,6 +41,12 @@ (val = getenv("LANG")) && *val || (val = "C.UTF-8"); } + if (dotp = strchr(val, '.')) { + char part[256]; + memcpy(part, val, dotp - val); + memcpy(&part[dotp - val], ".UTF-8\0", 7); + val = part; + } /* Limit name length and forbid leading dot or any slashes. */ for (n=0; n