Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7287 was 7284, checked in by landauf, 14 years ago

merged consolecommands3 branch back to trunk.

note: the console command interface has changed completely, but the documentation is not yet up to date. just copy an existing command and change it to your needs, it's pretty self-explanatory. also the include files related to console commands are now located in core/command/. in the game it should work exactly like before, except for some changes in the auto-completion.

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