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