Merge libgettext code into libi2ncommon
[libi2ncommon] / src / i18n.cpp
1 /***************************************************************************
2                           i18n.cpp  -  description
3                              -------------------
4     begin                : Wed Apr 25 2001
5     copyright            : (C) 2001-2004 by Intra2net AG
6     email                : info@intra2net.com
7  ***************************************************************************/
8
9 #include <sstream>
10 #include <string>
11 #include <vector>
12 #include <iostream>
13 #include <fstream>
14
15 #include <time.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "i18n.h"
19
20 #define DEFAULT_LANG "en_EN"
21
22 using namespace std;
23
24 void i18n_init (const string& domain, const string& path)
25 {
26    i18n_set_language (i18n_get_default_language());
27
28    bindtextdomain (domain.c_str(), path.c_str());
29    textdomain (domain.c_str());
30 }
31
32 void i18n_set_language (const string &lang)
33 {
34    string target;
35
36    if (lang.empty())
37       target=DEFAULT_LANG;
38    else
39    {
40       if (lang=="NULL")
41          target="";
42       else
43          target=lang;
44    }
45
46    if (target.empty())
47       setlocale(LC_ALL,"C");
48    else
49       setlocale(LC_ALL,target.c_str());
50
51     // Flush gcc based gettext caching. Code is from the -GNU-
52     // gettext manual in the "being a gettext grok" chapter.
53     {
54         extern int  _nl_msg_cat_cntr;
55         ++_nl_msg_cat_cntr;
56     }
57
58    return;
59 }
60
61 // empty string returned: no language set
62 string i18n_get_current_language(void)
63 {
64    string lng;
65    char* env=setlocale(LC_ALL,NULL);
66
67    if (env != NULL)
68    {
69       if (strcmp(env,"C")==0)
70          lng="NULL";
71       else
72          lng=env;
73    }
74    else
75       lng="NULL";
76
77    return lng;
78 }
79
80 // empty string returned: no language set
81 string i18n_get_default_language(void)
82 {
83     string lang;
84
85     ifstream in("/usr/intranator/etc/locale");
86     if (in)
87     {
88         getline (in, lang);
89
90         if (lang.empty())
91             lang=DEFAULT_LANG;
92         in.close(); 
93     }
94
95     return lang;
96 }
97
98 void i18n_get_string(const char *source, string &target, const vector<string> &data) {
99     string src = string (source);
100     i18n_get_string (src, target, data);
101 }
102
103 string i18n_get_string(const char *source, const vector<string> &data) {
104     string target;
105     string src = string (source);
106     i18n_get_string (src, target, data);
107     return target;
108 }
109
110 string i18n_get_string(const string &source, const vector<string> &data) {
111     string target;
112     i18n_get_string (source, target, data);
113     return target;
114 }
115
116 void i18n_get_string(const string &source, string &target, const vector<string> &data)
117 {
118         string::size_type p=0, slen=0;
119         string dollar="$";
120
121         // custom vars
122         string text = source;
123
124         target=text;
125
126         while ((p=target.find('$',p))!=string::npos)
127         {
128                 const string *ins;
129
130                 if (target.size() < p)
131                 {
132                         ostringstream os;
133                         os << "i18n syntax error: $ without number at pos ->" << p << "<- in string ->" << text << "<-";
134                         target = os.str();
135                         return;
136                 }                       
137
138                 // find string to insert (=ins)
139                 if (target.at(p+1)=='$')
140                 {
141                         ins=&dollar;            
142                         slen=2;
143                 }
144                 else
145                 {
146                         slen=target.find_first_not_of("0123456789",p+1);
147
148                         if (slen==string::npos)
149                 slen=target.size();
150
151                         if (slen==p+1)
152                         {
153                                 ostringstream os;
154                                 os << "i18n syntax error: $ without number at pos ->" << p << "<- in string ->" << text << "<-";
155                                 target = os.str();
156                                 return;
157                         }                       
158
159                         slen-=p;
160                         istringstream is(target.substr(p+1,slen-1));
161                         unsigned int dnr;
162
163                         is >> dnr;
164
165                         if (is.fail())
166                         {
167                                 ostringstream os;
168                                 os << "i18n syntax error: error reading number at pos ->" << p << "<- in string ->" << text << "<-";
169                                 target = os.str();
170                                 return;
171                         }                       
172
173                         if (dnr+1 > data.size())
174                         {
175                                 ostringstream os;
176                                 os << "i18n parameter error: missing variable ->$" << dnr << "<- in string ->" << text << "<-";
177                                 target = os.str();
178                                 return;
179                         }                       
180
181                         ins=&(data.at(dnr));
182                 }
183
184                 target.replace(p,slen,*ins);
185                 p=p+ins->size();
186         }
187 }
188
189 // convert locale to language (de_DE -> de)
190 string i18n_locale2language(string locale)
191 {
192     // search for "_"
193     string::size_type pos = locale.find("_");
194     if (pos == string::npos)
195         return locale;
196
197     return(locale.substr(0, pos));
198 }