Line data Source code
1 : // tinygettext - A gettext replacement that works directly on .po files
2 : // Copyright (c) 2006 Ingo Ruhnke <grumbel@gmail.com>
3 : //
4 : // This software is provided 'as-is', without any express or implied
5 : // warranty. In no event will the authors be held liable for any damages
6 : // arising from the use of this software.
7 : //
8 : // Permission is granted to anyone to use this software for any purpose,
9 : // including commercial applications, and to alter it and redistribute it
10 : // freely, subject to the following restrictions:
11 : //
12 : // 1. The origin of this software must not be misrepresented; you must not
13 : // claim that you wrote the original software. If you use this software
14 : // in a product, an acknowledgement in the product documentation would be
15 : // appreciated but is not required.
16 : // 2. Altered source versions must be plainly marked as such, and must not be
17 : // misrepresented as being the original software.
18 : // 3. This notice may not be removed or altered from any source distribution.
19 :
20 : #include "precompiled.h"
21 :
22 : #include <assert.h>
23 :
24 : #include "tinygettext/log_stream.hpp"
25 : #include "tinygettext/dictionary.hpp"
26 :
27 : namespace tinygettext {
28 :
29 : namespace {
30 :
31 0 : std::ostream& operator<<(std::ostream& o, const std::vector<std::string>& v)
32 : {
33 0 : for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it)
34 : {
35 0 : if (it != v.begin())
36 0 : o << ", ";
37 0 : o << "'" << *it << "'";
38 : }
39 0 : return o;
40 : }
41 :
42 : } // namespace
43 :
44 0 : Dictionary::Dictionary(const std::string& charset_) :
45 : entries(),
46 : ctxt_entries(),
47 : charset(charset_),
48 : plural_forms(),
49 : m_has_fallback(false),
50 0 : m_fallback()
51 : {
52 0 : }
53 :
54 0 : Dictionary::~Dictionary()
55 : {
56 0 : }
57 :
58 : std::string
59 0 : Dictionary::get_charset() const
60 : {
61 0 : return charset;
62 : }
63 :
64 : void
65 0 : Dictionary::set_plural_forms(const PluralForms& plural_forms_)
66 : {
67 0 : plural_forms = plural_forms_;
68 0 : }
69 :
70 : PluralForms
71 0 : Dictionary::get_plural_forms() const
72 : {
73 0 : return plural_forms;
74 : }
75 :
76 : std::string
77 0 : Dictionary::translate_plural(const std::string& msgid, const std::string& msgid_plural, int num) const
78 : {
79 0 : return translate_plural(entries, msgid, msgid_plural, num);
80 : }
81 :
82 : std::string
83 0 : Dictionary::translate_plural(const Entries& dict, const std::string& msgid, const std::string& msgid_plural, int count) const
84 : {
85 0 : Entries::const_iterator it = dict.find(msgid);
86 0 : if (it != dict.end())
87 : {
88 0 : unsigned int n = plural_forms.get_plural(count);
89 0 : const std::vector<std::string>& msgstrs = it->second;
90 0 : if (n >= msgstrs.size())
91 : {
92 0 : log_error << "Plural translation not available (and not set to empty): '" << msgid << "'" << std::endl;
93 0 : log_error << "Missing plural form: " << n << std::endl;
94 0 : return msgid;
95 : }
96 :
97 0 : if (!msgstrs[n].empty())
98 0 : return msgstrs[n];
99 : else
100 0 : if (count == 1) // default to english rules
101 0 : return msgid;
102 : else
103 0 : return msgid_plural;
104 : }
105 : else
106 : {
107 0 : log_info << "Couldn't translate: " << msgid << std::endl;
108 0 : log_info << "Candidates: " << std::endl;
109 0 : for (it = dict.begin(); it != dict.end(); ++it)
110 0 : log_info << "'" << it->first << "'" << std::endl;
111 :
112 0 : if (count == 1) // default to english rules
113 0 : return msgid;
114 : else
115 0 : return msgid_plural;
116 : }
117 : }
118 :
119 : std::string
120 0 : Dictionary::translate(const std::string& msgid) const
121 : {
122 0 : return translate(entries, msgid);
123 : }
124 :
125 : std::string
126 0 : Dictionary::translate(const Entries& dict, const std::string& msgid) const
127 : {
128 0 : Entries::const_iterator i = dict.find(msgid);
129 0 : if (i != dict.end() && !i->second.empty())
130 : {
131 0 : return i->second[0];
132 : }
133 : else
134 : {
135 0 : log_info << "Couldn't translate: " << msgid << std::endl;
136 :
137 0 : if (m_has_fallback) return m_fallback->translate(msgid);
138 0 : else return msgid;
139 : }
140 : }
141 :
142 : std::string
143 0 : Dictionary::translate_ctxt(const std::string& msgctxt, const std::string& msgid) const
144 : {
145 0 : CtxtEntries::const_iterator i = ctxt_entries.find(msgctxt);
146 0 : if (i != ctxt_entries.end())
147 : {
148 0 : return translate(i->second, msgid);
149 : }
150 : else
151 : {
152 0 : log_info << "Couldn't translate: " << msgid << std::endl;
153 0 : return msgid;
154 : }
155 : }
156 :
157 : std::string
158 0 : Dictionary::translate_ctxt_plural(const std::string& msgctxt,
159 : const std::string& msgid, const std::string& msgidplural, int num) const
160 : {
161 0 : CtxtEntries::const_iterator i = ctxt_entries.find(msgctxt);
162 0 : if (i != ctxt_entries.end())
163 : {
164 0 : return translate_plural(i->second, msgid, msgidplural, num);
165 : }
166 : else
167 : {
168 0 : log_info << "Couldn't translate: " << msgid << std::endl;
169 0 : if (num != 1) // default to english
170 0 : return msgidplural;
171 : else
172 0 : return msgid;
173 : }
174 : }
175 :
176 : void
177 0 : Dictionary::add_translation(const std::string& msgid, const std::string& msgid_plural,
178 : const std::vector<std::string>& msgstrs)
179 : {
180 0 : std::vector<std::string>& vec = entries[msgid];
181 0 : if (vec.empty())
182 : {
183 0 : vec = msgstrs;
184 : }
185 0 : else if (vec != msgstrs)
186 : {
187 0 : log_warning << "collision in add_translation: '"
188 : << msgid << "', '" << msgid_plural
189 0 : << "' -> [" << vec << "] vs [" << msgstrs << "]" << std::endl;
190 0 : vec = msgstrs;
191 : }
192 0 : }
193 :
194 : void
195 0 : Dictionary::add_translation(const std::string& msgid, const std::string& msgstr)
196 : {
197 0 : std::vector<std::string>& vec = entries[msgid];
198 0 : if (vec.empty())
199 : {
200 0 : vec.push_back(msgstr);
201 : }
202 0 : else if (vec[0] != msgstr)
203 : {
204 0 : log_warning << "collision in add_translation: '"
205 0 : << msgid << "' -> '" << msgstr << "' vs '" << vec[0] << "'" << std::endl;
206 0 : vec[0] = msgstr;
207 : }
208 0 : }
209 :
210 : void
211 0 : Dictionary::add_translation(const std::string& msgctxt,
212 : const std::string& msgid, const std::string& msgid_plural,
213 : const std::vector<std::string>& msgstrs)
214 : {
215 0 : std::vector<std::string>& vec = ctxt_entries[msgctxt][msgid];
216 0 : if (vec.empty())
217 : {
218 0 : vec = msgstrs;
219 : }
220 0 : else if (vec != msgstrs)
221 : {
222 0 : log_warning << "collision in add_translation: '"
223 : << msgctxt << "', '" << msgid << "', '" << msgid_plural
224 0 : << "' -> [" << vec << "] vs [" << msgstrs << "]" << std::endl;
225 0 : vec = msgstrs;
226 : }
227 0 : }
228 :
229 : void
230 0 : Dictionary::add_translation(const std::string& msgctxt, const std::string& msgid, const std::string& msgstr)
231 : {
232 0 : std::vector<std::string>& vec = ctxt_entries[msgctxt][msgid];
233 0 : if (vec.empty())
234 : {
235 0 : vec.push_back(msgstr);
236 : }
237 0 : else if (vec[0] != msgstr)
238 : {
239 0 : log_warning << "collision in add_translation: '"
240 : << msgctxt << "', '" << msgid
241 0 : << "' -> '" << vec[0] << "' vs '" << msgstr << "'" << std::endl;
242 0 : vec[0] = msgstr;
243 : }
244 0 : }
245 :
246 3 : } // namespace tinygettext
247 :
248 : /* EOF */
|