Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20260907024553.GA25922@brightrain.aerifal.cx>
Date: Sun, 6 Sep 2026 22:45:53 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Idiom to replace LCTRANS/gettext approach in locale overhaul

I'm working out some of the last details for actually being able to
merge the locale overhaul. The big thing we set out to replace was the
gettext-style string localization, which did not work for "May", and
while inexpensive in the C-locale case, made substitution by a
localized string rather slow. In addition, the C-locale message lookup
for everything but strerror already was slow (linear search over a
multi-string).

The new approach performs O(1)-time lookup via the int-keyed
multi-level table format, for both the baked-in C-locale strings and
localized ones. This has been the plan since near the beginning, but
the source-level idiom for the logic hasn't been spelled out til now.

The approach I've settled on lets the relevant functions -- strerror,
gai_strerror, hstrerror, reg_error, and nl_langinfo -- share all of
their core logic in a function which takes the following arguments:

- built-in table for the C locale
- mmapped table for the requested locale
- key for the string requested
- fallback key if requested key is not found

First, it checks whether the requested key is present in the C locale.
This ensures that invalid keys are caught and that a locale file which
has new keys for things added in a later libc version don't cause
older libc versions to wrongly show those things as present.

If the key is found in the C locale, a lookup is performed in the
requested locale. If successful, it's used. If not, the value obtained
from the C locale is used.

If the key is not found in the C locale, the above process is repeated
with the fallback key. This makes it so each of the above functions
does not need its own independent logic for "unknown error code" or
similar. It simply provides the key for the "Unknown error" string
(for errno, /4/0/-1) as fallback, and the shared logic handles the
rest, including getting the localized version of the fallback if
available.

In the case of nl_langinfo, where the fallback result should be "" and
locales must not be able to override this, we can just pass a key
that's not present in the C locale data. This will prevent a localized
lookup, and nl_langinfo() can replace the null-pointer result with ""
before returning.

For strerror with untranslated messages, all of this comes out
slightly "worse" than the current implementation in code size and
performance, simply because it's generalized and using a portable data
format rather than a native array. For the rest, though, it comes out
far better than what we have now, and I don't think the difference for
strerror is significant.

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.