# Locale functions # # Copyright (C) 2012, 2018, 2019 Patrick McDermott # # This file is part of opkbuild. # # opkbuild is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # opkbuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with opkbuild. If not, see . _OB_DEFAULT_LOCALE='en_US' _OB_INTERNAL_TEXT_DOMAIN="libopkbuild_${LIBOPKBUILD_SHSOVERSION}" _ob_text_domain= _ob_builddir= _ob_msgs_loaded=false ## @brief Get the current message domain ## @details \fBob_get_text_domain\fP() prints the currently loaded message ## domain. ## @return Returns 0 on success. ## @stdout Prints the name of the currently loaded message domain. ## @pure yes This function has no side effects. ob_get_text_domain() { printf '%s' "${_ob_text_domain}" return 0 } _ob_try_load_messages() { local locale="${1}" shift 1 || _ob_abort local ms= if [ x"${_ob_builddir}" != x'' ]; then # Env var set and not null ms="${_ob_builddir}" ms="${ms}/${locale}/${_ob_text_domain}.ms" else ms="${LOCALEDIR}" ms="${ms}/${locale}/LC_MESSAGES/${_ob_text_domain}.ms" fi # POSIX on the dot utility: # "If no readable file is found, a non-interactive shell shall abort" # So to survive an ENOENT or other error and display a more informative # error message before aborting, we need this eval/cat command. This is # more resilient against race conditions than `[ -f "${ms}" ]` is. eval "$(cat "${ms}" 2>/dev/null)" || return 1 return 0 } ## @brief Set and load the message domain ## @details \fBob_set_text_domain\fP() sets and loads the message domain for ## future \fBob_get_msg\fP() calls. A message domain is a catalog of ## localized messages identified by message IDs. Each application ## should have its own message domain. libopkbuild also has its own ## message domain and temporarily switches to it when needed. ## @operand text_domain req The message domain to load. ## @return Returns 0 on success or 1 if \fItext_domain\fP is missing or invalid ## or if the message domain cannot be loaded. ## @pure no This function sets an internal global variable and loads a message ## catalog that sets numerous message variables. ob_set_text_domain() { local text_domain="${1}" shift 1 || _ob_abort case "${text_domain}" in *[!A-Za-z0-9_]* | '') return 1 esac _ob_text_domain="${text_domain}" _ob_builddir="${OB_EXE_BUILDDIR-}" # Exit early if domain's messages have already been loaded. if eval "\${_ob_text_domain_${_ob_text_domain}_loaded:-false}"; then return fi eval "_ob_text_domain_${_ob_text_domain}_loaded=true" # Try to load the messages. if ! _ob_try_load_messages "${LC_MESSAGES%.*}"; then if ! _ob_try_load_messages "${LC_MESSAGES%_*}"; then if ! _ob_try_load_messages "${_OB_DEFAULT_LOCALE}"; then return 1 fi fi fi _ob_msgs_loaded=true return 0 } ## @brief Get a message from the current message domain ## @details \fBob_get_msg\fP() prints a message, identified by a message ID, ## from the currently loaded message catalog. ## \fBob_set_text_domain\fP() must be called first. ## @operand msgid req The ID of the message to print ## @return Returns 0 on success. ## @stdout Prints the requested message from the current message domain. ## @pure yes This function has no side effects. ob_get_msg() { local msgid="${1}" shift 1 || _ob_abort if ! ${_ob_msgs_loaded}; then printf '%s: Error: No text domain set\n' "${0##*/}" >&2 _ob_abort fi eval "printf '%s' \"\${msg_${_ob_text_domain}_${msgid}}\"" return 0 } _ob_get_msg() { local msgid="${1}" shift 1 || _ob_abort eval "printf '%s' \"\${msg_${_OB_INTERNAL_TEXT_DOMAIN}_${msgid}}\"" return 0 } _ob_load_internal_text_domain() { # Make sure LC_MESSAGES is set. if [ x"${LC_MESSAGES:+set}" != x'set' ]; then if [ x"${LC_ALL:+set}" = x'set' ]; then LC_MESSAGES="${LC_ALL}" elif [ x"${LANG:+set}" = x'set' ]; then LC_MESSAGES="${LANG}" else LC_MESSAGES="${_OB_DEFAULT_LOCALE}" fi fi # Try to load the messages. _ob_text_domain="${_OB_INTERNAL_TEXT_DOMAIN}" _ob_builddir="${OB_LIB_BUILDDIR-}" if ! _ob_try_load_messages "${LC_MESSAGES%.*}"; then printf '%s: Error: Failed to load locale messages\n' \ "${0##*/}" >&2 kill 0 exit 1 # Should never be reached, but just in case fi } __init _ob_load_internal_text_domain