Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2740 was 2710, checked in by rgrieder, 16 years ago

Merged buildsystem3 containing buildsystem2 containing Adi's buildsystem branch back to the trunk.
Please update the media directory if you were not using buildsystem3 before.

  • Property svn:eol-style set to native
File size: 11.9 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 <boost/filesystem.hpp>
38
39#include "Core.h"
40#include "util/Debug.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 != "") && (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    // ###############################
90
91    Language* Language::singletonRef_s = 0;
92
93    /**
94        @brief Constructor: Reads the default language file and sets some values.
95    */
96    Language::Language()
97    {
98        assert(singletonRef_s == 0);
99        singletonRef_s = this;
100
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    /**
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
116        assert(singletonRef_s);
117        singletonRef_s = 0;
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
139        COUT(2) << "Warning: Language entry " << label << " is duplicate in " << getFilename(this->defaultLanguage_) << "!" << std::endl;
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    */
196    const std::string Language::getFilename(const std::string& language)
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
208        boost::filesystem::path filepath(Core::getConfigPath() / getFilename(this->defaultLanguage_));
209
210        // This creates the file if it's not existing
211        std::ofstream createFile;
212        createFile.open(filepath.file_string().c_str(), std::fstream::app);
213        createFile.close();
214
215        // Open the file
216        std::ifstream file;
217        file.open(filepath.file_string().c_str(), std::fstream::in);
218
219        if (!file.is_open())
220        {
221            COUT(1) << "An error occurred in Language.cc:" << std::endl;
222            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to read the default language entries!" << std::endl;
223            return;
224        }
225
226        char line[1024];
227
228        // Iterate through the file and create the LanguageEntries
229        while (file.good() && !file.eof())
230        {
231            file.getline(line, 1024);
232            std::string lineString = std::string(line);
233
234            // Check if the line is empty
235            if ((lineString != "") && (lineString.size() > 0))
236            {
237                size_t pos = lineString.find('=');
238
239                // Check if the length is at least 3 and if there's an entry before and behind the =
240                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
241                    this->createEntry(lineString.substr(0, pos), lineString.substr(pos + 1));
242                else
243                {
244                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(this->defaultLanguage_) << std::endl;
245                }
246            }
247        }
248
249        file.close();
250    }
251
252    /**
253        @brief Reads the language file of the configured language and assigns the localisation to the corresponding LanguageEntry object.
254    */
255    void Language::readTranslatedLanguageFile()
256    {
257        COUT(4) << "Read translated language file (" << Core::getLanguage() << ")." << std::endl;
258
259        boost::filesystem::path filepath(Core::getConfigPath() / getFilename(Core::getLanguage()));
260
261        // Open the file
262        std::ifstream file;
263        file.open(filepath.file_string().c_str(), std::fstream::in);
264
265        if (!file.is_open())
266        {
267            COUT(1) << "An error occurred in Language.cc:" << std::endl;
268            COUT(1) << "Error: Couldn't open file " << getFilename(Core::getLanguage()) << " to read the translated language entries!" << std::endl;
269            Core::resetLanguage();
270            COUT(3) << "Info: Reset language to " << this->defaultLanguage_ << "." << std::endl;
271            return;
272        }
273
274        char line[1024];
275
276        // Iterate through the file and create the LanguageEntries
277        while (file.good() && !file.eof())
278        {
279            file.getline(line, 1024);
280            std::string lineString = std::string(line);
281
282            // Check if the line is empty
283            if ((lineString != "") && (lineString.size() > 0))
284            {
285                size_t pos = lineString.find('=');
286
287                // Check if the length is at least 3 and if there's an entry before and behind the =
288                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
289                {
290                    std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(lineString.substr(0, pos));
291
292                    // Check if the entry exists
293                    if (it != this->languageEntries_.end())
294                        it->second->setLocalisation(lineString.substr(pos + 1));
295                    else
296                        this->createEntry(lineString.substr(0, pos), this->defaultLocalisation_)->setLocalisation(lineString.substr(pos + 1));
297                }
298                else
299                {
300                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(Core::getLanguage()) << std::endl;
301                }
302            }
303        }
304
305        file.close();
306    }
307
308    /**
309        @brief Writes all default entries to the default language file.
310    */
311    void Language::writeDefaultLanguageFile() const
312    {
313        COUT(4) << "Language: Write default language file." << std::endl;
314
315        boost::filesystem::path filepath(Core::getConfigPath() / getFilename(this->defaultLanguage_));
316
317        // Open the file
318        std::ofstream file;
319        file.open(filepath.file_string().c_str(), std::fstream::out);
320
321        if (!file.is_open())
322        {
323            COUT(1) << "An error occurred in Language.cc:" << std::endl;
324            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to write the default language entries!" << std::endl;
325            return;
326        }
327
328        // Iterate through the list an write the lines into the file
329        for (std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.begin(); it != this->languageEntries_.end(); ++it)
330        {
331            file << (*it).second->getLabel() << "=" << (*it).second->getDefault() << std::endl;
332        }
333
334        file.close();
335    }
336}
Note: See TracBrowser for help on using the repository browser.