Ticket #7266: gettext_paths.patch

File gettext_paths.patch, 21.0 KB (added by Artyom Beilis, 10 years ago)

Better patch for future updates

  • boost/locale/gnu_gettext.hpp

     
    2424namespace gnu_gettext {
    2525
    2626    ///
     27    /// The callback for custom file system support. This callback should read the file named \a file_name
     28    /// encoded in \a encoding character set into std::vector<char> and return it.
     29    ///
     30    /// - If the file does not exist, it should return an empty vector.
     31    /// - If a error occurs during file read it should throw a error.
     32    ///
     33    /// \note The user should support only the encodings the locales are created for. So if the user
     34    /// uses only one encoding or the file system is encoding agnostic, he may ignore the \a encoding parameter.
     35    ///
     36    typedef function<
     37                std::vector<char>(
     38                    std::string const &file_name,
     39                    std::string const &encoding
     40                )
     41            > callback_type;
     42
     43    ///
     44    /// \brief This type represents GNU Gettext domain name for the messages.
     45    ///
     46    /// It consists of two parameters:
     47    ///
     48    /// - name - the name of the domain - used for opening the file name
     49    /// - encoding - the encoding of the keys in the sources, default - UTF-8
     50    ///
     51    class BOOST_LOCALE_DECL domain {
     52    public:
     53        ///
     54        /// Create a domain object from the name that can hold an encoding after symbol "/"
     55        /// such that if n is "hello/cp1255" then the name would be "hello" and "encoding" would
     56        /// be "cp1255" and if n is "hello" then the name would be the same but encoding would be
     57        /// "UTF-8"
     58        ///
     59        domain(std::string const &n);
     60        ///
     61        /// Create a domain object from the name and encoding
     62        ///
     63        domain(std::string const &name,std::string const &encodings);
     64       
     65        domain();
     66        domain(domain const &other);
     67        domain const &operator=(domain const &);
     68        ~domain();
     69
     70        std::string name() const;
     71        std::string encoding() const;
     72
     73        ///
     74        /// Check whether two objects are equivalent, only names are compared, encoding is ignored
     75        ///
     76        bool operator==(domain const &other) const;
     77        ///
     78        /// Check whether two objects aren't equivalent, only names are compared, encoding is ignored
     79        ///
     80        bool operator!=(domain const &other) const;
     81    private:
     82        struct data;
     83        data *d;
     84        std::string name_,encoding_;
     85    };
     86
     87
     88    ///
    2789    /// \brief This structure holds all information required for creating gnu-gettext message catalogs,
    2890    ///
    2991    /// The user is expected to set its parameters to load these catalogs correctly. This structure
    3092    /// also allows providing functions for charset conversion. Note, you need to provide them,
    3193    /// so this structure is not useful for wide characters without subclassing and it will also
    3294    /// ignore gettext catalogs that use a charset different from \a encoding.
     95    ///
     96    class BOOST_LOCALE_DECL catalog_info {
     97    public:
     98
     99        ///
     100        /// Initializes default catalog for "C" locale:
     101        ///
     102        /// - language: "C"
     103        /// - country: empty
     104        /// - variant: empty
     105        /// - encoding: empty
     106        /// - locale_category: "LC_MESSAGES"
     107        /// - path_formats: ( "{1}/{2}/{3}/{4}.mo" )
     108        ///
     109        ///
     110        ///  The user is expected to define at least: language, paths (at least one), domains (at least one)
     111        ///  and encoding for narrow character catalogs
     112        ///
     113        catalog_info();
     114        catalog_info(catalog_info const &);
     115        catalog_info const &operator=(catalog_info const &);
     116        ~catalog_info();
     117       
     118        ///
     119        /// Get the language we load the catalog for, like "ru", "en", "de"
     120        ///
     121        std::string language() const; 
     122        ///
     123        /// Set the language we load the catalog for, like "ru", "en", "de"
     124        ///
     125        void language(std::string const &); 
     126        ///
     127        /// Get the country we load the catalog for, like "US", "IL"   
     128        ///
     129        std::string country() const;   
     130        ///
     131        /// Set the country we load the catalog for, like "US", "IL"   
     132        ///
     133        void country(std::string const &);   
     134        ///
     135        /// Get language variant, like "euro" so it would look for catalog like de_DE\@euro
     136        ///
     137        std::string variant() const;   
     138        ///
     139        /// Set language variant, like "euro" so it would look for catalog like de_DE\@euro
     140        ///
     141        void variant(std::string const &);   
     142        ///
     143        /// Get the required target charset encoding. Ignored for wide characters.
     144        /// For narrow, should specify the correct encoding required for this catalog
     145        ///
     146        std::string encoding() const;   
     147        ///
     148        /// Set the required target charset encoding. Ignored for wide characters.
     149        /// For narrow, should specify the correct encoding required for this catalog
     150        ///
     151        void encoding(std::string const &);   
     152                                       
     153        ///
     154        /// Get the locale category, is set by default to LC_MESSAGES, but may be changed
     155        ///
     156        std::string locale_category() const;
     157        ///
     158        /// Set the locale category, is set by default to LC_MESSAGES, but may be changed
     159        ///
     160        void locale_category(std::string const &);
     161
     162        ///
     163        /// Get the callback for handling custom file systems, if it is empty, the real OS file-system
     164        /// is being used.
     165        ///
     166        callback_type callback() const;
     167        ///
     168        /// Set the callback for handling custom file systems, if it is empty, the real OS file-system
     169        /// is being used.
     170        ///
     171        void callback(callback_type const &);
     172       
     173        ///
     174        /// Type that defines a list of domains that are loaded
     175        /// The first one is the default one
     176        ///
     177        typedef std::vector<domain> domains_type;   
     178       
     179        ///
     180        /// Get message domains - application name, like my_app. So files named my_app.mo would be loaded
     181        ///
     182        domains_type domains() const;
     183        ///
     184        /// Add message domain - application name, like my_app. So files named my_app.mo would be loaded
     185        ///
     186        void add_domain(domain const &);
     187                                     
     188        /// 
     189        /// Paths to search files in. Under MS Windows it uses encoding
     190        /// parameter to convert them to wide OS specific paths.
     191        ///
     192        std::vector<std::string> paths() const;
     193
     194        ///
     195        /// Add a path to search in
     196        ///
     197        void add_path(std::string const &);
     198
     199        ///
     200        /// Optional formats to search the file in.
     201        ///
     202        /// Formats are the same syntax as the Boost format functions, but
     203        /// use the following variables:
     204        ///
     205        /// \li {1} A path to search for catalogs in.
     206        /// \li {2} The locale's name.
     207        /// \li {3} The locale's category.
     208        /// \li {4} The Gettext domain.
     209        ///
     210        /// For example, \c {1}/{2}/{3}/{4}.mo is the standard Gettext layout.
     211        /// Using something like \c {1}/{2}.mo would compact the folder hierarchy, for an
     212        /// application that uses a single domain
     213        ///
     214        std::vector<std::string> path_formats() const;
     215
     216        ///
     217        /// Add new path format, see \ref path_formats()
     218        ///
     219        void add_path_format(std::string const &);
     220
     221    private:
     222        struct data;
     223        data *d;
     224    };
     225
     226
    33227    ///
     228    /// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get
     229    /// information about where to read them from and uses it for character set conversion (if needed)
     230    ///
     231    template<typename CharType>
     232    message_format<CharType> *create_messages_facet(catalog_info const &info);
     233
     234
     235    // ---- deprecated stuff goes there --- //
     236
     237
     238 
     239    ///
     240    /// \brief This structure holds all information required for creating gnu-gettext message catalogs,
     241    ///
     242    /// The user is expected to set its parameters to load these catalogs correctly. This structure
     243    /// also allows providing functions for charset conversion. Note, you need to provide them,
     244    /// so this structure is not useful for wide characters without subclassing and it will also
     245    /// ignore gettext catalogs that use a charset different from \a encoding.
     246    ///
     247    /// \deprecated Use catalog_info instead
     248    ///
    34249    struct messages_info {
    35250        messages_info() :
    36251            language("C"),
     
    124339        ///
    125340        callback_type callback;
    126341
     342        ///
     343        /// Convert to non-deprecated format
     344        ///
     345        catalog_info to_catalog() const
     346        {
     347            catalog_info r;
     348           
     349            r.language(language);
     350
     351            if(!country.empty())
     352                r.country(country);
     353            if(!variant.empty())
     354                r.variant(variant);
     355            if(!encoding.empty())
     356                r.encoding(encoding);
     357            r.locale_category(locale_category);
     358            if(!callback.empty())
     359                r.callback(callback);
     360            for(size_t i=0;i<paths.size();i++)
     361                r.add_path(paths[i]);
     362            for(size_t i=0;i<domains.size();i++) {
     363                if(domains[i].encoding.empty())
     364                    r.add_domain(domains[i].name);
     365                else
     366                    r.add_domain(boost::locale::gnu_gettext::domain(domains[i].name,domains[i].encoding));
     367            }
     368            return r;
     369        }
     370
    127371    };
    128372
    129373    ///
    130374    /// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get
    131375    /// information about where to read them from and uses it for character set conversion (if needed)
    132376    ///
     377    /// \deprecated use create_messages_facet(catalog_info const &info)
     378    ///
    133379
    134380    template<typename CharType>
    135381    message_format<CharType> *create_messages_facet(messages_info const &info);
     382   
    136383
    137384    /// \cond INTERNAL
     385
     386    template<>
     387    BOOST_LOCALE_DECL message_format<char> *create_messages_facet(catalog_info const &info);
    138388   
    139389    template<>
     390    BOOST_LOCALE_DECL message_format<wchar_t> *create_messages_facet(catalog_info const &info);
     391
     392    #ifdef BOOST_HAS_CHAR16_T
     393    template<>
     394    BOOST_LOCALE_DECL message_format<char16_t> *create_messages_facet(catalog_info const &info);
     395    #endif
     396   
     397    #ifdef BOOST_HAS_CHAR32_T
     398    template<>
     399    BOOST_LOCALE_DECL message_format<char32_t> *create_messages_facet(catalog_info const &info);
     400    #endif
     401
     402
     403    // deprecated internal stuff
     404   
     405    template<>
    140406    BOOST_LOCALE_DECL message_format<char> *create_messages_facet(messages_info const &info);
    141407   
    142408    template<>
  • libs/locale/src/shared/message.cpp

     
    99#include <boost/config.hpp>
    1010#include <boost/locale/message.hpp>
    1111#include <boost/locale/gnu_gettext.hpp>
     12#include <boost/locale/format.hpp>
    1213#include <boost/shared_ptr.hpp>
    1314#include <boost/locale/encoding.hpp>
    1415#ifdef BOOST_MSVC
     
    533534                    return p->second;
    534535                }
    535536
    536                 mo_message(messages_info const &inf)
     537                mo_message(catalog_info const &inf)
    537538                {
    538                     std::string language = inf.language;
    539                     std::string variant = inf.variant;
    540                     std::string country = inf.country;
    541                     std::string encoding = inf.encoding;
    542                     std::string lc_cat = inf.locale_category;
    543                     std::vector<messages_info::domain> const &domains = inf.domains;
    544                     std::vector<std::string> const &search_paths = inf.paths;
     539                    std::vector<std::string> formats = inf.path_formats();
    545540                   
     541                    std::string language = inf.language();
     542                    std::string variant = inf.variant();
     543                    std::string country = inf.country();
     544                    std::string encoding = inf.encoding();
     545                    std::string lc_cat = inf.locale_category();
     546                    std::vector<boost::locale::gnu_gettext::domain> domains = inf.domains();
     547                    std::vector<std::string> search_paths = inf.paths();
     548                   
    546549                    //
    547550                    // List of fallbacks: en_US@euro, en@euro, en_US, en.
    548551                    //
     
    566569
    567570
    568571                    for(unsigned id=0;id<domains.size();id++) {
    569                         std::string domain=domains[id].name;
    570                         std::string key_encoding = domains[id].encoding;
     572                        std::string domain=domains[id].name();
     573                        std::string key_encoding = domains[id].encoding();
    571574                        domains_[domain]=id;
    572575
    573576
    574577                        bool found=false;
    575578                        for(unsigned j=0;!found && j<paths.size();j++) {
    576579                            for(unsigned i=0;!found && i<search_paths.size();i++) {
    577                                 std::string full_path = search_paths[i]+"/"+paths[j]+"/" + lc_cat + "/"+domain+".mo";
    578                                 found = load_file(full_path,encoding,key_encoding,id,inf.callback);
     580                                for(unsigned k=0;!found && k<formats.size();k++) {
     581                                    std::string full_path = (format(formats[k]) % search_paths[i] % paths[j] % lc_cat % domain).str(std::locale::classic());
     582                                    found = load_file(full_path,encoding,key_encoding,id,inf.callback());
     583                                }
    579584                            }
    580585                        }
    581586                    }
     
    743748                bool key_conversion_required_;
    744749            };
    745750
     751
    746752            template<>
    747             message_format<char> *create_messages_facet(messages_info const &info)
     753            message_format<char> *create_messages_facet(catalog_info const &data)
    748754            {
    749                 return new mo_message<char>(info);
     755                return new mo_message<char>(data);
    750756            }
    751757
    752758            template<>
    753             message_format<wchar_t> *create_messages_facet(messages_info const &info)
     759            message_format<wchar_t> *create_messages_facet(catalog_info const &data)
    754760            {
    755                 return new mo_message<wchar_t>(info);
     761                return new mo_message<wchar_t>(data);
    756762            }
    757763           
    758764            #ifdef BOOST_HAS_CHAR16_T
    759765
    760766            template<>
    761             message_format<char16_t> *create_messages_facet(messages_info const &info)
     767            message_format<char16_t> *create_messages_facet(catalog_info const &data)
    762768            {
    763                 return new mo_message<char16_t>(info);
     769                return new mo_message<char16_t>(data);
    764770            }
    765771            #endif
    766772           
    767773            #ifdef BOOST_HAS_CHAR32_T
    768774
    769775            template<>
    770             message_format<char32_t> *create_messages_facet(messages_info const &info)
     776            message_format<char32_t> *create_messages_facet(catalog_info const &data)
    771777            {
    772                 return new mo_message<char32_t>(info);
     778                return new mo_message<char32_t>(data);
    773779            }
    774780            #endif
    775781
     782            template<>
     783            message_format<char> *create_messages_facet(messages_info const &data)
     784            {
     785                return new mo_message<char>(data.to_catalog());
     786            }
    776787
     788            template<>
     789            message_format<wchar_t> *create_messages_facet(messages_info const &data)
     790            {
     791                return new mo_message<wchar_t>(data.to_catalog());
     792            }
     793           
     794            #ifdef BOOST_HAS_CHAR16_T
     795
     796            template<>
     797            message_format<char16_t> *create_messages_facet(messages_info const &data)
     798            {
     799                return new mo_message<char16_t>(data.to_catalog());
     800            }
     801            #endif
     802           
     803            #ifdef BOOST_HAS_CHAR32_T
     804
     805            template<>
     806            message_format<char32_t> *create_messages_facet(messages_info const &data)
     807            {
     808                return new mo_message<char32_t>(data.to_catalog());
     809            }
     810            #endif
     811
     812            struct domain::data {};
     813            domain::domain() : d(0) {}
     814            domain::~domain() {}
     815            domain::domain(domain const &other) :
     816                d(0),
     817                name_(other.name_),
     818                encoding_(other.encoding_)
     819            {
     820            }
     821            domain const &domain::operator=(domain const &other)
     822            {
     823                if(this!=&other) {
     824                    name_ = other.name_;
     825                    encoding_ = other.encoding_;
     826                }
     827                return *this;
     828            }
     829            std::string domain::name() const { return name_; }
     830            std::string domain::encoding() const { return encoding_; }
     831            domain::domain(std::string const &n,std::string const &e) :d(0),name_(n),encoding_(e) {}
     832            domain::domain(std::string const &n) : d(0)
     833            {
     834                size_t pos = n.find("/");
     835                if(pos==std::string::npos) {
     836                    name_ = n;
     837                    encoding_ = "UTF-8";
     838                }
     839                else {
     840                    name_ = n.substr(0,pos);
     841                    encoding_ = n.substr(pos+1);
     842                }
     843            }
     844            bool domain::operator==(domain const &other) const
     845            {
     846                return name_ == other.name_;
     847            }
     848            bool domain::operator!=(domain const &other) const
     849            {
     850                return !(*this == other);
     851            }
     852
     853            struct catalog_info::data {
     854                data() : language("C"), locale_category("LC_MESSAGES") {}
     855                std::string language;
     856                std::string country;
     857                std::string variant;
     858                std::string encoding;
     859                std::string locale_category;
     860                std::vector<domain> domains;
     861                std::vector<std::string> paths;
     862                callback_type callback;
     863                std::vector<std::string> path_formats;
     864            };
     865
     866            catalog_info::catalog_info() : d(new catalog_info::data())
     867            {
     868            }
     869            catalog_info::~catalog_info() { delete d; }
     870            // d is never 0
     871            catalog_info::catalog_info(catalog_info const &other) : d(new catalog_info::data(*other.d))
     872            {
     873            }
     874
     875            catalog_info const &catalog_info::operator=(catalog_info const &other)
     876            {
     877                if(this != &other) {
     878                    // d is never 0
     879                    catalog_info::data *p = new catalog_info::data(*other.d);
     880                    delete d;
     881                    d=p;
     882                }
     883                return *this;
     884            }
     885
     886
     887            std::string catalog_info::language() const { return d->language; }
     888            void catalog_info::language(std::string const &v) { d->language=v; }
     889
     890            std::string catalog_info::country() const { return d->country; }
     891            void catalog_info::country(std::string const &v) { d->country=v; }
     892
     893            std::string catalog_info::variant() const { return d->variant; }
     894            void catalog_info::variant(std::string const &v) { d->variant=v; }
     895
     896            std::string catalog_info::encoding() const { return d->encoding; }
     897            void catalog_info::encoding(std::string const &v) { d->encoding=v; }
     898
     899            std::string catalog_info::locale_category() const { return d->locale_category; }
     900            void catalog_info::locale_category(std::string const &v) { d->locale_category=v; }
     901
     902            callback_type catalog_info::callback() const { return d->callback; }
     903            void catalog_info::callback(callback_type const &v) { d->callback=v; }
     904           
     905            catalog_info::domains_type catalog_info::domains() const { return d->domains; }
     906            void catalog_info::add_domain(domain const &v) { d->domains.push_back(v); }
     907
     908            std::vector<std::string> catalog_info::paths() const { return d->paths; }
     909            void catalog_info::add_path(std::string const &v) { d->paths.push_back(v); }
     910
     911            std::vector<std::string> catalog_info::path_formats() const
     912            {
     913                if(d->path_formats.empty()) {
     914                    std::vector<std::string> r;
     915                    r.push_back("{1}/{2}/{3}/{4}.mo");
     916                    return r;
     917                }
     918                return d->path_formats;
     919            }
     920            void catalog_info::add_path_format(std::string const &v) { d->path_formats.push_back(v); }
     921
     922
     923
     924
     925           
     926
    777927        } /// gnu_gettext
    778928
    779929    } // locale