1 //
2 //  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See
5 //  accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #ifndef BOOST_LOCLAE_GNU_GETTEXT_HPP
9 #define BOOST_LOCLAE_GNU_GETTEXT_HPP
10 
11 #include <boost/locale/message.hpp>
12 #include <boost/function.hpp>
13 #include <stdexcept>
14 
15 namespace boost {
16 namespace locale {
17 /// \addtogroup message
18 /// @{
19 
20 
21 ///
22 /// \brief This namespace holds classes that provide GNU Gettext message catalogs support.
23 ///
24 namespace gnu_gettext {
25 
26     ///
27     /// \brief This structure holds all information required for creating gnu-gettext message catalogs,
28     ///
29     /// The user is expected to set its parameters to load these catalogs correctly. This structure
30     /// also allows providing functions for charset conversion. Note, you need to provide them,
31     /// so this structure is not useful for wide characters without subclassing and it will also
32     /// ignore gettext catalogs that use a charset different from \a encoding.
33     ///
34     struct messages_info {
messages_infoboost::locale::gnu_gettext::messages_info35         messages_info() :
36             language("C"),
37             locale_category("LC_MESSAGES")
38         {
39         }
40 
41         std::string language;   ///< The language we load the catalog for, like "ru", "en", "de"
42         std::string country;    ///< The country we load the catalog for, like "US", "IL"
43         std::string variant;    ///< Language variant, like "euro" so it would look for catalog like de_DE\@euro
44         std::string encoding;   ///< Required target charset encoding. Ignored for wide characters.
45                                 ///< For narrow, should specify the correct encoding required for this catalog
46         std::string locale_category; ///< Locale category, is set by default to LC_MESSAGES, but may be changed
47         ///
48         /// \brief This type represents GNU Gettext domain name for the messages.
49         ///
50         /// It consists of two parameters:
51         ///
52         /// - name - the name of the domain - used for opening the file name
53         /// - encoding - the encoding of the keys in the sources, default - UTF-8
54         ///
55         struct domain {
56 
57             std::string name; ///< The name of the domain
58             std::string encoding;   ///< The character encoding for the domain
domainboost::locale::gnu_gettext::messages_info::domain59             domain() {}
60             ///
61             /// Create a domain object from the name that can hold an encoding after symbol "/"
62             /// such that if n is "hello/cp1255" then the name would be "hello" and "encoding" would
63             /// be "cp1255" and if n is "hello" then the name would be the same but encoding would be
64             /// "UTF-8"
65             ///
domainboost::locale::gnu_gettext::messages_info::domain66             domain(std::string const &n)
67             {
68                 size_t pos = n.find("/");
69                 if(pos==std::string::npos) {
70                     name = n;
71                     encoding = "UTF-8";
72                 }
73                 else {
74                     name = n.substr(0,pos);
75                     encoding = n.substr(pos+1);
76                 }
77 
78             }
79 
80             ///
81             /// Check whether two objects are equivalent, only names are compared, encoding is ignored
82             ///
operator ==boost::locale::gnu_gettext::messages_info::domain83             bool operator==(domain const &other) const
84             {
85                 return name==other.name;
86             }
87             ///
88             /// Check whether two objects are distinct, only names are compared, encoding is ignored
89             ///
operator !=boost::locale::gnu_gettext::messages_info::domain90             bool operator!=(domain const &other) const
91             {
92                 return !(*this==other);
93             }
94 
95         };
96 
97         typedef std::vector<domain> domains_type;   ///< Type that defines a list of domains that are loaded
98                                                     ///< The first one is the default one
99         domains_type domains;           ///< Message domains - application name, like my_app. So files named my_app.mo
100                                         ///< would be loaded
101         std::vector<std::string> paths; ///< Paths to search files in. Under MS Windows it uses encoding
102                                         ///< parameter to convert them to wide OS specific paths.
103 
104         ///
105         /// The callback for custom file system support. This callback should read the file named \a file_name
106         /// encoded in \a encoding character set into std::vector<char> and return it.
107         ///
108         /// - If the file does not exist, it should return an empty vector.
109         /// - If a error occurs during file read it should throw a error.
110         ///
111         /// \note The user should support only the encodings the locales are created for. So if the user
112         /// uses only one encoding or the file system is encoding agnostic, he may ignore the \a encoding parameter.
113         ///
114         typedef function<
115                     std::vector<char>(
116                         std::string const &file_name,
117                         std::string const &encoding
118                     )
119                 > callback_type;
120 
121         ///
122         /// The callback for handling custom file systems, if it is empty, the real OS file-system
123         /// is being used.
124         ///
125         callback_type callback;
126 
127     };
128 
129     ///
130     /// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get
131     /// information about where to read them from and uses it for character set conversion (if needed)
132     ///
133 
134     template<typename CharType>
135     message_format<CharType> *create_messages_facet(messages_info const &info);
136 
137     /// \cond INTERNAL
138 
139     template<>
140     BOOST_LOCALE_DECL message_format<char> *create_messages_facet(messages_info const &info);
141 
142     template<>
143     BOOST_LOCALE_DECL message_format<wchar_t> *create_messages_facet(messages_info const &info);
144 
145     #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
146     template<>
147     BOOST_LOCALE_DECL message_format<char16_t> *create_messages_facet(messages_info const &info);
148     #endif
149 
150     #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
151     template<>
152     BOOST_LOCALE_DECL message_format<char32_t> *create_messages_facet(messages_info const &info);
153     #endif
154 
155     /// \endcond
156 
157 } // gnu_gettext
158 
159 /// @}
160 
161 } // locale
162 } // boost
163 
164 #endif
165 
166 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
167 
168