Index: boost/locale/generator.hpp =================================================================== --- boost/locale/generator.hpp (revision 80104) +++ boost/locale/generator.hpp (working copy) @@ -136,6 +136,27 @@ void clear_domains(); /// + /// Adds a new format for use when finding Gettext catalogs. + /// + /// Formats are the same syntax as the Boost format functions, but + /// use the following variables: + /// + /// \li {1} A path to search for catalogs in. + /// \li {2} The locale's name. + /// \li {3} The locale's category. + /// \li {4} The Gettext domain. + /// + /// For example, \c {1}/{2}/{3}/{4}.mo is the standard Gettext layout. + /// Using something like \c {1}/{2}.mo would compact the folder hierarchy. + /// + void add_path_format(std::string const &path); + + /// + /// Remove all added formats from the list + /// + void clear_path_formats(); + + /// /// Add a search path where dictionaries are looked in. /// /// \note Index: boost/locale/gnu_gettext.hpp =================================================================== --- boost/locale/gnu_gettext.hpp (revision 80104) +++ boost/locale/gnu_gettext.hpp (working copy) @@ -98,6 +98,7 @@ ///< The first one is the default one domains_type domains; ///< Message domains - application name, like my_app. So files named my_app.mo ///< would be loaded + std::vector path_formats; ///< The path formats used when finding Gettext catalogs. std::vector paths; ///< Paths to search files in. Under MS Windows it uses encoding ///< parameter to convert them to wide OS specific paths. Index: libs/locale/doc/messages_formatting.txt =================================================================== --- libs/locale/doc/messages_formatting.txt (revision 80104) +++ libs/locale/doc/messages_formatting.txt (working copy) @@ -111,6 +111,9 @@ // Specify location of dictionaries gen.add_messages_path("."); gen.add_messages_domain("hello"); + + // Use a path format like "./en_US/LC_MESSAGES/hello.mo" + gen.add_path_format("{1}/{2}/{3}/{4}.mo"); // Generate locales and imbue them to iostream locale::global(gen("")); Index: libs/locale/src/icu/icu_backend.cpp =================================================================== --- libs/locale/src/icu/icu_backend.cpp (revision 80104) +++ libs/locale/src/icu/icu_backend.cpp (working copy) @@ -31,6 +31,7 @@ icu_localization_backend(icu_localization_backend const &other) : localization_backend(), paths_(other.paths_), + path_formats_(other.path_formats_), domains_(other.domains_), locale_id_(other.locale_id_), invalid_(true), @@ -49,6 +50,8 @@ locale_id_ = value; else if(name=="message_path") paths_.push_back(value); + else if(name=="message_path_format") + path_formats_.push_back(value); else if(name=="message_application") domains_.push_back(value); else if(name=="use_ansi_encoding") @@ -62,6 +65,7 @@ locale_id_.clear(); paths_.clear(); domains_.clear(); + path_formats_.clear(); } void prepare_data() @@ -112,6 +116,7 @@ minf.encoding = data_.encoding; std::copy(domains_.begin(),domains_.end(),std::back_inserter(minf.domains)); minf.paths = paths_; + minf.path_formats = path_formats_; switch(type) { case char_facet: return std::locale(base,gnu_gettext::create_messages_facet(minf)); @@ -143,6 +148,7 @@ private: std::vector paths_; + std::vector path_formats_; std::vector domains_; std::string locale_id_; Index: libs/locale/src/posix/posix_backend.cpp =================================================================== --- libs/locale/src/posix/posix_backend.cpp (revision 80104) +++ libs/locale/src/posix/posix_backend.cpp (working copy) @@ -33,6 +33,7 @@ posix_localization_backend(posix_localization_backend const &other) : localization_backend(), paths_(other.paths_), + path_formats_(other.path_formats_), domains_(other.domains_), locale_id_(other.locale_id_), invalid_(true) @@ -50,6 +51,8 @@ locale_id_ = value; else if(name=="message_path") paths_.push_back(value); + else if(name=="message_path_format") + path_formats_.push_back(value); else if(name=="message_application") domains_.push_back(value); @@ -59,6 +62,7 @@ invalid_ = true; locale_id_.clear(); paths_.clear(); + path_formats_.clear(); domains_.clear(); } @@ -135,6 +139,7 @@ minf.encoding = inf.encoding; std::copy(domains_.begin(),domains_.end(),std::back_inserter(minf.domains)); minf.paths = paths_; + minf.path_formats = path_formats_; switch(type) { case char_facet: return std::locale(base,gnu_gettext::create_messages_facet(minf)); @@ -162,6 +167,7 @@ private: std::vector paths_; + std::vector path_formats_; std::vector domains_; std::string locale_id_; std::string real_id_; Index: libs/locale/src/shared/generator.cpp =================================================================== --- libs/locale/src/shared/generator.cpp (revision 80104) +++ libs/locale/src/shared/generator.cpp (working copy) @@ -38,6 +38,7 @@ bool use_ansi_encoding; std::vector paths; + std::vector path_formats; std::vector domains; std::map > options; @@ -96,6 +97,17 @@ { d->domains.clear(); } + + void generator::add_path_format(std::string const &format) + { + if(std::find(d->path_formats.begin(),d->path_formats.end(),format) == d->path_formats.end()) + d->path_formats.push_back(format); + } + + void generator::clear_path_formats() + { + d->path_formats.clear(); + } void generator::add_messages_path(std::string const &path) { d->paths.push_back(path); @@ -184,6 +196,8 @@ backend->set_option("message_application",d->domains[i]); for(size_t i=0;ipaths.size();i++) backend->set_option("message_path",d->paths[i]); + for(size_t i=0;ipath_formats.size();i++) + backend->set_option("message_path_format",d->path_formats[i]); } } // locale Index: libs/locale/src/shared/message.cpp =================================================================== --- libs/locale/src/shared/message.cpp (revision 80104) +++ libs/locale/src/shared/message.cpp (working copy) @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #ifdef BOOST_MSVC @@ -543,6 +544,14 @@ std::vector const &domains = inf.domains; std::vector const &search_paths = inf.paths; + // Can't do this because of backwards compatiblity. + //std::vector const &path_formats = inf.path_formats; + + // Instead, do this: + std::vector path_formats = inf.path_formats; + if(path_formats.empty()) + path_formats.push_back("{1}/{2}/{3}/{4}.mo"); + // // List of fallbacks: en_US@euro, en@euro, en_US, en. // @@ -574,8 +583,10 @@ bool found=false; for(unsigned j=0;!found && j(minf.domains)); minf.paths = paths_; + minf.path_formats = path_formats_; switch(type) { case char_facet: return std::locale(base,gnu_gettext::create_messages_facet(minf)); @@ -212,6 +217,7 @@ private: std::vector paths_; + std::vector path_formats_; std::vector domains_; std::string locale_id_; Index: libs/locale/src/win32/win_backend.cpp =================================================================== --- libs/locale/src/win32/win_backend.cpp (revision 80104) +++ libs/locale/src/win32/win_backend.cpp (working copy) @@ -31,6 +31,7 @@ winapi_localization_backend(winapi_localization_backend const &other) : localization_backend(), paths_(other.paths_), + path_formats_(other.path_formats_), domains_(other.domains_), locale_id_(other.locale_id_), invalid_(true) @@ -48,6 +49,8 @@ locale_id_ = value; else if(name=="message_path") paths_.push_back(value); + else if(name=="message_path_format") + path_formats_.push_back(value); else if(name=="message_application") domains_.push_back(value); @@ -57,6 +60,7 @@ invalid_ = true; locale_id_.clear(); paths_.clear(); + path_formats_.clear(); domains_.clear(); } @@ -113,6 +117,7 @@ minf.encoding = inf.encoding(); std::copy(domains_.begin(),domains_.end(),std::back_inserter(minf.domains)); minf.paths = paths_; + minf.path_formats = path_formats_; switch(type) { case char_facet: return std::locale(base,gnu_gettext::create_messages_facet(minf)); @@ -134,6 +139,7 @@ private: std::vector paths_; + std::vector path_formats_; std::vector domains_; std::string locale_id_; std::string real_id_; Index: libs/locale/test/test_message.cpp =================================================================== --- libs/locale/test/test_message.cpp (revision 80104) +++ libs/locale/test/test_message.cpp (working copy) @@ -344,7 +344,7 @@ g.add_messages_path(argv[1]); else g.add_messages_path("./"); - + g.add_path_format("{1}/{2}/{3}/{4}.mo"); std::string locales[] = { "he_IL.UTF-8", "he_IL.ISO8859-8" }; @@ -442,8 +442,10 @@ info.paths.push_back(argv[1]); else info.paths.push_back("./"); + // The Gettext format should be added by default. info.domains.push_back(bl::gnu_gettext::messages_info::domain("default")); + info.callback = file_loader(); std::locale l(std::locale::classic(),boost::locale::gnu_gettext::create_messages_facet(info)); @@ -465,7 +467,8 @@ g.add_messages_path(argv[1]); else g.add_messages_path("./"); - + g.add_path_format("{1}/{2}/{3}/{4}.mo"); + std::locale l = g("he_IL.UTF-8"); // narrow @@ -494,6 +497,8 @@ else g.add_messages_path("./"); + g.add_path_format("{1}/{2}/{3}/{4}.mo"); + std::locale l = g("he_IL.UTF-8"); // narrow non-UTF-8 keys