From 0704a4b1787b7e5356ee6560e4a692e323c3d076 Mon Sep 17 00:00:00 2001 From: Nicolas Adenis-Lamarre Date: Sun, 12 May 2019 22:28:32 +0200 Subject: [PATCH 1/2] locales init Signed-off-by: Nicolas Adenis-Lamarre --- .gitignore | 1 + CMakeLists.txt | 11 ++++++ es-app/src/main.cpp | 34 +++++++++++++++-- es-app/src/views/SystemView.cpp | 8 +++- es-core/CMakeLists.txt | 2 + es-core/src/LocaleES.cpp | 10 +++++ es-core/src/LocaleES.h | 12 ++++++ locale/CMakeLists.txt | 17 +++++++++ locale/checkLocale.sh | 10 +++++ locale/emulationstation.pot | 37 +++++++++++++++++++ .../lang/fr/LC_MESSAGES/emulationstation.po | 29 +++++++++++++++ 11 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 es-core/src/LocaleES.cpp create mode 100644 es-core/src/LocaleES.h create mode 100644 locale/CMakeLists.txt create mode 100755 locale/checkLocale.sh create mode 100644 locale/emulationstation.pot create mode 100644 locale/lang/fr/LC_MESSAGES/emulationstation.po diff --git a/.gitignore b/.gitignore index 4055d624e6..0e13d33f7b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.slo *.lo *.o +*.mo # Compiled Dynamic libraries *.so diff --git a/CMakeLists.txt b/CMakeLists.txt index ef2d778a22..283e80b23f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,6 +235,17 @@ else() endif() endif() +# i18n +find_program (MSGFMT_EXECUTABLE msgfmt) +find_program (MSGMERGE_EXECUTABLE msgmerge) +find_program (XGETTEXT_EXECUTABLE xgettext) +if(MSGFMT_EXECUTABLE AND MSGMERGE_EXECUTABLE AND XGETTEXT_EXECUTABLE) + message (STATUS "Native language support enabled.") + add_definitions(-DHAVE_GETTEXT) + add_subdirectory (locale) +endif() +add_definitions(-DINSTALLATION_PREFIX_DIR=\"${CMAKE_INSTALL_PREFIX}\") + #------------------------------------------------------------------------------- # set up build directories set(dir ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 6c1fe80ef6..b4b87ebc82 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -24,6 +24,7 @@ #ifdef WIN32 #include #endif +#include "LocaleES.h" #include @@ -196,6 +197,28 @@ bool verifyHomeFolderExists() return true; } +void locales_init() { +#ifdef HAVE_GETTEXT + char* btd; + char* cs; + +#define LOCALEDIR INSTALLATION_PREFIX_DIR "/share/locale" +// local dir ; uncomment if you want to use locally compiled .mo files instead of .mo from the installation dir (present only after make install) +//#define LOCALEDIR "./locale/lang" + + setlocale (LC_MESSAGES, ""); + textdomain("emulationstation"); + if((btd=bindtextdomain("emulationstation", LOCALEDIR)) == NULL) { + return; + } + + cs = bind_textdomain_codeset("emulationstation", "UTF-8"); + if(cs == NULL) { + /* outch not enough memory, no real thing to do */ + } +#endif +} + // Returns true if everything is OK, bool loadSystemConfigFile(const char** errorString) { @@ -287,6 +310,9 @@ int main(int argc, char* argv[]) //always close the log on exit atexit(&onExit); + // Set locale + locales_init(); + Window window; SystemScreenSaver screensaver(&window); PowerSaver::init(); @@ -311,9 +337,9 @@ int main(int argc, char* argv[]) LOG(LogInfo) << " ARB_texture_non_power_of_two: " << (glExts.find("ARB_texture_non_power_of_two") != std::string::npos ? "ok" : "MISSING"); if(splashScreen) { - std::string progressText = "Loading..."; + std::string progressText = _("Loading..."); if (splashScreenProgress) - progressText = "Loading system config..."; + progressText = _("Loading system config..."); window.renderLoadingScreen(progressText); } } @@ -333,7 +359,7 @@ int main(int argc, char* argv[]) // we can't handle es_systems.cfg file problems inside ES itself, so display the error message then quit window.pushGui(new GuiMsgBox(&window, errorMsg, - "QUIT", [] { + _("QUIT"), [] { SDL_Event* quit = new SDL_Event(); quit->type = SDL_QUIT; SDL_PushEvent(quit); @@ -354,7 +380,7 @@ int main(int argc, char* argv[]) ViewController::get()->preload(); if(splashScreen && splashScreenProgress) - window.renderLoadingScreen("Done."); + window.renderLoadingScreen(_("Done.")); //choose which GUI to open depending on if an input configuration already exists if(errorMsg == NULL) diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index cdd5b1ea10..326bea1cd4 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -9,6 +9,7 @@ #include "Settings.h" #include "SystemData.h" #include "Window.h" +#include "LocaleES.h" // buffer values for scrolling velocity (left, stopped, right) const int logoBuffersLeft[] = { -5, -2, -1 }; @@ -255,11 +256,14 @@ void SystemView::onCursorChanged(const CursorState& /*state*/) // also change the text after we've fully faded out setAnimation(infoFadeOut, 0, [this, gameCount] { std::stringstream ss; + char strbuf[256]; if (!getSelected()->isGameSystem()) ss << "CONFIGURATION"; - else - ss << gameCount << " GAMES AVAILABLE"; + else { + snprintf(strbuf, 256, ngettext("%i GAME AVAILABLE", "%i GAMES AVAILABLE", gameCount), gameCount); + ss << strbuf; + } mSystemInfo.setText(ss.str()); }, false, 1); diff --git a/es-core/CMakeLists.txt b/es-core/CMakeLists.txt index 9e4302f1e3..5f37b9178b 100644 --- a/es-core/CMakeLists.txt +++ b/es-core/CMakeLists.txt @@ -12,6 +12,7 @@ set(CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Log.h ${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/LocaleES.h ${CMAKE_CURRENT_SOURCE_DIR}/src/platform.h ${CMAKE_CURRENT_SOURCE_DIR}/src/PowerSaver.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer.h @@ -88,6 +89,7 @@ set(CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Log.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/LocaleES.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/platform.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/PowerSaver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer_draw_gl.cpp diff --git a/es-core/src/LocaleES.cpp b/es-core/src/LocaleES.cpp new file mode 100644 index 0000000000..e168cdeed9 --- /dev/null +++ b/es-core/src/LocaleES.cpp @@ -0,0 +1,10 @@ +#include "LocaleES.h" + +#ifndef HAVE_GETTEXT +char* ngettext(char* msgid, char* msgid_plural, unsigned long int n) { + if(n > 1) { + return msgid_plural; + } + return msgid; +} +#endif diff --git a/es-core/src/LocaleES.h b/es-core/src/LocaleES.h new file mode 100644 index 0000000000..8ba6aeb554 --- /dev/null +++ b/es-core/src/LocaleES.h @@ -0,0 +1,12 @@ +#ifndef _LOCALE_H_ +#define _LOCALE_H_ + +#ifdef HAVE_GETTEXT + #include + #define _(A) gettext(A) +#else + #define _(A) A + char* ngettext(char* msgid, char* msgid_plural, unsigned long int n); +#endif + +#endif diff --git a/locale/CMakeLists.txt b/locale/CMakeLists.txt new file mode 100644 index 0000000000..0b29813591 --- /dev/null +++ b/locale/CMakeLists.txt @@ -0,0 +1,17 @@ +add_custom_target (i18n ALL COMMENT "Building i18n messages.") +file (GLOB es_PO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/lang/*) +set(es_POT ${CMAKE_CURRENT_SOURCE_DIR}/emulationstation.pot) +# update the pot +MESSAGE("Building the pot file") +add_custom_command (TARGET i18n COMMAND find "${CMAKE_SOURCE_DIR}/es-app" "${CMAKE_SOURCE_DIR}/es-core" -name "*.cpp" -o -name "*.h" | ${XGETTEXT_EXECUTABLE} -f - -o ${es_POT} --no-location --keyword=_) + +foreach (es_PO_INPUT ${es_PO_FILES}) + get_filename_component (es_PO_LANG ${es_PO_INPUT} NAME_WE) + MESSAGE("LANG = ${es_PO_LANG}") + set (es_MO_OUTPUT ${es_PO_INPUT}/LC_MESSAGES/emulationstation.mo) + # update the po from the pot + add_custom_command (TARGET i18n COMMAND basename ${es_PO_INPUT} && ${MSGMERGE_EXECUTABLE} -U --no-fuzzy-matching ${es_PO_INPUT}/LC_MESSAGES/emulationstation.po ${es_POT}) + # compile the po to mo + add_custom_command (TARGET i18n COMMAND ${MSGFMT_EXECUTABLE} -o ${es_MO_OUTPUT} ${es_PO_INPUT}/LC_MESSAGES/emulationstation.po --statistics) + install (FILES ${es_MO_OUTPUT} DESTINATION share/locale/${es_PO_LANG}/LC_MESSAGES RENAME emulationstation.mo) +endforeach (es_PO_INPUT ${es_PO_FILES}) diff --git a/locale/checkLocale.sh b/locale/checkLocale.sh new file mode 100755 index 0000000000..513ef40e97 --- /dev/null +++ b/locale/checkLocale.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +(cd lang && + for POLANG in * + do + POFILE="./${POLANG}/LC_MESSAGES/emulationstation.po" + echo -n "${POLANG}: " + LANG=C msgfmt "${POFILE}" -o - --statistics > /dev/null + done + ) diff --git a/locale/emulationstation.pot b/locale/emulationstation.pot new file mode 100644 index 0000000000..5951478b65 --- /dev/null +++ b/locale/emulationstation.pot @@ -0,0 +1,37 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-19 10:06+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#, c-format +msgid "%i GAME AVAILABLE" +msgid_plural "%i GAMES AVAILABLE" +msgstr[0] "" +msgstr[1] "" + +msgid "Loading..." +msgstr "" + +msgid "Loading system config..." +msgstr "" + +msgid "QUIT" +msgstr "" + +msgid "Done." +msgstr "" diff --git a/locale/lang/fr/LC_MESSAGES/emulationstation.po b/locale/lang/fr/LC_MESSAGES/emulationstation.po new file mode 100644 index 0000000000..74d2a24820 --- /dev/null +++ b/locale/lang/fr/LC_MESSAGES/emulationstation.po @@ -0,0 +1,29 @@ +msgid "" +msgstr "" +"Project-Id-Version: emulationstation\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-05-12 22:25+0200\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: POEditor.com\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#, c-format +msgid "%i GAME AVAILABLE" +msgid_plural "%i GAMES AVAILABLE" +msgstr[0] "%i JEU DISPONIBLE" +msgstr[1] "%i JEUX DISPONIBLES" + +msgid "Loading..." +msgstr "Chargement..." + +msgid "Loading system config..." +msgstr "Chargement de la configuration système" + +msgid "QUIT" +msgstr "QUITTER" + +msgid "Done." +msgstr "Terminé." From 8d1af406a3ab69fc40f2f89053f6731ccd650a4d Mon Sep 17 00:00:00 2001 From: Nicolas Adenis-Lamarre Date: Fri, 19 Jul 2019 21:52:39 +0200 Subject: [PATCH 2/2] fix gettext english plural when gettext is not used Signed-off-by: Nicolas Adenis-Lamarre --- es-core/src/LocaleES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/es-core/src/LocaleES.cpp b/es-core/src/LocaleES.cpp index e168cdeed9..08110e9861 100644 --- a/es-core/src/LocaleES.cpp +++ b/es-core/src/LocaleES.cpp @@ -2,7 +2,7 @@ #ifndef HAVE_GETTEXT char* ngettext(char* msgid, char* msgid_plural, unsigned long int n) { - if(n > 1) { + if(n != 1) { return msgid_plural; } return msgid;