Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/Language.cc @ 7186

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

Moved ability to possess descriptions from Executor to ConsoleCommand, since no other executors use this feature. Also simplified this code a little by introducing a new shortcut in Language.h. XMLPort has to use a temporary solution for descriptions without Language support atm.

  • Property svn:eol-style set to native
File size: 11.7 KB
Line 
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/**
30    @file
31    @brief Implementation of the Language and the LanguageEntry classes.
32*/
33
34#include "Language.h"
35
36#include <fstream>
37#include "util/Debug.h"
38#include "util/StringUtils.h"
39#include "Core.h"
40#include "PathConfig.h"
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
65        if (!localisation.empty())
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    // ###############################
90
91    Language* Language::singletonPtr_s = 0;
92
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    /**
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);
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
133        COUT(2) << "Warning: Language entry " << label << " is duplicate in " << getFilename(this->defaultLanguage_) << '!' << std::endl;
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    */
172    const std::string& Language::getLocalisation(const LanguageEntryLabel& label, bool bError) const
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();
177        else if (bError)
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        }
183        else
184            return BLANKSTRING;
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    */
192    std::string Language::getFilename(const std::string& language)
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
204        const std::string& filepath = PathConfig::getConfigPathString() + getFilename(this->defaultLanguage_);
205
206        // This creates the file if it's not existing
207        std::ofstream createFile;
208        createFile.open(filepath.c_str(), std::fstream::app);
209        createFile.close();
210
211        // Open the file
212        std::ifstream file;
213        file.open(filepath.c_str(), std::fstream::in);
214
215        if (!file.is_open())
216        {
217            COUT(1) << "An error occurred in Language.cc:" << std::endl;
218            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to read the default language entries!" << std::endl;
219            return;
220        }
221
222        // Iterate through the file and create the LanguageEntries
223        while (file.good() && !file.eof())
224        {
225            std::string lineString;
226            std::getline(file, lineString);
227
228            // Check if the line is empty
229            if (!lineString.empty())
230            {
231                size_t pos = lineString.find('=');
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                {
238                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(this->defaultLanguage_) << std::endl;
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    {
251        COUT(4) << "Read translated language file (" << Core::getInstance().getLanguage() << ")." << std::endl;
252
253        const std::string& filepath = PathConfig::getConfigPathString() + getFilename(Core::getInstance().getLanguage());
254
255        // Open the file
256        std::ifstream file;
257        file.open(filepath.c_str(), std::fstream::in);
258
259        if (!file.is_open())
260        {
261            COUT(1) << "An error occurred in Language.cc:" << std::endl;
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;
265            return;
266        }
267
268        // Iterate through the file and create the LanguageEntries
269        while (file.good() && !file.eof())
270        {
271            std::string lineString;
272            std::getline(file, lineString);
273
274            // Check if the line is empty
275            if (!lineString.empty())
276            {
277                size_t pos = lineString.find('=');
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                {
292                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(Core::getInstance().getLanguage()) << std::endl;
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
307        const std::string& filepath = PathConfig::getConfigPathString() + getFilename(this->defaultLanguage_);
308
309        // Open the file
310        std::ofstream file;
311        file.open(filepath.c_str(), std::fstream::out);
312
313        if (!file.is_open())
314        {
315            COUT(1) << "An error occurred in Language.cc:" << std::endl;
316            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to write the default language entries!" << std::endl;
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        {
323            file << it->second->getLabel() << '=' << it->second->getDefault() << std::endl;
324        }
325
326        file.close();
327    }
328}
Note: See TracBrowser for help on using the repository browser.