1 /************************************************************************** 2 Copyright: 3 (C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com> 4 License: See LICENSE_zlib.txt file 5 ***************************************************************************/ 6 /// \file 7 /// \author Alexander Shaduri 8 /// \ingroup hz 9 /// \weakgroup hz 10 /// @{ 11 12 #ifndef HZ_I18N_H 13 #define HZ_I18N_H 14 15 #include "hz_config.h" // feature macros 16 17 18 /** 19 \file 20 Gettext bridge for internationalization. Sort of like gettext.h, 21 but a lot simpler / lighter. 22 This file is for internal use in hz. The application is expected 23 to use gettext.h or similar mechanisms. 24 25 Note: If you are using UTF-8 to display messages in your application 26 but system locale is not UTF-8, then you need to call gettext's 27 bind_textdomain_codeset(package, "UTF-8"); 28 to enable locale -> UTF-8 conversion for translated messages. 29 */ 30 31 32 namespace hz { 33 34 35 /// \def ENABLE_NLS 36 /// Defined to 0 or 1. If 1, enable native language support. 37 /// Usually NLS can be disabled through the configure --disable-nls option. 38 #if defined ENABLE_NLS && ENABLE_NLS 39 40 #include <libintl.h> // gettext functions 41 #include <cstddef> // std::size_t 42 #include <cstring> // std::strlen, std::memcpy 43 44 45 namespace internal { 46 i18n_C_helper(const char * msg_with_context,const char * clean_msg)47 inline const char* i18n_C_helper(const char* msg_with_context, const char* clean_msg) 48 { 49 const char* res = gettext(msg_with_context); 50 return ((res == msg_with_context) ? clean_msg : res); 51 } 52 53 i18n_R_helper(const char * context,const char * clean_msg)54 inline const char* i18n_R_helper(const char* context, const char* clean_msg) 55 { 56 std::size_t context_len = std::strlen(context) + 1; 57 std::size_t clean_msg_len = std::strlen(clean_msg) + 1; 58 59 char[] msg_with_context = new char[context_len + clean_msg_len]; 60 61 std::memcpy(msg_with_context, context, context_len - 1); 62 msg_with_context[context_len - 1] = '\004'; 63 std::memcpy(msg_with_context + context_len, clean_msg, clean_msg_len); 64 65 const char* res = gettext(msg_with_context); 66 if (res == msg_with_context) { 67 delete[] msg_with_context; 68 return clean_msg; 69 } 70 delete[] msg_with_context; 71 return res; 72 } 73 74 } 75 76 77 // ------- Mark and translate 78 79 /// The main gettext function. Marks and translates at runtime. 80 /// You need to pass --keyword=HZ__ to xgettext when extracting messages. 81 #define HZ__(String) gettext(String) 82 83 /// Same as HZ__(), but specifies a context too, to e.g. 84 /// disambiguate two "Open" menu entries as ("File", "Open") and ("Printer", "Open"). 85 /// You MUST pass --keyword=C_:1c,2 to xgettext when extracting messages. 86 #define HZ_C_(Context, String) i18n_C_helper((Context "\004" String), (String)) 87 88 89 // ------- Mark only 90 91 /// The no-op marking of a string for translation. 92 /// You MUST pass --keyword=HZ_N_ to xgettext when extracting messages. 93 #define HZ_N_(String) (String) 94 95 /// Same as HZ_N_(), but accepts context too. 96 /// --keyword=HZ_NC_:1c,2 97 #define HZ_NC_(Context, String) (String) 98 99 100 // ------- Translate only 101 102 /// Translate a dynamic string. 103 #define HZ_R_(String) gettext(String) 104 105 /// Same as HZ_R_(), but accepts context too. 106 #define HZ_RC_(Context, String) i18n_R_helper((Context), (String)) 107 108 109 #else 110 111 #define HZ__(String) (String) 112 #define HZ_C_(Context, String) (String) 113 114 #define HZ_N_(String) (String) 115 #define HZ_NC_(Context, String) (String) 116 117 #define HZ_R_(String) (String) 118 #define HZ_RC_(Context, String) (String) 119 120 #endif 121 122 123 } // ns hz 124 125 126 127 #endif 128 129 /// @} 130