xref: /haiku/headers/os/locale/Catalog.h (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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