~ubuntu-branches/ubuntu/precise/pingus/precise

« back to all changes in this revision

Viewing changes to src/tinygettext/dictionary_manager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-02-28 19:44:25 UTC
  • mfrom: (4.1.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20080228194425-e8ilohlijv02kgcf
Tags: 0.7.2-2
* Fix FTBFS with gcc-4.3 by adding the missing include in
  src/input/evdev_device.cpp (Closes: #462238):
   + debian/patches/20_fix_FTBFS_with_gcc-4.3.
* Rename former patch so that the filename reflects the order in which
  the patches are applied:
   - debian/patches/data_dir.patch
   + debian/patches/10_fix_data_directory.
* Bump Standards-Version from 3.7.2 to 3.7.3, no changes needed.
* Add a dh_desktop call in the arch-dep part of debian/rules.
* Adjust the “missing-dep-for-interpreter guile” override since lintian
  now lists an alternative for that dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  $Id: dictionary_manager.cpp 3353 2007-10-28 08:05:10Z grumbel $
 
2
// 
 
3
//  TinyGetText - A small flexible gettext() replacement
 
4
//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
 
5
//
 
6
//  This program is free software; you can redistribute it and/or
 
7
//  modify it under the terms of the GNU General Public License
 
8
//  as published by the Free Software Foundation; either version 2
 
9
//  of the License, or (at your option) any later version.
 
10
//
 
11
//  This program is distributed in the hope that it will be useful,
 
12
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
//  GNU General Public License for more details.
 
15
// 
 
16
//  You should have received a copy of the GNU General Public License
 
17
//  along with this program; if not, write to the Free Software
 
18
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
19
 
 
20
#include <iostream>
 
21
#include <stdlib.h>
 
22
#include <sys/types.h>
 
23
#ifndef WIN32
 
24
#  include <dirent.h>
 
25
#else
 
26
# include "../win32/uce_dirent.h"
 
27
#endif
 
28
 
 
29
#include <fstream>
 
30
#include "dictionary_manager.hpp"
 
31
#include "po_file_reader.hpp"
 
32
 
 
33
namespace TinyGetText {
 
34
 
 
35
static bool has_suffix(const std::string& lhs, const std::string rhs)
 
36
{
 
37
  if (lhs.length() < rhs.length())
 
38
    return false;
 
39
  else
 
40
    return lhs.compare(lhs.length() - rhs.length(), rhs.length(), rhs) == 0;
 
41
}
 
42
 
 
43
DictionaryManager::DictionaryManager()
 
44
  : empty_dict(&lang_en, "ISO-8859-1"),
 
45
    language(&lang_en),
 
46
    current_dict(&empty_dict)    
 
47
{
 
48
#ifndef WIN32
 
49
  parseLocaleAliases();
 
50
#endif
 
51
 
 
52
  // setup language from environment vars
 
53
  const char* lang = getenv("LC_ALL");
 
54
  if (!lang)
 
55
    lang = getenv("LC_MESSAGES");
 
56
  if (!lang)
 
57
    lang = getenv("LANG");
 
58
  
 
59
  if (lang)
 
60
    set_current_dictionary(lang);
 
61
}
 
62
 
 
63
void
 
64
DictionaryManager::parseLocaleAliases()
 
65
{
 
66
  // try to parse language alias list
 
67
  std::ifstream in("/usr/share/locale/locale.alias");
 
68
  
 
69
  char c = ' ';
 
70
  while(in.good() && !in.eof()) {
 
71
    while(isspace(c) && !in.eof())
 
72
      in.get(c);
 
73
    
 
74
    if(c == '#') { // skip comments
 
75
      while(c != '\n' && !in.eof())
 
76
        in.get(c);
 
77
      continue;
 
78
    }
 
79
    
 
80
    std::string alias;
 
81
    while(!isspace(c) && !in.eof()) {
 
82
      alias += c;
 
83
      in.get(c);
 
84
    }
 
85
    while(isspace(c) && !in.eof())
 
86
      in.get(c);
 
87
    std::string lang;
 
88
    while(!isspace(c) && !in.eof()) {
 
89
      lang += c;
 
90
      in.get(c);
 
91
    }
 
92
 
 
93
    if(in.eof())
 
94
      break;
 
95
    
 
96
    set_language_alias(alias, lang);
 
97
  }
 
98
}
 
99
  
 
100
Dictionary&
 
101
DictionaryManager::get_dictionary(LanguageDef* lang)
 
102
{
 
103
  Dictionaries::iterator i = dictionaries.find(lang);
 
104
  if (i != dictionaries.end())
 
105
    {
 
106
      return i->second;
 
107
    }
 
108
  else // Dictionary for languages lang isn't loaded, so we load it
 
109
    {
 
110
      Dictionary& dict = dictionaries[lang];
 
111
 
 
112
      dict.set_language(lang);
 
113
 
 
114
      for(SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
 
115
        {
 
116
          DIR* dir = opendir(p->c_str());
 
117
          if (!dir)
 
118
            {
 
119
              std::cerr << "TinyGetText: Error: opendir() failed on " << *p << std::endl;
 
120
            }
 
121
          else
 
122
            {
 
123
              struct dirent* ent;
 
124
              while((ent = readdir(dir)))
 
125
                {
 
126
                  if (std::string(ent->d_name) == std::string(lang->code) + ".po")
 
127
                    {
 
128
                      std::string pofile = *p + "/" + ent->d_name;
 
129
                      std::ifstream in(pofile.c_str());
 
130
                      if (!in)
 
131
                        {
 
132
                          std::cerr << "Error: Failure file opening: " << pofile << std::endl;
 
133
                        }
 
134
                      else
 
135
                        {
 
136
                          POFileReader reader(in, dict);
 
137
                        }
 
138
                    }
 
139
                }
 
140
              closedir(dir);
 
141
            }
 
142
        }
 
143
 
 
144
      return dict;
 
145
    }
 
146
}
 
147
 
 
148
std::set<std::string>
 
149
DictionaryManager::get_languages()
 
150
{
 
151
  std::set<std::string> languages;
 
152
 
 
153
  for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
 
154
    {
 
155
      DIR* dir = opendir(p->c_str());
 
156
      if (!dir)
 
157
        {
 
158
          std::cerr << "Error: opendir() failed on " << *p << std::endl;
 
159
        }
 
160
      else
 
161
        {
 
162
          struct dirent* ent;
 
163
          while((ent = readdir(dir)))
 
164
            {
 
165
              if (has_suffix(ent->d_name, ".po"))
 
166
                {
 
167
                  std::string filename = ent->d_name;
 
168
                  languages.insert(filename.substr(0, filename.length()-3));
 
169
                }
 
170
            }
 
171
          closedir(dir);
 
172
        }
 
173
    }  
 
174
  return languages;
 
175
}
 
176
 
 
177
void
 
178
DictionaryManager::set_current_dictionary(const std::string& lang)
 
179
{
 
180
  LanguageDef* new_lang = get_canonical_language(lang);
 
181
  if (!new_lang)
 
182
    {
 
183
      std::cout << "Error: DictionaryManager: Couldn't find LanguageDef for '" << lang
 
184
                << "', leaving current dictionary unchanged" << std::endl;
 
185
    }
 
186
  else
 
187
    {
 
188
      language = new_lang;
 
189
      // std::cout << "Language: supplied: '" << lang << "' -> canonical: '" << language->code << "'" << std::endl;
 
190
      current_dict = &(get_dictionary(language));
 
191
    }
 
192
}
 
193
 
 
194
void
 
195
DictionaryManager::set_language_alias(const std::string& alias,
 
196
    const std::string& language)
 
197
{
 
198
  language_aliases.insert(std::make_pair(alias, language));
 
199
}
 
200
 
 
201
LanguageDef*
 
202
DictionaryManager::get_canonical_language(const std::string& spec)
 
203
{
 
204
  std::string lang_code = spec;
 
205
 
 
206
  // Check for language aliases
 
207
  Aliases::iterator i = language_aliases.find(spec);
 
208
  if(i != language_aliases.end()) 
 
209
    lang_code = i->second;
 
210
 
 
211
  // Cut away any specification of the codeset (i.e. de_DE.ISO-8859-1)
 
212
  std::string::size_type s = lang_code.find_first_of(".");
 
213
 
 
214
  if (s != std::string::npos)
 
215
    lang_code = std::string(spec, 0, s);
 
216
 
 
217
  LanguageDef* lang_def = get_language_def(lang_code);
 
218
  if (lang_def)
 
219
    return lang_def;
 
220
  else if (lang_code.length() == 5) // 'en_EN' failed, try 'en'
 
221
    return get_language_def(lang_code.substr(0, 2));
 
222
  else 
 
223
    return 0;
 
224
}
 
225
 
 
226
void
 
227
DictionaryManager::add_directory(const std::string& pathname)
 
228
{
 
229
  dictionaries.clear(); // adding directories invalidates cache
 
230
  search_path.push_back(pathname);
 
231
  current_dict = &(get_dictionary(language));
 
232
}
 
233
 
 
234
} // namespace TinyGetText
 
235
 
 
236
/* EOF */