392e8d3bd859c034a0f6da292665688bc386ac35
[libi2ncommon] / src / i18n.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /***************************************************************************
21                           i18n.cpp  -  description
22                              -------------------
23     begin                : Wed Apr 25 2001
24     copyright            : (C) 2001-2004 by Intra2net AG
25  ***************************************************************************/
26
27 #include <sstream>
28 #include <string>
29 #include <vector>
30 #include <iostream>
31 #include <fstream>
32
33 #include <time.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "i18n.h"
37
38 #define DEFAULT_LANG "en_EN"
39
40 using namespace std;
41
42 void i18n_init (const string& domain, const string& path)
43 {
44    i18n_set_language (i18n_get_default_language());
45
46    bindtextdomain (domain.c_str(), path.c_str());
47    textdomain (domain.c_str());
48 }
49
50 void i18n_set_language (const string &lang)
51 {
52    string target;
53
54    if (lang.empty())
55       target=DEFAULT_LANG;
56    else
57    {
58       if (lang=="NULL")
59          target="";
60       else
61          target=lang;
62    }
63
64    if (target.empty())
65       setlocale(LC_ALL,"C");
66    else
67       setlocale(LC_ALL,target.c_str());
68
69     // Flush gcc based gettext caching. Code is from the -GNU-
70     // gettext manual in the "being a gettext grok" chapter.
71     {
72         extern int  _nl_msg_cat_cntr;
73         ++_nl_msg_cat_cntr;
74     }
75
76    return;
77 }
78
79 // empty string returned: no language set
80 string i18n_get_current_language(void)
81 {
82    string lng;
83    char* env=setlocale(LC_ALL,NULL);
84
85    if (env != NULL)
86    {
87       if (strcmp(env,"C")==0)
88          lng="NULL";
89       else
90          lng=env;
91    }
92    else
93       lng="NULL";
94
95    return lng;
96 }
97
98 // empty string returned: no language set
99 string i18n_get_default_language(void)
100 {
101     string lang;
102
103     ifstream in("/usr/intranator/etc/locale");
104     if (in)
105     {
106         getline (in, lang);
107
108         if (lang.empty())
109             lang=DEFAULT_LANG;
110         in.close(); 
111     }
112
113     return lang;
114 }
115
116 void i18n_get_string(const char *source, string &target, const vector<string> &data) {
117     string src = string (source);
118     i18n_get_string (src, target, data);
119 }
120
121 string i18n_get_string(const char *source, const vector<string> &data) {
122     string target;
123     string src = string (source);
124     i18n_get_string (src, target, data);
125     return target;
126 }
127
128 string i18n_get_string(const string &source, const vector<string> &data) {
129     string target;
130     i18n_get_string (source, target, data);
131     return target;
132 }
133
134 void i18n_get_string(const string &source, string &target, const vector<string> &data)
135 {
136         string::size_type p=0, slen=0;
137         string dollar="$";
138
139         // custom vars
140         string text = source;
141
142         target=text;
143
144         while ((p=target.find('$',p))!=string::npos)
145         {
146                 const string *ins;
147
148                 if (target.size() < p)
149                 {
150                         ostringstream os;
151                         os << "i18n syntax error: $ without number at pos ->" << p << "<- in string ->" << text << "<-";
152                         target = os.str();
153                         return;
154                 }                       
155
156                 // find string to insert (=ins)
157                 if (target.at(p+1)=='$')
158                 {
159                         ins=&dollar;            
160                         slen=2;
161                 }
162                 else
163                 {
164                         slen=target.find_first_not_of("0123456789",p+1);
165
166                         if (slen==string::npos)
167                 slen=target.size();
168
169                         if (slen==p+1)
170                         {
171                                 ostringstream os;
172                                 os << "i18n syntax error: $ without number at pos ->" << p << "<- in string ->" << text << "<-";
173                                 target = os.str();
174                                 return;
175                         }                       
176
177                         slen-=p;
178                         istringstream is(target.substr(p+1,slen-1));
179                         unsigned int dnr;
180
181                         is >> dnr;
182
183                         if (is.fail())
184                         {
185                                 ostringstream os;
186                                 os << "i18n syntax error: error reading number at pos ->" << p << "<- in string ->" << text << "<-";
187                                 target = os.str();
188                                 return;
189                         }                       
190
191                         if (dnr+1 > data.size())
192                         {
193                                 ostringstream os;
194                                 os << "i18n parameter error: missing variable ->$" << dnr << "<- in string ->" << text << "<-";
195                                 target = os.str();
196                                 return;
197                         }                       
198
199                         ins=&(data.at(dnr));
200                 }
201
202                 target.replace(p,slen,*ins);
203                 p=p+ins->size();
204         }
205 }
206
207 // convert locale to language (de_DE -> de)
208 string i18n_locale2language(string locale)
209 {
210     // search for "_"
211     string::size_type pos = locale.find("_");
212     if (pos == string::npos)
213         return locale;
214
215     return(locale.substr(0, pos));
216 }