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