Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2/src/libraries/core/Language.cc @ 6380

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

Removed CoreConfiguration and GameConfiguration workaround. I have found an easy solution that doesn't need this.
Config values for these classes can again be found under "Game" and "Core".

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