00001 /* 00002 * i18n.h 00003 * 00004 * Copyright (c) 2010 Thomas A. Vaughan 00005 * All rights reserved. 00006 * 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * * Neither the name of the <organization> nor the 00016 * names of its contributors may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY 00020 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY 00023 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00026 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * 00031 * Internationalization and localization--particularly, management of 00032 * localized strings. 00033 */ 00034 00035 #ifndef WAVEPACKET_I18N_H__ 00036 #define WAVEPACKET_I18N_H__ 00037 00038 00039 // includes -------------------------------------------------------------------- 00040 #include "nstream/nstream.h" 00041 00042 00043 namespace i18n { 00044 00045 //////////////////////////////////////////////////////////////////////////////// 00046 /// 00047 /// \ingroup general 00048 /// \defgroup i18n Internationalization (i18n) Library 00049 /// 00050 //////////////////////////////////////////////////////////////////////////////// 00051 /*@{*/ 00052 00053 00054 /// simple struct for managing a locale specification 00055 struct locale_t { 00056 // public enums 00057 enum eConstants { 00058 eLanguageOffset = 0, ///< internal use only 00059 eCountryOffset = 3, ///< internal use only 00060 eEncodingOffset = 6, ///< internal use only 00061 eBufferSize = 8, ///< use this for buffer sizes 00062 eMaxLength = 15 ///< max size of locale string 00063 }; 00064 00065 // constructor, manipulators 00066 locale_t(void) throw() { this->clear(); } 00067 void clear(void) throw() { 00068 string[eLanguageOffset] = 0; // null language 00069 string[eCountryOffset] = 0; // null country 00070 string[eEncodingOffset] = 0; // null encoding 00071 } 00072 00073 const char * getString(void) const throw() { return string; } 00074 00075 /// is this a valid locale? 00076 bool isValid(void) const throw(); 00077 00078 /// NOTE: for now we use ISO 639-1 (2-character language codes), but 00079 /// in the future this library could use ISO 639-2 (3-character 00080 /// codes) if they become common enough. Client code should use 00081 /// the locale_t::eBufferSize constant to construct character 00082 /// buffer arrays, to remain forward compatible. 00083 const char * getLanguageCode(OUT char * buffer) const throw() { 00084 ASSERT(buffer, "null"); 00085 buffer[0] = string[eLanguageOffset]; 00086 buffer[1] = string[eLanguageOffset + 1]; 00087 buffer[2] = 0; 00088 return buffer; 00089 } 00090 00091 const char * getCountryCode(OUT char * buffer) const throw() { 00092 ASSERT(buffer, "null"); 00093 buffer[0] = string[eCountryOffset]; 00094 buffer[1] = string[eCountryOffset + 1]; 00095 buffer[2] = 0; 00096 return buffer; 00097 } 00098 00099 const char * getEncoding(OUT char * buffer) const throw() { 00100 ASSERT(buffer, "null"); 00101 strcpy(buffer, string + eEncodingOffset); 00102 return buffer; 00103 } 00104 00105 // data fields 00106 char string[eMaxLength + 1]; // up to 15 characters 00107 }; 00108 00109 00110 00111 class Manager { 00112 public: 00113 // virtual destructor -------------------------------------------------- 00114 virtual ~Manager(void) throw(); 00115 00116 // i18n::Manager class interface methods ------------------------------- 00117 virtual const char * getLocale(void) const throw() = 0; 00118 00119 /// given a named stream (nstream::Stream), parses all localeInfo 00120 /// blocks relevant to this Manager's locale. 00121 virtual void parseStrings(IN nstream::Stream * stream) = 0; 00122 00123 /// recursively walks all child Entries beneath the specified Folder, 00124 /// and calls parseStrings() on each. Caller can provide a filter 00125 /// (only Entries whose full path includes the filter as a substring 00126 /// will be visited). For many projects, the locale name can be 00127 /// used as a filter (since filenames/paths will include the 00128 /// locale specifier). The caller can also (optionally) provide a 00129 /// set of valid filename extensions. 00130 /// Skips files and directories beginning with a dot ('.'). 00131 virtual void parseFolder(IN nstream::Folder * folder, 00132 IN const SetString * extensions = NULL, 00133 IN const char * filter = NULL) = 0; 00134 00135 /// retrieves the specified string. Returns null if ID is not 00136 /// recognized. 00137 virtual const char * getString(IN const char * id) const throw() = 0; 00138 00139 // static class methods (factory methods) ------------------------------ 00140 static smart_ptr<Manager> create(IN const char * locale); 00141 }; 00142 00143 00144 00145 //////////////////////////////////////////////////////////////////////////////// 00146 // 00147 // public API 00148 // 00149 //////////////////////////////////////////////////////////////////////////////// 00150 00151 /// given a locale string, of the form "xx_yy.zzzz", returns a locale_t 00152 /// - xx: 2 character language code (ISO 639-1) 00153 /// - yy: 2 character country code (ISO 3166) 00154 /// - zzzz: encoding (arbitrary length, only "UTF-8" is supported right now) 00155 void getLocaleFromString(IN const char * localeString, 00156 OUT locale_t& locale); 00157 00158 /// is this a valid country code? Based on ISO 3166 00159 bool isValidCountryCode(IN const char * country_code); 00160 00161 /// is this a valid language code? Only supports ISO 639-1 (2-character codes) 00162 /// for now. 00163 bool isValidLanguageCode(IN const char * language_code); 00164 00165 00166 /// is this a valid encoding? "valid" means "supported by this library", which 00167 /// for right now is just "UTF-8" 00168 bool isValidEncoding(IN const char * encoding); 00169 00170 00171 /// returns the string from the given Manager. If the string isn't found, a 00172 /// general (probably English) error message is returned instead. This is 00173 /// handy if a missing string isn't fatal and you don't need richer error 00174 /// messaging. This will help missing strings be identified by the user. 00175 const char * getString(IN const Manager * mgr, 00176 IN const char * id); 00177 00178 00179 /// attempt to determine the local host locale. Can return NULL! 00180 const char * getHostLocale(void); 00181 00182 00183 }; // i18n namespace 00184 00185 /*@}*/ // end of documentation block 00186 00187 #endif // WAVEPACKET_I18N_H__ 00188