Skip to content

Commit

Permalink
Merge pull request #74 from sharkwouter/add-translation-support
Browse files Browse the repository at this point in the history
Add translation support
  • Loading branch information
sharkwouter authored Jul 18, 2024
2 parents 7fae85c + 86b8ffa commit 156de15
Show file tree
Hide file tree
Showing 19 changed files with 378 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*.lo
*.o
*.obj
*.mo
*.pot
*.po~

# Precompiled Headers
*.gch
Expand Down
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,30 @@ include_directories(
${JSONCPP_INCLUDE_DIRS}
)

option(TRANSLATION_SUPPORT "Add support for loading translations, requires tinygettext" OFF)

# Create translations
if(TRANSLATION_SUPPORT)
pkg_search_module(TINYGETTEXT REQUIRED tinygettext)
if(BUILD_STATIC)
target_link_libraries(${PROJECT_NAME} PRIVATE ${TINYGETTEXT_STATIC_LIBRARIES})
else()
target_link_libraries(${PROJECT_NAME} PRIVATE ${TINYGETTEXT_LIBRARIES})
endif()

add_compile_definitions(TRANSLATION_SUPPORT=1)
endif()

# Set asset paths
set(ASSETS_FONTS "${CMAKE_SOURCE_DIR}/assets/fonts")
set(ASSETS_IMAGES "${CMAKE_SOURCE_DIR}/assets/images")
set(ASSETS_LEVELS "${CMAKE_SOURCE_DIR}/assets/levels")
set(ASSETS_SOUNDS "${CMAKE_SOURCE_DIR}/assets/sounds")
set(ASSETS_MUSIC "${CMAKE_SOURCE_DIR}/assets/music")
set(ASSETS_BACKGROUNDS "${CMAKE_SOURCE_DIR}/assets/backgrounds")
if(TRANSLATION_SUPPORT)
set(ASSETS_LANGUAGES "${CMAKE_SOURCE_DIR}/assets/languages")
endif()

if(PSP)
set(ASSETS_BACKGROUNDS "${CMAKE_CURRENT_SOURCE_DIR}/platform/psp/assets/backgrounds")
Expand Down Expand Up @@ -99,6 +116,11 @@ if(NOT VITA)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${ASSETS_SOUNDS} ${CMAKE_CURRENT_BINARY_DIR}/assets/sounds)
if(TRANSLATION_SUPPORT)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${ASSETS_LANGUAGES} ${CMAKE_CURRENT_BINARY_DIR}/assets/languages)
endif()
endif()

# Platform specific install
Expand Down
164 changes: 164 additions & 0 deletions assets/languages/nl.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# 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 <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-18 15:25+0200\n"
"PO-Revision-Date: 2024-07-18 11:07+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.4\n"

#: ../src/BoardManager.cpp:610
msgid " moves"
msgstr " acties"

#: ../src/states/WonState.cpp:7
msgid "Game Mode Completed!"
msgstr "Modus Afgerond!"

#: ../src/states/GameOverState.cpp:7
msgid "Game Over!"
msgstr "Game Over!"

#: ../src/states/GameStateChallenge.cpp:12 ../src/states/GameState.cpp:15
#: ../src/states/GameStateRelaxed.cpp:7
msgid "Game Paused"
msgstr "Spel gepauseerd"

#: ../src/states/HighscoreState.cpp:12
msgid "High Scores"
msgstr "Resultaten"

#: ../src/states/GameStateChallenge.cpp:14 ../src/states/GameState.cpp:17
msgid "Level Failed"
msgstr "Level Mislukt"

#: ../src/states/GameStateChallenge.cpp:13 ../src/states/GameState.cpp:16
msgid "Level Finished!"
msgstr "Level Afgerond!"

#: ../src/states/NotImplementedState.cpp:7
msgid "Not Yet Implemented"
msgstr "Nog Niet Geimplementeerd"

#: ../src/states/OptionsState.cpp:272
msgid "Options"
msgstr "opties"

#: ../src/states/MenuState.cpp:23
msgid "challenge mode"
msgstr "uitdagingsmodus"

#: ../src/states/OptionsState.cpp:172
msgid "change music upon level switch: "
msgstr "wissel muziek bij level overgang: "

#: ../src/states/MenuState.cpp:24
msgid "ends only when lives run out"
msgstr "eindigt alleen als je levens op zijn"

