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_LOCALE_MESSAGE_HPP_INCLUDED
9 #define BOOST_LOCALE_MESSAGE_HPP_INCLUDED
10 
11 #include <boost/locale/config.hpp>
12 #ifdef BOOST_MSVC
13 #  pragma warning(push)
14 #  pragma warning(disable : 4275 4251 4231 4660)
15 #endif
16 #include <locale>
17 #include <string>
18 #include <vector>
19 #include <set>
20 #include <memory>
21 #include <boost/locale/formatting.hpp>
22 
23 
24 namespace boost {
25     namespace locale {
26         ///
27         /// \defgroup message Message Formatting (translation)
28         ///
29         ///This module provides message translation functionality, i.e. allow your application to speak native language
30         ///
31         /// @{
32         ///
33 
34         /// \cond INTERNAL
35 
36         template<typename CharType>
37         struct base_message_format: public std::locale::facet
38         {
39         };
40 
41         /// \endcond
42 
43         ///
44         /// \brief This facet provides message formatting abilities
45         ///
46         template<typename CharType>
47         class message_format : public base_message_format<CharType>
48         {
49         public:
50 
51             ///
52             /// Character type
53             ///
54             typedef CharType char_type;
55             ///
56             /// String type
57             ///
58             typedef std::basic_string<CharType> string_type;
59 
60             ///
61             /// Default constructor
62             ///
message_format(size_t refs=0)63             message_format(size_t refs = 0) :
64                 base_message_format<CharType>(refs)
65             {
66             }
67 
68             ///
69             /// This function returns a pointer to the string for a message defined by a \a context
70             /// and identification string \a id. Both create a single key for message lookup in
71             /// a domain defined by \a domain_id.
72             ///
73             /// If \a context is NULL it is not considered to be a part of the key
74             ///
75             /// If a translated string is found, it is returned, otherwise NULL is returned
76             ///
77             ///
78             virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const = 0;
79             ///
80             /// This function returns a pointer to the string for a plural message defined by a \a context
81             /// and identification string \a single_id.
82             ///
83             /// If \a context is NULL it is not considered to be a part of the key
84             ///
85             /// Both create a single key for message lookup in
86             /// a domain defined \a domain_id. \a n is used to pick the correct translation string for a specific
87             /// number.
88             ///
89             /// If a translated string is found, it is returned, otherwise NULL is returned
90             ///
91             ///
92             virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const = 0;
93 
94             ///
95             /// Convert a string that defines \a domain to the integer id used by \a get functions
96             ///
97             virtual int domain(std::string const &domain) const = 0;
98 
99             ///
100             /// Convert the string \a msg to target locale's encoding. If \a msg is already
101             /// in target encoding it would be returned otherwise the converted
102             /// string is stored in temporary \a buffer and buffer.c_str() is returned.
103             ///
104             /// Note: for char_type that is char16_t, char32_t and wchar_t it is no-op, returns
105             /// msg
106             ///
107             virtual char_type const *convert(char_type const *msg,string_type &buffer) const = 0;
108 
109 #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
__get_id(void) const110             std::locale::id& __get_id (void) const { return id; }
111 #endif
112         protected:
~message_format()113             virtual ~message_format()
114             {
115             }
116 
117         };
118 
119         /// \cond INTERNAL
120 
121         namespace details {
is_us_ascii_char(char c)122             inline bool is_us_ascii_char(char c)
123             {
124                 // works for null terminated strings regardless char "signness"
125                 return 0<c && c<0x7F;
126             }
is_us_ascii_string(char const * msg)127             inline bool is_us_ascii_string(char const *msg)
128             {
129                 while(*msg) {
130                     if(!is_us_ascii_char(*msg++))
131                         return false;
132                 }
133                 return true;
134             }
135 
136             template<typename CharType>
137             struct string_cast_traits {
castboost::locale::details::string_cast_traits138                 static CharType const *cast(CharType const *msg,std::basic_string<CharType> &/*unused*/)
139                 {
140                     return msg;
141                 }
142             };
143 
144             template<>
145             struct string_cast_traits<char> {
castboost::locale::details::string_cast_traits146                 static char const *cast(char const *msg,std::string &buffer)
147                 {
148                     if(is_us_ascii_string(msg))
149                         return msg;
150                     buffer.reserve(strlen(msg));
151                     char c;
152                     while((c=*msg++)!=0) {
153                         if(is_us_ascii_char(c))
154                             buffer+=c;
155                     }
156                     return buffer.c_str();
157                 }
158             };
159         } // details
160 
161         /// \endcond
162 
163         ///
164         /// \brief This class represents a message that can be converted to a specific locale message
165         ///
166         /// It holds the original ASCII string that is queried in the dictionary when converting to the output string.
167         /// The created string may be UTF-8, UTF-16, UTF-32 or other 8-bit encoded string according to the target
168         /// character type and locale encoding.
169         ///
170         template<typename CharType>
171         class basic_message {
172         public:
173 
174             typedef CharType char_type; ///< The character this message object is used with
175             typedef std::basic_string<char_type> string_type;   ///< The string type this object can be used with
176             typedef message_format<char_type> facet_type;   ///< The type of the facet the messages are fetched with
177 
178             ///
179             /// Create default empty message
180             ///
basic_message()181             basic_message() :
182                 n_(0),
183                 c_id_(0),
184                 c_context_(0),
185                 c_plural_(0)
186             {
187             }
188 
189             ///
190             /// Create a simple message from 0 terminated string. The string should exist
191             /// until the message is destroyed. Generally useful with static constant strings
192             ///
basic_message(char_type const * id)193             explicit basic_message(char_type const *id) :
194                 n_(0),
195                 c_id_(id),
196                 c_context_(0),
197                 c_plural_(0)
198             {
199             }
200 
201             ///
202             /// Create a simple plural form message from 0 terminated strings. The strings should exist
203             /// until the message is destroyed. Generally useful with static constant strings.
204             ///
205             /// \a n is the number, \a single and \a plural are singular and plural forms of the message
206             ///
basic_message(char_type const * single,char_type const * plural,int n)207             explicit basic_message(char_type const *single,char_type const *plural,int n) :
208                 n_(n),
209                 c_id_(single),
210                 c_context_(0),
211                 c_plural_(plural)
212             {
213             }
214 
215             ///
216             /// Create a simple message from 0 terminated strings, with context
217             /// information. The string should exist
218             /// until the message is destroyed. Generally useful with static constant strings
219             ///
basic_message(char_type const * context,char_type const * id)220             explicit basic_message(char_type const *context,char_type const *id) :
221                 n_(0),
222                 c_id_(id),
223                 c_context_(context),
224                 c_plural_(0)
225             {
226             }
227 
228             ///
229             /// Create a simple plural form message from 0 terminated strings, with context. The strings should exist
230             /// until the message is destroyed. Generally useful with static constant strings.
231             ///
232             /// \a n is the number, \a single and \a plural are singular and plural forms of the message
233             ///
basic_message(char_type const * context,char_type const * single,char_type const * plural,int n)234             explicit basic_message(char_type const *context,char_type const *single,char_type const *plural,int n) :
235                 n_(n),
236                 c_id_(single),
237                 c_context_(context),
238                 c_plural_(plural)
239             {
240             }
241 
242 
243             ///
244             /// Create a simple message from a string.
245             ///
basic_message(string_type const & id)246             explicit basic_message(string_type const &id) :
247                 n_(0),
248                 c_id_(0),
249                 c_context_(0),
250                 c_plural_(0),
251                 id_(id)
252             {
253             }
254 
255             ///
256             /// Create a simple plural form message from strings.
257             ///
258             /// \a n is the number, \a single and \a plural are single and plural forms of the message
259             ///
basic_message(string_type const & single,string_type const & plural,int number)260             explicit basic_message(string_type const &single,string_type const &plural,int number) :
261                 n_(number),
262                 c_id_(0),
263                 c_context_(0),
264                 c_plural_(0),
265                 id_(single),
266                 plural_(plural)
267             {
268             }
269 
270             ///
271             /// Create a simple message from a string with context.
272             ///
basic_message(string_type const & context,string_type const & id)273             explicit basic_message(string_type const &context,string_type const &id) :
274                 n_(0),
275                 c_id_(0),
276                 c_context_(0),
277                 c_plural_(0),
278                 id_(id),
279                 context_(context)
280             {
281             }
282 
283             ///
284             /// Create a simple plural form message from strings.
285             ///
286             /// \a n is the number, \a single and \a plural are single and plural forms of the message
287             ///
basic_message(string_type const & context,string_type const & single,string_type const & plural,int number)288             explicit basic_message(string_type const &context,string_type const &single,string_type const &plural,int number) :
289                 n_(number),
290                 c_id_(0),
291                 c_context_(0),
292                 c_plural_(0),
293                 id_(single),
294                 context_(context),
295                 plural_(plural)
296             {
297             }
298 
299             ///
300             /// Copy an object
301             ///
basic_message(basic_message const & other)302             basic_message(basic_message const &other) :
303                 n_(other.n_),
304                 c_id_(other.c_id_),
305                 c_context_(other.c_context_),
306                 c_plural_(other.c_plural_),
307                 id_(other.id_),
308                 context_(other.context_),
309                 plural_(other.plural_)
310             {
311             }
312 
313             ///
314             /// Assign other message object to this one
315             ///
operator =(basic_message const & other)316             basic_message const &operator=(basic_message const &other)
317             {
318                 if(this==&other) {
319                     return *this;
320                 }
321                 basic_message tmp(other);
322                 swap(tmp);
323                 return *this;
324             }
325 
326             ///
327             /// Swap two message objects
328             ///
swap(basic_message & other)329             void swap(basic_message &other)
330             {
331                 std::swap(n_,other.n_);
332                 std::swap(c_id_,other.c_id_);
333                 std::swap(c_context_,other.c_context_);
334                 std::swap(c_plural_,other.c_plural_);
335 
336                 id_.swap(other.id_);
337                 context_.swap(other.context_);
338                 plural_.swap(other.plural_);
339             }
340 
341             ///
342             /// Message class can be explicitly converted to string class
343             ///
344 
operator string_type() const345             operator string_type () const
346             {
347                 return str();
348             }
349 
350             ///
351             /// Translate message to a string in the default global locale, using default domain
352             ///
str() const353             string_type str() const
354             {
355                 std::locale loc;
356                 return str(loc,0);
357             }
358 
359             ///
360             /// Translate message to a string in the locale \a locale, using default domain
361             ///
str(std::locale const & locale) const362             string_type str(std::locale const &locale) const
363             {
364                 return str(locale,0);
365             }
366 
367             ///
368             /// Translate message to a string using locale \a locale and message domain  \a domain_id
369             ///
str(std::locale const & locale,std::string const & domain_id) const370             string_type str(std::locale const &locale,std::string const &domain_id) const
371             {
372                 int id=0;
373                 if(std::has_facet<facet_type>(locale))
374                     id=std::use_facet<facet_type>(locale).domain(domain_id);
375                 return str(locale,id);
376             }
377 
378             ///
379             /// Translate message to a string using the default locale and message domain  \a domain_id
380             ///
str(std::string const & domain_id) const381             string_type str(std::string const &domain_id) const
382             {
383                 int id=0;
384                 std::locale loc;
385                 if(std::has_facet<facet_type>(loc))
386                     id=std::use_facet<facet_type>(loc).domain(domain_id);
387                 return str(loc,id);
388             }
389 
390 
391             ///
392             /// Translate message to a string using locale \a loc and message domain index  \a id
393             ///
str(std::locale const & loc,int id) const394             string_type str(std::locale const &loc,int id) const
395             {
396                 string_type buffer;
397                 char_type const *ptr = write(loc,id,buffer);
398                 if(ptr == buffer.c_str())
399                     return buffer;
400                 else
401                     buffer = ptr;
402                 return buffer;
403             }
404 
405 
406             ///
407             /// Translate message and write to stream \a out, using imbued locale and domain set to the
408             /// stream
409             ///
write(std::basic_ostream<char_type> & out) const410             void write(std::basic_ostream<char_type> &out) const
411             {
412                 std::locale const &loc = out.getloc();
413                 int id = ios_info::get(out).domain_id();
414                 string_type buffer;
415                 out << write(loc,id,buffer);
416             }
417 
418         private:
plural() const419             char_type const *plural() const
420             {
421                 if(c_plural_)
422                     return c_plural_;
423                 if(plural_.empty())
424                     return 0;
425                 return plural_.c_str();
426             }
context() const427             char_type const *context() const
428             {
429                 if(c_context_)
430                     return c_context_;
431                 if(context_.empty())
432                     return 0;
433                 return context_.c_str();
434             }
435 
id() const436             char_type const *id() const
437             {
438                 return c_id_ ? c_id_ : id_.c_str();
439             }
440 
write(std::locale const & loc,int domain_id,string_type & buffer) const441             char_type const *write(std::locale const &loc,int domain_id,string_type &buffer) const
442             {
443                 char_type const *translated = 0;
444                 static const char_type empty_string[1] = {0};
445 
446                 char_type const *id = this->id();
447                 char_type const *context = this->context();
448                 char_type const *plural = this->plural();
449 
450                 if(*id == 0)
451                     return empty_string;
452 
453                 facet_type const *facet = 0;
454                 if(std::has_facet<facet_type>(loc))
455                     facet = &std::use_facet<facet_type>(loc);
456 
457                 if(facet) {
458                     if(!plural) {
459                         translated = facet->get(domain_id,context,id);
460                     }
461                     else {
462                         translated = facet->get(domain_id,context,id,n_);
463                     }
464                 }
465 
466                 if(!translated) {
467                     char_type const *msg = plural ? ( n_ == 1 ? id : plural) : id;
468 
469                     if(facet) {
470                         translated = facet->convert(msg,buffer);
471                     }
472                     else {
473                         translated = details::string_cast_traits<char_type>::cast(msg,buffer);
474                     }
475                 }
476                 return translated;
477             }
478 
479             /// members
480 
481             int n_;
482             char_type const *c_id_;
483             char_type const *c_context_;
484             char_type const *c_plural_;
485             string_type id_;
486             string_type context_;
487             string_type plural_;
488         };
489 
490 
491         ///
492         /// Convenience typedef for char
493         ///
494         typedef basic_message<char> message;
495         ///
496         /// Convenience typedef for wchar_t
497         ///
498         typedef basic_message<wchar_t> wmessage;
499         #ifdef BOOST_HAS_CHAR16_T
500         ///
501         /// Convenience typedef for char16_t
502         ///
503         typedef basic_message<char16_t> u16message;
504         #endif
505         #ifdef BOOST_HAS_CHAR32_T
506         ///
507         /// Convenience typedef for char32_t
508         ///
509         typedef basic_message<char32_t> u32message;
510         #endif
511 
512         ///
513         /// Translate message \a msg and write it to stream
514         ///
515         template<typename CharType>
operator <<(std::basic_ostream<CharType> & out,basic_message<CharType> const & msg)516         std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_message<CharType> const &msg)
517         {
518             msg.write(out);
519             return out;
520         }
521 
522         ///
523         /// \anchor boost_locale_translate_family \name Indirect message translation function family
524         /// @{
525 
526         ///
527         /// \brief Translate a message, \a msg is not copied
528         ///
529         template<typename CharType>
translate(CharType const * msg)530         inline basic_message<CharType> translate(CharType const *msg)
531         {
532             return basic_message<CharType>(msg);
533         }
534         ///
535         /// \brief Translate a message in context, \a msg and \a context are not copied
536         ///
537         template<typename CharType>
translate(CharType const * context,CharType const * msg)538         inline basic_message<CharType> translate(   CharType const *context,
539                                                     CharType const *msg)
540         {
541             return basic_message<CharType>(context,msg);
542         }
543         ///
544         /// \brief Translate a plural message form, \a single and \a plural are not copied
545         ///
546         template<typename CharType>
translate(CharType const * single,CharType const * plural,int n)547         inline basic_message<CharType> translate(   CharType const *single,
548                                                     CharType const *plural,
549                                                     int n)
550         {
551             return basic_message<CharType>(single,plural,n);
552         }
553         ///
554         /// \brief Translate a plural message from in constext, \a context, \a single and \a plural are not copied
555         ///
556         template<typename CharType>
translate(CharType const * context,CharType const * single,CharType const * plural,int n)557         inline basic_message<CharType> translate(   CharType const *context,
558                                                     CharType const *single,
559                                                     CharType const *plural,
560                                                     int n)
561         {
562             return basic_message<CharType>(context,single,plural,n);
563         }
564 
565         ///
566         /// \brief Translate a message, \a msg is copied
567         ///
568         template<typename CharType>
translate(std::basic_string<CharType> const & msg)569         inline basic_message<CharType> translate(std::basic_string<CharType> const &msg)
570         {
571             return basic_message<CharType>(msg);
572         }
573 
574         ///
575         /// \brief Translate a message in context,\a context and \a msg is copied
576         ///
577         template<typename CharType>
translate(std::basic_string<CharType> const & context,std::basic_string<CharType> const & msg)578         inline basic_message<CharType> translate(   std::basic_string<CharType> const &context,
579                                                     std::basic_string<CharType> const &msg)
580         {
581             return basic_message<CharType>(context,msg);
582         }
583         ///
584         /// \brief Translate a plural message form in constext, \a context, \a single and \a plural are copied
585         ///
586         template<typename CharType>
translate(std::basic_string<CharType> const & context,std::basic_string<CharType> const & single,std::basic_string<CharType> const & plural,int n)587         inline basic_message<CharType> translate(   std::basic_string<CharType> const &context,
588                                                     std::basic_string<CharType> const &single,
589                                                     std::basic_string<CharType> const &plural,
590                                                     int n)
591         {
592             return basic_message<CharType>(context,single,plural,n);
593         }
594 
595         ///
596         /// \brief Translate a plural message form, \a single and \a plural are copied
597         ///
598 
599         template<typename CharType>
translate(std::basic_string<CharType> const & single,std::basic_string<CharType> const & plural,int n)600         inline basic_message<CharType> translate(   std::basic_string<CharType> const &single,
601                                                     std::basic_string<CharType> const &plural,
602                                                     int n)
603         {
604             return basic_message<CharType>(single,plural,n);
605         }
606 
607         /// @}
608 
609         ///
610         /// \anchor boost_locale_gettext_family \name Direct message translation functions family
611         ///
612 
613         ///
614         /// Translate message \a id according to locale \a loc
615         ///
616         template<typename CharType>
gettext(CharType const * id,std::locale const & loc=std::locale ())617         std::basic_string<CharType> gettext(CharType const *id,
618                                             std::locale const &loc=std::locale())
619         {
620             return basic_message<CharType>(id).str(loc);
621         }
622         ///
623         /// Translate plural form according to locale \a loc
624         ///
625         template<typename CharType>
ngettext(CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())626         std::basic_string<CharType> ngettext(   CharType const *s,
627                                                 CharType const *p,
628                                                 int n,
629                                                 std::locale const &loc=std::locale())
630         {
631             return basic_message<CharType>(s,p,n).str(loc);
632         }
633         ///
634         /// Translate message \a id according to locale \a loc in domain \a domain
635         ///
636         template<typename CharType>
dgettext(char const * domain,CharType const * id,std::locale const & loc=std::locale ())637         std::basic_string<CharType>  dgettext(  char const *domain,
638                                                 CharType const *id,
639                                                 std::locale const &loc=std::locale())
640         {
641             return basic_message<CharType>(id).str(loc,domain);
642         }
643 
644         ///
645         /// Translate plural form according to locale \a loc in domain \a domain
646         ///
647         template<typename CharType>
dngettext(char const * domain,CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())648         std::basic_string<CharType>  dngettext( char const *domain,
649                                                 CharType const *s,
650                                                 CharType const *p,
651                                                 int n,
652                                                 std::locale const &loc=std::locale())
653         {
654             return basic_message<CharType>(s,p,n).str(loc,domain);
655         }
656         ///
657         /// Translate message \a id according to locale \a loc in context \a context
658         ///
659         template<typename CharType>
pgettext(CharType const * context,CharType const * id,std::locale const & loc=std::locale ())660         std::basic_string<CharType>  pgettext(  CharType const *context,
661                                                 CharType const *id,
662                                                 std::locale const &loc=std::locale())
663         {
664             return basic_message<CharType>(context,id).str(loc);
665         }
666         ///
667         /// Translate plural form according to locale \a loc in context \a context
668         ///
669         template<typename CharType>
npgettext(CharType const * context,CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())670         std::basic_string<CharType>  npgettext( CharType const *context,
671                                                 CharType const *s,
672                                                 CharType const *p,
673                                                 int n,
674                                                 std::locale const &loc=std::locale())
675         {
676             return basic_message<CharType>(context,s,p,n).str(loc);
677         }
678         ///
679         /// Translate message \a id according to locale \a loc in domain \a domain in context \a context
680         ///
681         template<typename CharType>
dpgettext(char const * domain,CharType const * context,CharType const * id,std::locale const & loc=std::locale ())682         std::basic_string<CharType>  dpgettext( char const *domain,
683                                                 CharType const *context,
684                                                 CharType const *id,
685                                                 std::locale const &loc=std::locale())
686         {
687             return basic_message<CharType>(context,id).str(loc,domain);
688         }
689         ///
690         /// Translate plural form according to locale \a loc in domain \a domain in context \a context
691         ///
692         template<typename CharType>
dnpgettext(char const * domain,CharType const * context,CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())693         std::basic_string<CharType>  dnpgettext(char const *domain,
694                                                 CharType const *context,
695                                                 CharType const *s,
696                                                 CharType const *p,
697                                                 int n,
698                                                 std::locale const &loc=std::locale())
699         {
700             return basic_message<CharType>(context,s,p,n).str(loc,domain);
701         }
702 
703         ///
704         /// \cond INTERNAL
705         ///
706 
707         template<>
708         struct BOOST_LOCALE_DECL base_message_format<char> : public std::locale::facet
709         {
base_message_formatboost::locale::base_message_format710             base_message_format(size_t refs = 0) : std::locale::facet(refs)
711             {
712             }
713             static std::locale::id id;
714         };
715 
716         template<>
717         struct BOOST_LOCALE_DECL base_message_format<wchar_t> : public std::locale::facet
718         {
base_message_formatboost::locale::base_message_format719             base_message_format(size_t refs = 0) : std::locale::facet(refs)
720             {
721             }
722             static std::locale::id id;
723         };
724 
725         #ifdef BOOST_HAS_CHAR16_T
726 
727         template<>
728         struct BOOST_LOCALE_DECL base_message_format<char16_t> : public std::locale::facet
729         {
base_message_formatboost::locale::base_message_format730             base_message_format(size_t refs = 0) : std::locale::facet(refs)
731             {
732             }
733             static std::locale::id id;
734         };
735 
736         #endif
737 
738         #ifdef BOOST_HAS_CHAR32_T
739 
740         template<>
741         struct BOOST_LOCALE_DECL base_message_format<char32_t> : public std::locale::facet
742         {
base_message_formatboost::locale::base_message_format743             base_message_format(size_t refs = 0) : std::locale::facet(refs)
744             {
745             }
746             static std::locale::id id;
747         };
748 
749         #endif
750 
751         /// \endcond
752 
753         ///
754         /// @}
755         ///
756 
757         namespace as {
758             /// \cond INTERNAL
759             namespace details {
760                 struct set_domain {
761                     std::string domain_id;
762                 };
763                 template<typename CharType>
operator <<(std::basic_ostream<CharType> & out,set_domain const & dom)764                 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out, set_domain const &dom)
765                 {
766                     int id = std::use_facet<message_format<CharType> >(out.getloc()).domain(dom.domain_id);
767                     ios_info::get(out).domain_id(id);
768                     return out;
769                 }
770             } // details
771             /// \endcond
772 
773             ///
774             /// \addtogroup manipulators
775             ///
776             /// @{
777 
778             ///
779             /// Manipulator for switching message domain in ostream,
780             ///
781             /// \note The returned object throws std::bad_cast if the I/O stream does not have \ref message_format facet installed
782             ///
783             inline
784             #ifdef BOOST_LOCALE_DOXYGEN
785             unspecified_type
786             #else
787             details::set_domain
788             #endif
domain(std::string const & id)789             domain(std::string const &id)
790             {
791                 details::set_domain tmp = { id };
792                 return tmp;
793             }
794             /// @}
795         } // as
796     } // locale
797 } // boost
798 
799 #ifdef BOOST_MSVC
800 #pragma warning(pop)
801 #endif
802 
803 
804 #endif
805 
806 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
807 
808