gnu_gettext.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. //
  2. // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #ifndef BOOST_LOCLAE_GNU_GETTEXT_HPP
  7. #define BOOST_LOCLAE_GNU_GETTEXT_HPP
  8. #include <boost/locale/detail/is_supported_char.hpp>
  9. #include <boost/locale/message.hpp>
  10. #include <functional>
  11. #include <stdexcept>
  12. #include <type_traits>
  13. #include <vector>
  14. #ifdef BOOST_MSVC
  15. # pragma warning(push)
  16. # pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface...
  17. #endif
  18. namespace boost { namespace locale {
  19. /// \addtogroup message
  20. /// @{
  21. /// \brief This namespace holds classes that provide GNU Gettext message catalogs support.
  22. namespace gnu_gettext {
  23. /// \brief This structure holds all information required for creating gnu-gettext message catalogs,
  24. ///
  25. /// The user is expected to set its parameters to load these catalogs correctly. This structure
  26. /// also allows providing functions for charset conversion. Note, you need to provide them,
  27. /// so this structure is not useful for wide characters without subclassing and it will also
  28. /// ignore gettext catalogs that use a charset different from \a encoding.
  29. struct BOOST_LOCALE_DECL messages_info {
  30. messages_info() : language("C"), locale_category("LC_MESSAGES") {}
  31. std::string language; ///< The language we load the catalog for, like "ru", "en", "de"
  32. std::string country; ///< The country we load the catalog for, like "US", "IL"
  33. std::string variant; ///< Language variant, like "euro" so it would look for catalog like de_DE\@euro
  34. std::string encoding; ///< Required target charset encoding. Ignored for wide characters.
  35. ///< For narrow, should specify the correct encoding required for this catalog
  36. std::string locale_category; ///< Locale category, is set by default to LC_MESSAGES, but may be changed
  37. ///
  38. /// \brief This type represents GNU Gettext domain name for the messages.
  39. ///
  40. /// It consists of two parameters:
  41. ///
  42. /// - name - the name of the domain - used for opening the file name
  43. /// - encoding - the encoding of the keys in the sources, default - UTF-8
  44. ///
  45. struct domain {
  46. std::string name; ///< The name of the domain
  47. std::string encoding; ///< The character encoding for the domain
  48. domain() = default;
  49. /// Create a domain object from the name that can hold an encoding after symbol "/"
  50. /// such that if n is "hello/cp1255" then the name would be "hello" and "encoding" would
  51. /// be "cp1255" and if n is "hello" then the name would be the same but encoding would be
  52. /// "UTF-8"
  53. domain(const std::string& n)
  54. {
  55. const size_t pos = n.find('/');
  56. if(pos == std::string::npos) {
  57. name = n;
  58. encoding = "UTF-8";
  59. } else {
  60. name = n.substr(0, pos);
  61. encoding = n.substr(pos + 1);
  62. }
  63. }
  64. /// Check whether two objects are equivalent, only names are compared, encoding is ignored
  65. bool operator==(const domain& other) const { return name == other.name; }
  66. /// Check whether two objects are distinct, only names are compared, encoding is ignored
  67. bool operator!=(const domain& other) const { return !(*this == other); }
  68. };
  69. typedef std::vector<domain> domains_type; ///< Type that defines a list of domains that are loaded
  70. ///< The first one is the default one
  71. domains_type domains; ///< Message domains - application name, like my_app. So files named my_app.mo
  72. ///< would be loaded
  73. std::vector<std::string> paths; ///< Paths to search files in. Under MS Windows it uses encoding
  74. ///< parameter to convert them to wide OS specific paths.
  75. /// The callback for custom file system support. This callback should read the file named \a file_name
  76. /// encoded in \a encoding character set into std::vector<char> and return it.
  77. ///
  78. /// - If the file does not exist, it should return an empty vector.
  79. /// - If an error occurs during file read it should throw an exception.
  80. ///
  81. /// \note The user should support only the encodings the locales are created for. So if the user
  82. /// uses only one encoding or the file system is encoding agnostic, he may ignore the \a encoding parameter.
  83. typedef std::function<std::vector<char>(const std::string& file_name, const std::string& encoding)>
  84. callback_type;
  85. /// The callback for handling custom file systems, if it is empty, the real OS file-system
  86. /// is being used.
  87. callback_type callback;
  88. /// Get paths to folders which may contain catalog files
  89. std::vector<std::string> get_catalog_paths() const;
  90. private:
  91. /// Get a list of folder names for the language, country and variant
  92. std::vector<std::string> get_lang_folders() const;
  93. };
  94. /// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get
  95. /// information about where to read them from and uses it for character set conversion (if needed)
  96. template<typename CharType, class = boost::locale::detail::enable_if_is_supported_char<CharType>>
  97. BOOST_LOCALE_DECL message_format<CharType>* create_messages_facet(const messages_info& info);
  98. } // namespace gnu_gettext
  99. /// @}
  100. }} // namespace boost::locale
  101. #ifdef BOOST_MSVC
  102. # pragma warning(pop)
  103. #endif
  104. #endif