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 entry_ref& catalogOwner, 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 entry_ref& catalogOwner, 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( 309 const entry_ref& appOrAddOnRef); 310 virtual status_t ReadFromResource( 311 const entry_ref& appOrAddOnRef); 312 virtual status_t WriteToFile(const char* path = NULL); 313 virtual status_t WriteToAttribute( 314 const entry_ref& appOrAddOnRef); 315 virtual status_t WriteToResource( 316 const entry_ref& appOrAddOnRef); 317 318 virtual void MakeEmpty(); 319 virtual int32 CountItems() const; 320 321 // magic marker functions which are used to mark a string/id 322 // which will be translated elsewhere in the code (where it can 323 // not be found since it is references by a variable): 324 static const char* MarkForTranslation(const char* string, 325 const char* context, const char* comment); 326 static int32 MarkForTranslation(int32 id); 327 328 void SetNext(BCatalogAddOn* next); 329 330 protected: 331 virtual void UpdateFingerprint(); 332 333 protected: 334 friend class BCatalog; 335 friend status_t get_add_on_catalog(BCatalog*, const char*); 336 337 status_t fInitCheck; 338 BString fSignature; 339 BString fLanguageName; 340 uint32 fFingerprint; 341 BCatalogAddOn* fNext; 342 }; 343 344 // every catalog-add-on should export these symbols... 345 // ...the function that instantiates a catalog for this add-on-type... 346 extern "C" 347 BCatalogAddOn *instantiate_catalog(const char *signature, 348 const char *language, uint32 fingerprint); 349 // ...the function that creates an empty catalog for this add-on-type... 350 extern "C" 351 BCatalogAddOn *create_catalog(const char *signature, 352 const char *language); 353 // ...and the priority which will be used to order the catalog-add-ons: 354 extern uint8 gCatalogAddOnPriority; 355 356 357 /* 358 * BCatalog - inlines for trivial accessors: 359 */ 360 inline status_t 361 BCatalog::GetSignature(BString *sig) 362 { 363 if (!sig) 364 return B_BAD_VALUE; 365 if (!fCatalog) 366 return B_NO_INIT; 367 *sig = fCatalog->fSignature; 368 return B_OK; 369 } 370 371 372 inline status_t 373 BCatalog::GetLanguage(BString *lang) 374 { 375 if (!lang) 376 return B_BAD_VALUE; 377 if (!fCatalog) 378 return B_NO_INIT; 379 *lang = fCatalog->fLanguageName; 380 return B_OK; 381 } 382 383 384 inline status_t 385 BCatalog::GetFingerprint(uint32 *fp) 386 { 387 if (!fp) 388 return B_BAD_VALUE; 389 if (!fCatalog) 390 return B_NO_INIT; 391 *fp = fCatalog->fFingerprint; 392 return B_OK; 393 } 394 395 396 inline const char * 397 BCatalog::GetNoAutoCollectString(const char *string, const char *context, 398 const char *comment) 399 { 400 return GetString(string, context, comment); 401 } 402 403 404 inline const char * 405 BCatalog::GetNoAutoCollectString(uint32 id) 406 { 407 return GetString(id); 408 } 409 410 411 inline status_t 412 BCatalog::InitCheck() const 413 { 414 return fCatalog 415 ? fCatalog->InitCheck() 416 : B_NO_INIT; 417 } 418 419 420 inline int32 421 BCatalog::CountItems() const 422 { 423 if (!fCatalog) 424 return 0; 425 return fCatalog->CountItems(); 426 } 427 428 429 inline BCatalogAddOn * 430 BCatalog::CatalogAddOn() 431 { 432 return fCatalog; 433 } 434 435 436 /* 437 * BCatalogAddOn - inlines for trivial accessors: 438 */ 439 inline BCatalogAddOn * 440 BCatalogAddOn::Next() 441 { 442 return fNext; 443 } 444 445 inline const char * 446 BCatalogAddOn::MarkForTranslation(const char *str, 447 const char * /*ctx __attribute__ ((unused))*/, 448 const char * /*cmt __attribute__ ((unused))*/) 449 { 450 return str; 451 } 452 453 454 inline int32 455 BCatalogAddOn::MarkForTranslation(int32 id) 456 { 457 return id; 458 } 459 460 461 // TODO: does not belong here, either 462 namespace BPrivate { 463 464 465 class EditableCatalog : public BCatalog { 466 public: 467 EditableCatalog(const char* type, 468 const char* signature, 469 const char* language); 470 virtual ~EditableCatalog(); 471 472 status_t SetString(const char* string, 473 const char* translated, 474 const char* context = NULL, 475 const char* comment = NULL); 476 status_t SetString(int32 id, const char* translated); 477 478 bool CanWriteData() const; 479 status_t SetData(const char* name, BMessage* msg); 480 status_t SetData(uint32 id, BMessage* msg); 481 482 status_t ReadFromFile(const char* path = NULL); 483 status_t ReadFromAttribute( 484 const entry_ref& appOrAddOnRef); 485 status_t ReadFromResource( 486 const entry_ref& appOrAddOnRef); 487 status_t WriteToFile(const char* path = NULL); 488 status_t WriteToAttribute( 489 const entry_ref& appOrAddOnRef); 490 status_t WriteToResource( 491 const entry_ref& appOrAddOnRef); 492 493 void MakeEmpty(); 494 495 private: 496 EditableCatalog(); 497 EditableCatalog(const EditableCatalog& other); 498 const EditableCatalog& operator=(const EditableCatalog& other); 499 // hide assignment, default-, and 500 // copy-constructor 501 }; 502 503 504 } // namespace BPrivate 505 506 507 #endif /* _CATALOG_H_ */ 508