Some documentation for stumpless has localization available. This is completely
community supported, and the amount of translations available for different
locales varies widely. To see the documentation for a given language, check the
l10n
folder in the root of the repository. There are folders for locales with
translations available. These are structured as a mirror of the root of the
repository, with documents with no localization missing. Note that some
files may only have partial translations available. File and folder names may
be localized as well, though this is not strictly required.
If you would like to contribute localization of part or all of a file, you only need to submit a pull request with the changes made. Keep in mind that only requests with a substantial addition will be added. For example, an update that simply adds a filename with no contents or only a few sentences will not be accepted.
Stumpless implements a simple framework to support different languages for
human-readable output, such as error messages. This implementation is based on
the use of header files with definitions for the strings based on a specific
locale. A simple wrapper header, private/config/wrapper/locale.h
, can then
be included by source files. This wrapper header chooses the correct locale
header based on the build configuration.
Locale headers are located in private/config/locale
and are named after the
locale that they hold using the IETF Language Tag format defined in
RFC 5646. For example, the United
States English locale is in private/config/locale/en-us.h
.
These header files all define the same set of preprocessor symbols, each
beginning with the prefix L10N_
. These are string constants that will be
placed into the source code during compilation to customize the library for
the desired locale.
Some of these symbols may be functions that take string constants as
parameters and insert these into the appropriate location. An example of this
is the L10N_NULL_ARG_ERROR_MESSAGE
function, which takes the name of the
argument that was null as a parameter so that it can insert it into the error
message. Different locales may use this value in different places, or not at
all.
If you are making a change that requires a new error message or other string
that needs to be localized, you will need to add it to all defined locales. It
is required that the en-us
locale include a meaningful definition of the
symbol. Others may be added as a placeholder value, for later translation by
someone with the necessary knowledge. For any string that is not translated,
a comment of // todo translate
must be added before the definition, and the
value of the string must be equal to the en-us
value as a fallback. The
scripts/check_l10n.rb
script can check this, and is run during integration
tests on all headers.
The scripts/add_l10n_string.rb
provides a quick way to do all of this for new
strings. Run it with the name of the new string and the english translation,
and it will insert placeholders into all locale headers. Here's an example
invocation:
# this will result in a string of L10N_TEST_STR being added to all locale
# headers with the english translation of "this is a test string"
ruby scripts/add_l10n_string.rb TEST_STR this is a test string
Strings that need to be translated are marked with a // todo translate
comment
in the localization headers. This means that you can easily find how many
strings need to be translated in any locale, despite stumpless not currently
having any integrations with translation frameworks. The following grep
invocation will give a count of how many untranslated strings exist:
grep -r -c "// todo translate" include/private/config/locale/
# output looks like this:
# include/private/config/locale/bg-bg.h:12
# include/private/config/locale/cz-cz.h:1
# include/private/config/locale/de-de.h:20
# include/private/config/locale/el-gr.h:0
# include/private/config/locale/en-us.h:0
# include/private/config/locale/es-es.h:2
# include/private/config/locale/fr-fr.h:20
# include/private/config/locale/it-it.h:0
# include/private/config/locale/pl-pl.h:1
# include/private/config/locale/sk-sk.h:17
# include/private/config/locale/sv-se.h:20
Adding a new locale to the library only requires the addition of the new header file and making sure that it can be used during build configuration. Adding the header is straightforward: just copy any already existing header (this will be easier if you understand the language of the original) and then change the defined symbols to reflect your new locale. Be sure that the name of the new header is a valid IETF Language Tag in all lowercase letters.
After adding the header itself, you will need to tie it in to the build system
by updating the tools/cmake/l10n.cmake
file, the include/private/config.h.in
header template, and the locale wrapper
include/private/config/wrapper/locale.h
. In the CMake script, add an elseif
block to the chain of conditionals responsible for determining the locale
following the pattern of the others that are already there. Next, in the private
config header template, add a definition for the locale symbol for the new
locale. This symbol should be of the form USE_LOCALE_XXX
where the last
portion is the RFC 5646 language tag in all caps with underscore separators.
Again, reference the already defined locales to see what this should look like.
Finally, in the locale wrapper header add an #elseif
statement for the new
locale symbol in the same order as it appears in the CMake build script to
include the new header.
The last step is to add new CI builds for the new locale to make sure that
there are no immediate problems and catch any future ones that arise. This is
done by updating the .github/workflows/locale.yml
configuration file with a
build profile for the new language. This is relatively simple: just make a new
line in the build matrix with the new language.
Finally, add a flag for the new locale to the project README (in the Key Features section) to show off your hard work to everyone else!