1 /* 2 * Copyright 2003-2010, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _CATALOG_H_ 6 #define _CATALOG_H_ 7 8 9 #include <LocaleRoster.h> 10 #include <SupportDefs.h> 11 #include <String.h> 12 13 14 class BCatalogAddOn; 15 class BLocale; 16 class BMessage; 17 struct entry_ref; 18 19 20 class BCatalog { 21 public: 22 BCatalog(); 23 BCatalog(const char* signature, 24 const char* language = NULL, 25 uint32 fingerprint = 0); 26 virtual ~BCatalog(); 27 28 const char* GetString(const char* string, 29 const char* context = NULL, 30 const char* comment = NULL); 31 const char* GetString(uint32 id); 32 33 const char* GetNoAutoCollectString(const char* string, 34 const char* context = NULL, 35 const char* comment = NULL); 36 const char* GetNoAutoCollectString(uint32 id); 37 38 status_t GetData(const char* name, BMessage* msg); 39 status_t GetData(uint32 id, BMessage* msg); 40 41 status_t GetSignature(BString* signature); 42 status_t GetLanguage(BString* language); 43 status_t GetFingerprint(uint32* fingerprint); 44 45 status_t SetCatalog(const char* signature, 46 uint32 fingerprint); 47 48 status_t InitCheck() const; 49 int32 CountItems() const; 50 51 BCatalogAddOn* CatalogAddOn(); 52 53 protected: 54 BCatalog(const BCatalog&); 55 const BCatalog& operator= (const BCatalog&); 56 // hide assignment and copy-constructor 57 58 BCatalogAddOn* fCatalog; 59 60 private: 61 friend class BLocale; 62 friend status_t get_add_on_catalog(BCatalog*, const char*); 63 }; 64 65 66 #ifndef B_COLLECTING_CATKEYS 67 68 #ifndef B_AVOID_TRANSLATION_MACROS 69 // macros for easy catalog-access, define B_AVOID_TRANSLATION_MACROS if 70 // you don't want these (in which case you need to collect the catalog keys 71 // manually, as collectcatkeys won't do it for you): 72 73 // TODO: maybe rename this to B_TRANSLATE_DEFAULT_CONTEXT, so that 74 // B_TRANSLATE_WITH_CONTEXT() can just be called B_TRANSLATE_CONTEXT() 75 #undef B_TRANSLATE_CONTEXT 76 // In a single application, several strings (e.g. 'Ok') will be used 77 // more than once, in different contexts. 78 // As the application programmer can not know if all translations of 79 // this string will be the same for all languages, each occurrence of 80 // the string must be translated on its own. 81 // Specifying the context explicitly with each string allows the person 82 // translating a catalog to separate these different occurrences of the 83 // same string and tell which strings appears in what context of the 84 // application. 85 // In order to give the translator a useful hint, the application 86 // programmer needs to define B_TRANSLATE_CONTEXT with the context he'd 87 // like to be associated with the strings used in this specifc source file. 88 // example: 89 // #define B_TRANSLATE_CONTEXT "Folder-Window" 90 // Tip: Use a descriptive name of the class implemented in that 91 // source-file. 92 93 // Translation macros which may be used to shorten translation requests: 94 #undef B_TRANSLATE 95 #define B_TRANSLATE(string) \ 96 be_locale_roster->GetCatalog()->GetString((string), B_TRANSLATE_CONTEXT) 97 98 #undef B_TRANSLATE_WITH_CONTEXT 99 #define B_TRANSLATE_WITH_CONTEXT(string, context) \ 100 be_locale_roster->GetCatalog()->GetString((string), (context)) 101 102 #undef B_TRANSLATE_COMMENT 103 #define B_TRANSLATE_COMMENT(string, comment) \ 104 be_locale_roster->GetCatalog()->GetString((string), B_TRANSLATE_CONTEXT, \ 105 (comment)) 106 107 #undef B_TRANSLATE_ALL 108 #define B_TRANSLATE_ALL(string, context, comment) \ 109 be_locale_roster->GetCatalog()->GetString((string), (context), (comment)) 110 111 #undef B_TRANSLATE_ID 112 #define B_TRANSLATE_ID(id) \ 113 be_locale_roster->GetCatalog()->GetString((id)) 114 115 // Translation markers which can be used to mark static strings/IDs which 116 // are used as key for translation requests (at other places in the code): 117 /* example: 118 #define B_TRANSLATE_CONTEXT "MyDecentApp-Menu" 119 120 static const char *choices[] = { 121 B_TRANSLATE_MARK("left"), 122 B_TRANSLATE_MARK("right"), 123 B_TRANSLATE_MARK("up"), 124 B_TRANSLATE_MARK("down") 125 }; 126 127 void MyClass::AddChoices(BMenu *menu) { 128 for (char **ch = choices; *ch; ch++) { 129 menu->AddItem( 130 new BMenuItem( 131 B_TRANSLATE(*ch), 132 new BMessage(...) 133 ) 134 ) 135 } 136 } 137 */ 138 #undef B_TRANSLATE_MARK 139 #define B_TRANSLATE_MARK(str) \ 140 BCatalogAddOn::MarkForTranslation((str), B_TRANSLATE_CONTEXT, "") 141 142 #undef B_TRANSLATE_MARK_COMMENT 143 #define B_TRANSLATE_MARK_COMMENT(str, cmt) \ 144 BCatalogAddOn::MarkForTranslation((str), B_TRANSLATE_CONTEXT, (cmt)) 145 146 #undef B_TRANSLATE_MARK_ALL 147 #define B_TRANSLATE_MARK_ALL(str, ctx, cmt) \ 148 BCatalogAddOn::MarkForTranslation((str), (ctx), (cmt)) 149 150 #undef B_TRANSLATE_MARK_ID 151 #define B_TRANSLATE_MARK_ID(id) \ 152 BCatalogAddOn::MarkForTranslation((id)) 153 154 // Translation macros which do not let collectcatkeys try to collect the key 155 // (useful in combination with the marking macros above): 156 #undef B_TRANSLATE_NOCOLLECT 157 #define B_TRANSLATE_NOCOLLECT(str) \ 158 B_TRANSLATE(str) 159 160 #undef B_TRANSLATE_NOCOLLECT_COMMENT 161 #define B_TRANSLATE_NOCOLLECT_COMMENT(str, cmt) \ 162 B_TRANSLATE_COMMENT(str, cmt) 163 164 #undef B_TRANSLATE_NOCOLLECT_ALL 165 #define B_TRANSLATE_NOCOLLECT_ALL(str, ctx, cmt) \ 166 B_TRANSLATE_ALL(str, ctx, cmt) 167 168 #undef B_TRANSLATE_NOCOLLECT_ID 169 #define B_TRANSLATE_NOCOLLECT_ID(id) \ 170 B_TRANSLATE_ID(id) 171 172 #endif /* B_AVOID_TRANSLATION_MACROS */ 173 174 #else /* B_COLLECTING_CATKEYS */ 175 // TODO: why define them here? Since we obviously control the preprocessor, we 176 // could simply always include a certain file that defines them; this doesn't 177 // really belong into a public header. 178 179 // Translation macros used when executing collectcatkeys 180 181 #undef B_TRANSLATE_CONTEXT 182 183 #undef B_TRANSLATE 184 #define B_TRANSLATE(string) \ 185 B_CATKEY((string), B_TRANSLATE_CONTEXT) 186 187 #undef B_TRANSLATE_WITH_CONTEXT 188 #define B_TRANSLATE_WITH_CONTEXT(string, context) \ 189 B_CATKEY((string), (context)) 190 191 #undef B_TRANSLATE_COMMENT 192 #define B_TRANSLATE_COMMENT(string, comment) \ 193 B_CATKEY((string), B_TRANSLATE_CONTEXT, (comment)) 194 195 #undef B_TRANSLATE_ALL 196 #define B_TRANSLATE_ALL(string, context, comment) \ 197 B_CATKEY((string), (context), (comment)) 198 199 #undef B_TRANSLATE_ID 200 #define B_TRANSLATE_ID(id) \ 201 B_CATKEY((id)) 202 203 #undef B_TRANSLATE_MARK 204 #define B_TRANSLATE_MARK(str) \ 205 B_CATKEY((str), B_TRANSLATE_CONTEXT) 206 207 #undef B_TRANSLATE_MARK_COMMENT 208 #define B_TRANSLATE_MARK_COMMENT(str, cmt) \ 209 B_CATKEY((str), B_TRANSLATE_CONTEXT, (cmt)) 210 211 #undef B_TRANSLATE_MARK_ALL 212 #define B_TRANSLATE_MARK_ALL(str, ctx, cmt) \ 213 B_CATKEY((str), (ctx), (cmt)) 214 215 #undef B_TRANSLATE_MARK_ID 216 #define B_TRANSLATE_MARK_ID(id) \ 217 B_CATKEY((id)) 218 219 #undef B_TRANSLATE_NOCOLLECT 220 #define B_TRANSLATE_NOCOLLECT(str) \ 221 (void) 222 223 #undef B_TRANSLATE_NOCOLLECT_COMMENT 224 #define B_TRANSLATE_NOCOLLECT_COMMENT(str, cmt) \ 225 (void) 226 227 #undef B_TRANSLATE_NOCOLLECT_ALL 228 #define B_TRANSLATE_NOCOLLECT_ALL(str, ctx, cmt) \ 229 (void) 230 231 #undef B_TRANSLATE_NOCOLLECT_ID 232 #define B_TRANSLATE_NOCOLLECT_ID(id) \ 233 (void) 234 235 #endif /* B_COLLECTING_CATKEYS */ 236 237 238 /************************************************************************/ 239 // For BCatalog add-on implementations: 240 // TODO: should go into another header 241 242 class BCatalogAddOn { 243 public: 244 BCatalogAddOn(const char* signature, 245 const char* language, 246 uint32 fingerprint); 247 virtual ~BCatalogAddOn(); 248 249 virtual const char* GetString(const char* string, 250 const char* context = NULL, 251 const char* comment = NULL) = 0; 252 virtual const char* GetString(uint32 id) = 0; 253 254 status_t InitCheck() const; 255 BCatalogAddOn* Next(); 256 257 // the following could be used to localize non-textual data (e.g. 258 // icons), but these will only be implemented if there's demand for such 259 // a feature: 260 virtual bool CanHaveData() const; 261 virtual status_t GetData(const char* name, BMessage* msg); 262 virtual status_t GetData(uint32 id, BMessage* msg); 263 264 // interface for catalog-editor-app and testing apps: 265 virtual status_t SetString(const char* string, 266 const char* translated, 267 const char* context = NULL, 268 const char* comment = NULL); 269 virtual status_t SetString(int32 id, const char* translated); 270 271 virtual bool CanWriteData() const; 272 virtual status_t SetData(const char* name, BMessage* msg); 273 virtual status_t SetData(uint32 id, BMessage* msg); 274 275 virtual status_t ReadFromFile(const char* path = NULL); 276 virtual status_t ReadFromAttribute(entry_ref* appOrAddOnRef); 277 virtual status_t ReadFromResource(entry_ref* appOrAddOnRef); 278 virtual status_t WriteToFile(const char* path = NULL); 279 virtual status_t WriteToAttribute(entry_ref* appOrAddOnRef); 280 virtual status_t WriteToResource(entry_ref* appOrAddOnRef); 281 282 virtual void MakeEmpty(); 283 virtual int32 CountItems() const; 284 285 // magic marker functions which are used to mark a string/id 286 // which will be translated elsewhere in the code (where it can 287 // not be found since it is references by a variable): 288 static const char* MarkForTranslation(const char* string, 289 const char* context, const char* comment); 290 static int32 MarkForTranslation(int32 id); 291 292 void SetNext(BCatalogAddOn* next); 293 294 protected: 295 virtual void UpdateFingerprint(); 296 297 protected: 298 friend class BCatalog; 299 friend status_t get_add_on_catalog(BCatalog*, const char*); 300 301 status_t fInitCheck; 302 BString fSignature; 303 BString fLanguageName; 304 uint32 fFingerprint; 305 BCatalogAddOn* fNext; 306 }; 307 308 // every catalog-add-on should export these symbols... 309 // ...the function that instantiates a catalog for this add-on-type... 310 extern "C" 311 BCatalogAddOn *instantiate_catalog(const char *signature, 312 const char *language, uint32 fingerprint); 313 // ...the function that creates an empty catalog for this add-on-type... 314 extern "C" 315 BCatalogAddOn *create_catalog(const char *signature, 316 const char *language); 317 // ...and the priority which will be used to order the catalog-add-ons: 318 extern uint8 gCatalogAddOnPriority; 319 320 321 /* 322 * BCatalog - inlines for trivial accessors: 323 */ 324 inline status_t 325 BCatalog::GetSignature(BString *sig) 326 { 327 if (!sig) 328 return B_BAD_VALUE; 329 if (!fCatalog) 330 return B_NO_INIT; 331 *sig = fCatalog->fSignature; 332 return B_OK; 333 } 334 335 336 inline status_t 337 BCatalog::GetLanguage(BString *lang) 338 { 339 if (!lang) 340 return B_BAD_VALUE; 341 if (!fCatalog) 342 return B_NO_INIT; 343 *lang = fCatalog->fLanguageName; 344 return B_OK; 345 } 346 347 348 inline status_t 349 BCatalog::GetFingerprint(uint32 *fp) 350 { 351 if (!fp) 352 return B_BAD_VALUE; 353 if (!fCatalog) 354 return B_NO_INIT; 355 *fp = fCatalog->fFingerprint; 356 return B_OK; 357 } 358 359 360 inline const char * 361 BCatalog::GetNoAutoCollectString(const char *string, const char *context, 362 const char *comment) 363 { 364 return GetString(string, context, comment); 365 } 366 367 368 inline const char * 369 BCatalog::GetNoAutoCollectString(uint32 id) 370 { 371 return GetString(id); 372 } 373 374 375 inline status_t 376 BCatalog::InitCheck() const 377 { 378 return fCatalog 379 ? fCatalog->InitCheck() 380 : B_NO_INIT; 381 } 382 383 384 inline int32 385 BCatalog::CountItems() const 386 { 387 if (!fCatalog) 388 return 0; 389 return fCatalog->CountItems(); 390 } 391 392 393 inline BCatalogAddOn * 394 BCatalog::CatalogAddOn() 395 { 396 return fCatalog; 397 } 398 399 400 /* 401 * BCatalogAddOn - inlines for trivial accessors: 402 */ 403 inline BCatalogAddOn * 404 BCatalogAddOn::Next() 405 { 406 return fNext; 407 } 408 409 inline const char * 410 BCatalogAddOn::MarkForTranslation(const char *str, const char *ctx, 411 const char *cmt) 412 { 413 return str; 414 } 415 416 417 inline int32 418 BCatalogAddOn::MarkForTranslation(int32 id) 419 { 420 return id; 421 } 422 423 424 // TODO: does not belong here, either 425 namespace BPrivate { 426 427 428 class EditableCatalog : public BCatalog { 429 public: 430 EditableCatalog(const char* type, 431 const char* signature, 432 const char* language); 433 virtual ~EditableCatalog(); 434 435 status_t SetString(const char* string, 436 const char* translated, 437 const char* context = NULL, 438 const char* comment = NULL); 439 status_t SetString(int32 id, const char* translated); 440 441 bool CanWriteData() const; 442 status_t SetData(const char* name, BMessage* msg); 443 status_t SetData(uint32 id, BMessage* msg); 444 445 status_t ReadFromFile(const char* path = NULL); 446 status_t ReadFromAttribute(entry_ref* appOrAddOnRef); 447 status_t ReadFromResource(entry_ref* appOrAddOnRef); 448 status_t WriteToFile(const char* path = NULL); 449 status_t WriteToAttribute(entry_ref* appOrAddOnRef); 450 status_t WriteToResource(entry_ref* appOrAddOnRef); 451 452 void MakeEmpty(); 453 454 private: 455 EditableCatalog(); 456 EditableCatalog(const EditableCatalog& other); 457 const EditableCatalog& operator=(const EditableCatalog& other); 458 // hide assignment, default-, and 459 // copy-constructor 460 }; 461 462 463 } // namespace BPrivate 464 465 466 #endif /* _CATALOG_H_ */ 467