ca731b9ac7980d859eeab373563dd19d5444537d
[supertux.git] / src / tinygettext / tinygettext.hpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.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 #ifndef HEADER_TINYGETTEXT_H
21 #define HEADER_TINYGETTEXT_H
22
23 #include <map>
24 #include <vector>
25 #include <set>
26 #include <string>
27
28 namespace TinyGetText {
29
30 typedef int (*PluralFunc)(int n);
31
32 struct LanguageDef {
33   const char* code;
34   const char* name;
35   int         nplural;
36   PluralFunc  plural;
37
38   LanguageDef(const char* code_, const char* name_,  int nplural_, PluralFunc plural_)
39     : code(code_), name(name_), nplural(nplural_), plural(plural_)
40   {}
41 };
42
43 /** A simple dictionary class that mimics gettext() behaviour. Each
44     Dictionary only works for a single language, for managing multiple
45     languages and .po files at once use the DictionaryManager. */
46 class Dictionary
47 {
48 private:
49   typedef std::map<std::string, std::string> Entries;
50   Entries entries;
51
52   typedef std::map<std::string, std::map<int, std::string> > PluralEntries;
53   PluralEntries plural_entries;
54
55   LanguageDef language;
56   std::string charset;
57 public:
58   /** */
59   Dictionary(const LanguageDef& language_, const std::string& charset = "");
60
61   Dictionary();
62
63   /** Return the charset used for this dictionary */
64   std::string get_charset() const;
65
66   /** Set a charset for this dictionary, this will NOT convert stuff,
67       it is for information only, you have to convert stuff yourself
68       when you add it with \a add_translation() */
69   void set_charset(const std::string& charset);
70
71   /** Set the language that is used for this dictionary, this is
72       mainly needed to evaluate plural forms */
73   void set_language(const LanguageDef& lang);
74
75   /** Translate the string \a msgid to its correct plural form, based
76       on the number of items given by \a num. \a msgid2 is \a msgid in
77       plural form. */
78   std::string translate(const std::string& msgid, const std::string& msgid2, int num);
79
80   /** Translate the string \a msgid. */
81   std::string translate(const std::string& msgid);
82   /** Translate the string \a msgid. */
83   const char* translate(const char* msgid);
84     
85   /** Add a translation from \a msgid to \a msgstr to the dictionary,
86       where \a msgid is the singular form of the message, msgid2 the
87       plural form and msgstrs a table of translations. The right
88       translation will be calculated based on the \a num argument to
89       translate(). */
90   void add_translation(const std::string& msgid, const std::string& msgid2,
91                        const std::map<int, std::string>& msgstrs);
92
93   /** Add a translation from \a msgid to \a msgstr to the
94       dictionary */
95   void add_translation(const std::string& msgid, const std::string& msgstr);
96 };
97
98 /** Manager class for dictionaries, you give it a bunch of directories
99     with .po files and it will then automatically load the right file
100     on demand depending on which language was set. */
101 class DictionaryManager
102 {
103 private:
104   typedef std::map<std::string, Dictionary> Dictionaries;
105   Dictionaries dictionaries;
106   typedef std::vector<std::string> SearchPath;
107   SearchPath search_path;
108   typedef std::map<std::string, std::string> Aliases;
109   Aliases language_aliases;
110   std::string charset;
111   std::string language;
112   Dictionary* current_dict;
113   Dictionary empty_dict;
114
115 public:
116   DictionaryManager();
117
118   /** Return the currently active dictionary, if none is set, an empty
119       dictionary is returned. */
120   Dictionary& get_dictionary()
121   { return *current_dict; }
122
123   /** Get dictionary for lang */
124   Dictionary& get_dictionary(const std::string& langspec);
125
126   /** Set a language based on a four? letter country code */
127   void set_language(const std::string& langspec);
128
129   /** returns the (normalized) country code of the currently used language */
130   const std::string& get_language() const;
131
132   /** Set a charset that will be set on the returned dictionaries */
133   void set_charset(const std::string& charset);
134
135   /** Define an alias for a language */
136   void set_language_alias(const std::string& alias, const std::string& lang);
137
138   /** Add a directory to the search path for dictionaries */
139   void add_directory(const std::string& pathname);
140   
141   /** Return a set of the available languages in their country code */
142   std::set<std::string> get_languages();
143
144 private:
145   void parseLocaleAliases();
146   /// returns the language part in a language spec (like de_DE.UTF-8 -> de)
147   std::string get_language_from_spec(const std::string& spec);
148 };
149
150 /** Read the content of the .po file given as \a in into the
151     dictionary given as \a dict */
152 void read_po_file(Dictionary& dict, std::istream& in);
153 LanguageDef& get_language_def(const std::string& name);
154
155 } // namespace TinyGetText
156
157 #endif
158
159 /* EOF */