Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/libraries/core/Language.cc @ 5836

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

Extracted path related parts of Core into a new PathConfig class. This should decrease the mess in Core.cc a little bit.

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