gnu_gettext.hpp 6.1 KB

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