#: ../src/states/MenuState.cpp:37
msgid "exit"
msgstr "stoppen"

#: ../src/states/OptionsState.cpp:176
msgid "full screen: "
msgstr "volledig scherm"

#: ../src/states/MenuState.cpp:31
msgid "high scores"
msgstr "resultaten"

#: ../src/states/HighscoreState.cpp:17
msgid "highest level reached in challenge mode: "
msgstr "hoogste level bereikt in uitdagingsmodus: "

#: ../src/BoardManager.cpp:590
msgid "level "
msgstr "level "

#: ../src/states/GameStateChallenge.cpp:112
msgid "lives left"
msgstr "levens "

#: ../src/states/MenuState.cpp:28
msgid "match without consequences"
msgstr "match zonder consequenties"

#: ../src/states/HighscoreState.cpp:18
msgid "matches in relaxed mode: "
msgstr "matches in relaxmodus: "

#: ../src/states/OptionsState.cpp:162
msgid "music volume: "
msgstr "muziekvolume: "

#: ../src/states/HighscoreState.cpp:15 ../src/states/OptionsState.cpp:172
#: ../src/states/OptionsState.cpp:176
msgid "no"
msgstr "nee"

#: ../src/states/MenuState.cpp:34
msgid "options"
msgstr "opties"

#: ../src/states/MenuState.cpp:20
msgid "play pre-made levels"
msgstr "speel voorgeprogrammeerde levels"

#: ../src/states/HighscoreState.cpp:13
msgid "press confirm to go back"
msgstr "druk op bevestigen om terug te gaan"

#: ../src/states/GameStateChallenge.cpp:13 ../src/states/GameState.cpp:16
#: ../src/states/NotImplementedState.cpp:7
msgid "press the confirm button to continue"
msgstr "druk op bevestigen om verder te gaan"

#: ../src/states/GameOverState.cpp:7 ../src/states/GameStateChallenge.cpp:12
#: ../src/states/GameState.cpp:15 ../src/states/GameStateRelaxed.cpp:7
#: ../src/states/WonState.cpp:7
msgid "press the confirm button to exit"
msgstr "druk op bevestigen om te sluiten"

#: ../src/states/GameStateChallenge.cpp:14 ../src/states/GameState.cpp:17
msgid "press the confirm button to restart"
msgstr "druk op bevestigen om het opnieuw te proberen"

#: ../src/states/MenuState.cpp:27
msgid "relaxed mode"
msgstr "relaxmodus"

#: ../src/states/OptionsState.cpp:180
msgid "resolution: "
msgstr "resolutie: "

#: ../src/states/OptionsState.cpp:295
msgid "return to menu"
msgstr "terug naar menu"

#: ../src/states/OptionsState.cpp:152
msgid "sound volume: "
msgstr "volume geluiden: "

#: ../src/states/MenuState.cpp:19
msgid "standard mode"
msgstr "standardmodus"

#: ../src/states/HighscoreState.cpp:16
msgid "standard mode completed: "
msgstr "standardmodus afgesloten: "

#: ../src/states/HighscoreState.cpp:15 ../src/states/OptionsState.cpp:172
#: ../src/states/OptionsState.cpp:176
msgid "yes"
msgstr "ja"
13 changes: 13 additions & 0 deletions platform/add-translation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

cd "$(dirname "$0")"

if [ -z "${1}" ]; then
echo "Please select a language like: ${0} en_US"
fi

POTFILE="oceanpop.pot"

