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