Added initial localization support

This commit is contained in:
Leon Styhre 2024-06-29 21:24:28 +02:00
parent b7b873e553
commit ec8a49623a
8 changed files with 192 additions and 1 deletions

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
# Object files
*.o
*.lo
*.mo
*.slo
# Shared libraries

View file

@ -0,0 +1,60 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindIntl
--------
Find the Gettext libintl headers and libraries.
This module reports information about the Gettext libintl
installation in several variables. General variables::
Intl_FOUND - true if the libintl headers and libraries were found
Intl_INCLUDE_DIRS - the directory containing the libintl headers
Intl_LIBRARIES - libintl libraries to be linked
The following cache variables may also be set::
Intl_INCLUDE_DIR - the directory containing the libintl headers
Intl_LIBRARY - the libintl library (if any)
.. note::
On some platforms, such as Linux with GNU libc, the gettext
functions are present in the C standard library and libintl
is not required. ``Intl_LIBRARIES`` will be empty in this
case.
.. note::
If you wish to use the Gettext tools (``msgmerge``,
``msgfmt``, etc.), use :module:`FindGettext`.
#]=======================================================================]
# Written by Roger Leigh <rleigh@codelibre.net>
# Find include directory
find_path(Intl_INCLUDE_DIR
NAMES "libintl.h"
DOC "libintl include directory")
mark_as_advanced(Intl_INCLUDE_DIR)
# Find all Intl libraries
find_library(Intl_LIBRARY "intl"
DOC "libintl libraries (if not in the C library)")
mark_as_advanced(Intl_LIBRARY)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl
FOUND_VAR Intl_FOUND
REQUIRED_VARS Intl_INCLUDE_DIR
FAIL_MESSAGE "Failed to find Gettext libintl")
if(Intl_FOUND)
set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}")
if(Intl_LIBRARY)
set(Intl_LIBRARIES "${Intl_LIBRARY}")
else()
unset(Intl_LIBRARIES)
endif()
endif()

View file

@ -136,6 +136,7 @@ elseif(NOT EMSCRIPTEN AND NOT ANDROID)
find_package(FFmpeg REQUIRED)
find_package(FreeImage REQUIRED)
find_package(Freetype REQUIRED)
find_package(Intl REQUIRED)
find_package(Libgit2 REQUIRED)
find_package(Pugixml REQUIRED)
find_package(SDL2 REQUIRED)

View file

@ -36,6 +36,7 @@
#include "guis/GuiTextEditKeyboardPopup.h"
#include "guis/GuiTextEditPopup.h"
#include "guis/GuiThemeDownloader.h"
#include "utils/LocalizationUtil.h"
#include "utils/PlatformUtil.h"
#if defined(__ANDROID__)
@ -48,7 +49,7 @@
GuiMenu::GuiMenu()
: mRenderer {Renderer::getInstance()}
, mMenu {"MAIN MENU"}
, mMenu {_("MAIN MENU")}
, mThemeDownloaderReloadCounter {0}
{
const bool isFullUI {UIModeController::getInstance()->isUIModeFull()};

View file

@ -29,6 +29,7 @@
#include "guis/GuiDetectDevice.h"
#include "guis/GuiLaunchScreen.h"
#include "utils/FileSystemUtil.h"
#include "utils/LocalizationUtil.h"
#include "utils/PlatformUtil.h"
#include "utils/StringUtil.h"
#include "views/ViewController.h"
@ -732,6 +733,7 @@ int main(int argc, char* argv[])
return 0;
}
Utils::Localization::setLanguage(Utils::Localization::getLocale());
Scripting::fireEvent("startup");
#if defined(__EMSCRIPTEN__)

View file

@ -90,6 +90,7 @@ set(CORE_HEADERS
# Utils
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/CImgUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/LocalizationUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/MathUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/PlatformUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.h
@ -164,6 +165,7 @@ set(CORE_SOURCES
# Utils
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/CImgUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/LocalizationUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/MathUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/PlatformUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.cpp

View file

@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT
//
// ES-DE Frontend
// LocalizationUtil.cpp
//
// Localization functions.
// Provides support for translations using gettext/libintl.
//
#include "utils/LocalizationUtil.h"
#include "Log.h"
#include "resources/ResourceManager.h"
#include "utils/StringUtil.h"
#include <algorithm>
#include <iostream>
namespace Utils
{
namespace Localization
{
std::string getLocale()
{
std::string language;
// The LANGUAGE environment variable takes precedence over LANG.
if (getenv("LANGUAGE") != nullptr)
language = getenv("LANGUAGE");
const std::vector<std::string> languageValues {
Utils::String::delimitedStringToVector(language, ":")};
for (auto value : languageValues) {
if (std::find(sSupportedLanguages.cbegin(), sSupportedLanguages.cend(), value) !=
sSupportedLanguages.cend()) {
return value;
}
}
if (getenv("LANG") != nullptr)
language = getenv("LANG");
if (language.empty())
return "en_US";
return language.substr(0, language.find("."));
}
void setLanguage(const std::string& locale)
{
if (std::find(sSupportedLanguages.cbegin(), sSupportedLanguages.cend(), locale) ==
sSupportedLanguages.cend()) {
LOG(LogInfo) << "No support for language \"" << locale
<< "\", reverting to default language \"en_US\"";
return;
}
else {
LOG(LogInfo) << "Setting application language to \"" << locale << "\"";
}
// No need to perform translations if we're using the default language.
if (locale == "en_US")
return;
std::string localePath;
localePath.append("/")
.append(locale)
.append("/LC_MESSAGES/")
.append(locale)
.append(".mo");
// If the message catalog file is not found then an emergency shutdown will be
// initiated by ResourceManager.
std::string objectPath {
ResourceManager::getInstance().getResourcePath(":/locale" + localePath)};
// This makes it possible to override the message catalog with a file in the
// application data directory.
if (objectPath.length() > localePath.length())
objectPath = objectPath.substr(0, objectPath.length() - localePath.length());
setenv("LANGUAGE", locale.c_str(), 1);
setlocale(LC_MESSAGES, "");
textdomain(locale.c_str());
bindtextdomain(locale.c_str(), objectPath.c_str());
bind_textdomain_codeset(locale.c_str(), "UTF-8");
}
} // namespace Localization
} // namespace Utils

View file

@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
//
// ES-DE Frontend
// LocalizationUtil.h
//
// Localization functions.
// Provides support for translations using gettext/libintl.
//
#ifndef ES_CORE_UTILS_LOCALIZATION_UTIL_H
#define ES_CORE_UTILS_LOCALIZATION_UTIL_H
#include <libintl.h>
#include <string>
#include <vector>
#define _(STR) std::string(gettext(STR))
namespace Utils
{
namespace Localization
{
static inline std::vector<std::string> sSupportedLanguages {"en_US", "sv_SE"};
std::string getLocale();
void setLanguage(const std::string& locale);
} // namespace Localization
} // namespace Utils
#endif // ES_CORE_UTILS_LOCALIZATION_UTIL_H