xgettext --from-code=UTF-8 --keyword=_ --sort-output --language=C++ ../src/*.cpp ../src/*.hpp ../src/states/*.cpp ../src/states/*.hpp -o ${POTFILE}

msginit --locale="${1}" --input=${POTFILE} -o "../assets/languages/${1}.po"
12 changes: 12 additions & 0 deletions platform/update-translation-files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

cd "$(dirname "$0")"

POTFILE="oceanpop.pot"

xgettext --from-code=UTF-8 --keyword=_ --sort-output --language=C++ ../src/*.cpp ../src/*.hpp ../src/states/*.cpp ../src/states/*.hpp -o ${POTFILE}

# Update each po file
for langfile in ../assets/languages/*.po; do
msgmerge -U "${langfile}" "${POTFILE}"
done
5 changes: 3 additions & 2 deletions src/BoardManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Sound.hpp"
#include "colors.hpp"
#include "FontType.hpp"
#include "utils.hpp"

BoardManager::BoardManager(SDL_Renderer *renderer, FontManager *fonts, SoundManager * sounds, OptionManager * options, int x, int y, int width, int height, int moves, int required_matches, int level, int seed) : fonts(fonts), sounds(sounds), options(options),
textures(renderer, options) {
Expand Down Expand Up @@ -586,7 +587,7 @@ void BoardManager::drawInfo(SDL_Renderer * renderer) {
// Generate texture with text
if (this->level_updated) {
std::string str_level = std::to_string(level);
str_level = "level " + str_level;
str_level = _("level ") + str_level;
if (text_level != NULL) {
SDL_DestroyTexture(text_level);
}
Expand All @@ -606,7 +607,7 @@ void BoardManager::drawInfo(SDL_Renderer * renderer) {
}
if (this->moves_updated) {
std::string str_moves = std::to_string(this->moves);
str_moves += " moves";
str_moves += _(" moves");
if (text_moves != NULL) {
SDL_DestroyTexture(text_moves);
}
Expand Down
77 changes: 77 additions & 0 deletions src/TranslationManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#ifdef TRANSLATION_SUPPORT

#include "TranslationManager.hpp"

#include <iostream>
#include <string.h>
#include <fstream>
#include <stdlib.h>
#include <iostream>

#include <tinygettext/po_parser.hpp>
#include <tinygettext/tinygettext.hpp>
#include <tinygettext/unix_file_system.hpp>

#include "utils.hpp"

TranslationManager::TranslationManager() : dictionary_manager(std::unique_ptr<tinygettext::FileSystem>(new tinygettext::UnixFileSystem)) {
loadTranslations();
}

TranslationManager::~TranslationManager() {

}

void TranslationManager::loadTranslations() {
std::string language_dir = getResourcePath("assets/languages/");
dictionary_manager.add_directory(language_dir);


for(std::string system_language : getSystemLanguageList()) {
tinygettext::Language language = tinygettext::Language::from_name(system_language);
if (language) {
for (tinygettext::Language l: dictionary_manager.get_languages()) {
if (l == language) {
dictionary_manager.set_language(language);
SDL_Log("Using language %s", language.get_language().c_str());
language_set = true;
return;
}
}
}
}
SDL_Log("Using default language English");;
}

std::vector<std::string> TranslationManager::getSystemLanguageList() {
std::vector<std::string> locales;

#include <locale.h>
char * locale_c_str = setlocale(LC_ALL, "");
if (locale_c_str != NULL){
std::string locale(locale_c_str);
if (strlen(locale_c_str) > 1) {
free(locale_c_str);
}

locales.push_back(locale);
if (locale.find(".") != std::string::npos) {
locales.push_back(locale.substr(0, locale.find(".")));
}
if (locale.find("_") != std::string::npos) {
locales.push_back(locale.substr(0, locale.find("_")));
}
}

return locales;
}

std::string TranslationManager::translate(std::string input) {
if (language_set) {
return dictionary_manager.get_dictionary().translate(input);
} else {
return input;
}
}

#endif // TRANSLATION_SUPPORT
25 changes: 25 additions & 0 deletions src/TranslationManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef TRANSLATIONMANAGER_H
#define TRANSLATIONMANAGER_H

#ifdef TRANSLATION_SUPPORT
#include <vector>

#include <tinygettext/tinygettext.hpp>

class TranslationManager {
private:
tinygettext::DictionaryManager dictionary_manager;
bool language_set = false;

std::vector<std::string> getSystemLanguageList();
void loadTranslations();

public:
TranslationManager();
~TranslationManager();

std::string translate(std::string input);
};
#endif

#endif // TRANSLATIONMANAGER_H
6 changes: 6 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@
#include "StateManager.hpp"
#include "EventManager.hpp"
#include "OptionManager.hpp"
#include "TranslationManager.hpp"
#include "utils.hpp"
#include "constants.hpp"
#include "states/MenuState.hpp"

#ifdef TRANSLATION_SUPPORT
// Create global TranslationManager object set in utils.h
TranslationManager translation_manager;
#endif

void run() {
OptionManager option_manager;
Window window("OceanPop", &option_manager);
Expand Down
Loading

0 comments on commit 156de15

Please sign in to comment.