1 // tinygettext - A gettext replacement that works directly on .po files
2 // Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #include "dictionary_manager.hpp"
27 #include "log_stream.hpp"
28 #include "po_parser.hpp"
29 #include "unix_file_system.hpp"
31 namespace tinygettext {
33 static bool has_suffix(const std::string& lhs, const std::string rhs)
35 if (lhs.length() < rhs.length())
38 return lhs.compare(lhs.length() - rhs.length(), rhs.length(), rhs) == 0;
41 DictionaryManager::DictionaryManager(const std::string& charset_) :
49 filesystem(new UnixFileSystem)
53 DictionaryManager::~DictionaryManager()
55 for(Dictionaries::iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
62 DictionaryManager::clear_cache()
64 for(Dictionaries::iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
74 DictionaryManager::get_dictionary()
84 current_dict = &get_dictionary(current_language);
95 DictionaryManager::get_dictionary(const Language& language)
97 //log_debug << "Dictionary for language \"" << spec << "\" requested" << std::endl;
98 //log_debug << "...normalized as \"" << lang << "\"" << std::endl;
101 Dictionaries::iterator i = dictionaries.find(language);
102 if (i != dictionaries.end())
106 else // Dictionary for languages lang isn't loaded, so we load it
108 //log_debug << "get_dictionary: " << lang << std::endl;
109 Dictionary* dict = new Dictionary(charset);
111 dictionaries[language] = dict;
113 for (SearchPath::reverse_iterator p = search_path.rbegin(); p != search_path.rend(); ++p)
115 std::vector<std::string> files = filesystem->open_directory(*p);
117 std::string best_filename;
120 for(std::vector<std::string>::iterator filename = files.begin(); filename != files.end(); filename++)
122 // check if filename matches requested language
123 if (has_suffix(*filename, ".po"))
124 { // ignore anything that isn't a .po file
125 Language po_language = Language::from_env(filename->substr(0, filename->size()-3));
129 log_warning << *filename << ": warning: ignoring, unknown language" << std::endl;
133 int score = Language::match(language, po_language);
135 if (score > best_score)
138 best_filename = *filename;
144 if (!best_filename.empty())
146 std::string pofile = *p + "/" + best_filename;
149 std::auto_ptr<std::istream> in = filesystem->open_file(pofile);
152 log_error << "error: failure opening: " << pofile << std::endl;
156 POParser::parse(pofile, *in, *dict);
159 catch(std::exception& e)
161 log_error << "error: failure parsing: " << pofile << std::endl;
162 log_error << e.what() << "" << std::endl;
172 DictionaryManager::get_languages()
174 std::set<Language> languages;
176 for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
178 std::vector<std::string> files = filesystem->open_directory(*p);
180 for(std::vector<std::string>::iterator file = files.begin(); file != files.end(); ++file)
182 if (has_suffix(*file, ".po"))
184 languages.insert(Language::from_env(file->substr(0, file->size()-3)));
192 DictionaryManager::set_language(const Language& language)
194 if (current_language != language)
196 current_language = language;
202 DictionaryManager::get_language() const
204 return current_language;
208 DictionaryManager::set_charset(const std::string& charset_)
210 clear_cache(); // changing charset invalidates cache
215 DictionaryManager::set_use_fuzzy(bool t)
222 DictionaryManager::get_use_fuzzy() const
228 DictionaryManager::add_directory(const std::string& pathname)
230 clear_cache(); // adding directories invalidates cache
231 search_path.push_back(pathname);
235 DictionaryManager::set_filesystem(std::auto_ptr<FileSystem> filesystem_)
237 filesystem = filesystem_;
240 } // namespace tinygettext