Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/Language.cc @ 5967

Last change on this file since 5967 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

  • Property svn:eol-style set to native
File size: 11.6 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
[2171]30    @file
[1505]31    @brief Implementation of the Language and the LanguageEntry classes.
32*/
33
34#include "Language.h"
35
36#include <fstream>
[3196]37#include "util/Debug.h"
[1535]38#include "Core.h"
[5929]39#include "PathConfig.h"
[1505]40
41namespace orxonox
42{
43    // ###############################
44    // ###      LanguageEntry      ###
45    // ###############################
46    /**
47        @brief Constructor: Sets the default entry.
48        @param fallbackEntry The default entry
49    */
50    LanguageEntry::LanguageEntry(const std::string& fallbackEntry)
51    {
52        this->fallbackEntry_ = fallbackEntry;
53        this->localisedEntry_ = fallbackEntry; // Set the localisation to the fallback entry, for the case that no translation gets assigned
54        this->bLocalisationSet_ = false;
55    }
56
57    /**
58        @brief Sets the localisation of the entry.
59        @param localisation The localisation
60    */
61    void LanguageEntry::setLocalisation(const std::string& localisation)
62    {
63        // Check if the translation is more than just an empty string
64        if ((localisation != "") && (localisation.size() > 0))
65        {
66            this->localisedEntry_ = localisation;
67            this->bLocalisationSet_ = true;
68        }
69        else
70            this->localisedEntry_ = this->fallbackEntry_;
71    }
72
73    /**
74        @brief Sets the default entry.
75        @param fallbackEntry The default entry
76    */
77    void LanguageEntry::setDefault(const std::string& fallbackEntry)
78    {
79        // If the default entry changes and the translation wasn't set yet, use the new default entry as translation
80        if (!this->bLocalisationSet_)
81            this->localisedEntry_ = fallbackEntry;
82
83        this->fallbackEntry_ = fallbackEntry;
84    }
85
86    // ###############################
87    // ###        Language         ###
88    // ###############################
[2662]89
[3370]90    Language* Language::singletonPtr_s = 0;
[2662]91
[1505]92    /**
93        @brief Constructor: Reads the default language file and sets some values.
94    */
95    Language::Language()
96    {
97        this->defaultLanguage_ = "default";
98        this->defaultLocalisation_ = "ERROR: LANGUAGE ENTRY DOESN'T EXIST!";
99
100        // Read the default language file to create all known LanguageEntry objects
101        this->readDefaultLanguageFile();
102    }
103
104    /**
[1747]105        @brief Destructor: Deletes all language entries.
106    */
107    Language::~Language()
108    {
109        for (std::map<std::string, LanguageEntry*>::iterator it = this->languageEntries_.begin(); it != this->languageEntries_.end(); ++it)
110            delete (it->second);
[1505]111    }
112
113    /**
114        @brief Creates a new LanguageEntry with a given label and a given default entry.
115        @param label The label of the entry
116        @param entry The default entry
117        @return The created LanguageEntry object
118    */
119    LanguageEntry* Language::createEntry(const LanguageEntryLabel& label, const std::string& entry)
120    {
121        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
122
123        // Make sure we don't create a duplicate entry
124        if (it == this->languageEntries_.end())
125        {
126            LanguageEntry* newEntry = new LanguageEntry(entry);
127            newEntry->setLabel(label);
128            this->languageEntries_[label] = newEntry;
129            return newEntry;
130        }
131
[2103]132        COUT(2) << "Warning: Language entry " << label << " is duplicate in " << getFilename(this->defaultLanguage_) << "!" << std::endl;
[1505]133        return it->second;
134    }
135
136    /**
137        @brief Adds a new LanguageEntry, if it's not already existing.
138        @param label The label of the entry
139        @param entry The default entry
140    */
141    void Language::addEntry(const LanguageEntryLabel& label, const std::string& entry)
142    {
143        COUT(5) << "Language: Called addEntry with\n  label: " << label << "\n  entry: " <<  entry << std::endl;
144        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
145        if (it == this->languageEntries_.end())
146        {
147            // The entry isn't available yet, meaning it's new, so create it
148            this->createEntry(label, entry);
149        }
150        else if (it->second->getDefault().compare(entry) == 0)
151        {
152            // The entry is available and the default string is the same, so return because everything is fine
153            return;
154        }
155        else
156        {
157            // The defined default entry is not the same as in the default language file - change it to the new entry
158            it->second->setDefault(entry);
159        }
160
161        // Write the default language file because either a new entry was created or an existing entry has changed
162        this->writeDefaultLanguageFile();
163
164    }
165
166    /**
167        @brief Returns the localisation of a given entry.
168        @param label The label of the entry
169        @return The localisation
170    */
171    const std::string& Language::getLocalisation(const LanguageEntryLabel& label) const
172    {
173        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
174        if (it != this->languageEntries_.end())
175            return it->second->getLocalisation();
176        else
177        {
178            // Uh, oh, an undefined entry was requested: return the default string
179            COUT(2) << "Warning: Language entry \"" << label << "\" not found!" << std::endl;
180            return this->defaultLocalisation_;
181        }
182    }
183
184    /**
185        @brief Creates the name of the language file out of the languages name.
186        @param language The name of the language
187        @return The filename
188    */
[3280]189    std::string Language::getFilename(const std::string& language)
[1505]190    {
191        return std::string("translation_" + language + ".lang");
192    }
193
194    /**
195        @brief Reads the default language file and creates a LanguageEntry objects for every entry.
196    */
197    void Language::readDefaultLanguageFile()
198    {
199        COUT(4) << "Read default language file." << std::endl;
200
[5929]201        std::string filepath = PathConfig::getConfigPathString() + getFilename(this->defaultLanguage_);
[2710]202
[1505]203        // This creates the file if it's not existing
204        std::ofstream createFile;
[5929]205        createFile.open(filepath.c_str(), std::fstream::app);
[1505]206        createFile.close();
207
208        // Open the file
209        std::ifstream file;
[5929]210        file.open(filepath.c_str(), std::fstream::in);
[1505]211
212        if (!file.is_open())
213        {
214            COUT(1) << "An error occurred in Language.cc:" << std::endl;
[2103]215            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to read the default language entries!" << std::endl;
[1505]216            return;
217        }
218
219        // Iterate through the file and create the LanguageEntries
220        while (file.good() && !file.eof())
221        {
[3198]222            std::string lineString;
223            std::getline(file, lineString);
[1505]224
225            // Check if the line is empty
226            if ((lineString != "") && (lineString.size() > 0))
227            {
[2662]228                size_t pos = lineString.find('=');
[1505]229
230                // Check if the length is at least 3 and if there's an entry before and behind the =
231                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
232                    this->createEntry(lineString.substr(0, pos), lineString.substr(pos + 1));
233                else
234                {
[2103]235                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(this->defaultLanguage_) << std::endl;
[1505]236                }
237            }
238        }
239
240        file.close();
241    }
242
243    /**
244        @brief Reads the language file of the configured language and assigns the localisation to the corresponding LanguageEntry object.
245    */
246    void Language::readTranslatedLanguageFile()
247    {
[1535]248        COUT(4) << "Read translated language file (" << Core::getLanguage() << ")." << std::endl;
[1505]249
[5929]250        std::string filepath = PathConfig::getConfigPathString() + getFilename(Core::getLanguage());
[2710]251
[1505]252        // Open the file
253        std::ifstream file;
[5929]254        file.open(filepath.c_str(), std::fstream::in);
[1505]255
256        if (!file.is_open())
257        {
258            COUT(1) << "An error occurred in Language.cc:" << std::endl;
[2103]259            COUT(1) << "Error: Couldn't open file " << getFilename(Core::getLanguage()) << " to read the translated language entries!" << std::endl;
[1535]260            Core::resetLanguage();
[1505]261            COUT(3) << "Info: Reset language to " << this->defaultLanguage_ << "." << std::endl;
262            return;
263        }
264
265        // Iterate through the file and create the LanguageEntries
266        while (file.good() && !file.eof())
267        {
[3198]268            std::string lineString;
269            std::getline(file, lineString);
[1505]270
271            // Check if the line is empty
272            if ((lineString != "") && (lineString.size() > 0))
273            {
[2662]274                size_t pos = lineString.find('=');
[1505]275
276                // Check if the length is at least 3 and if there's an entry before and behind the =
277                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
278                {
279                    std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(lineString.substr(0, pos));
280
281                    // Check if the entry exists
282                    if (it != this->languageEntries_.end())
283                        it->second->setLocalisation(lineString.substr(pos + 1));
284                    else
285                        this->createEntry(lineString.substr(0, pos), this->defaultLocalisation_)->setLocalisation(lineString.substr(pos + 1));
286                }
287                else
288                {
[2103]289                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(Core::getLanguage()) << std::endl;
[1505]290                }
291            }
292        }
293
294        file.close();
295    }
296
297    /**
298        @brief Writes all default entries to the default language file.
299    */
300    void Language::writeDefaultLanguageFile() const
301    {
302        COUT(4) << "Language: Write default language file." << std::endl;
303
[5929]304        std::string filepath = PathConfig::getConfigPathString() + getFilename(this->defaultLanguage_);
[2710]305
[1505]306        // Open the file
307        std::ofstream file;
[5929]308        file.open(filepath.c_str(), std::fstream::out);
[1505]309
310        if (!file.is_open())
311        {
312            COUT(1) << "An error occurred in Language.cc:" << std::endl;
[2103]313            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to write the default language entries!" << std::endl;
[1505]314            return;
315        }
316
317        // Iterate through the list an write the lines into the file
318        for (std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.begin(); it != this->languageEntries_.end(); ++it)
319        {
320            file << (*it).second->getLabel() << "=" << (*it).second->getDefault() << std::endl;
321        }
322
323        file.close();
324    }
325}
Note: See TracBrowser for help on using the repository browser.