Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/Language.cc @ 3339

Last change on this file since 3339 was 3280, checked in by rgrieder, 15 years ago

Merged most of the core4 revisions back to the trunk except for:

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