1 | $Revision: 1.1.1.2 $ |
---|
2 | $Date: 2002-01-21 21:38:03 $ |
---|
3 | 20 |
---|
4 | !!! README for gemtext. !!! |
---|
5 | If you think the above mentioned date is old check out |
---|
6 | http://stud.uni-sb.de/~gufl0000/atari/gemtext. You will find the latest |
---|
7 | version there. You will also find links to ftp sites from where you can |
---|
8 | download gemtext via anonymous ftp. |
---|
9 | |
---|
10 | See the file INSTALL for installing gemtext. |
---|
11 | See the file COPYING for licensing. |
---|
12 | See the file NEWS for information that is not covered by either this file |
---|
13 | or the provided manual pages. All information concerning features of |
---|
14 | gemtext included in any text file that comes along with this package is |
---|
15 | subject to change without notice! |
---|
16 | |
---|
17 | ========================================================================== |
---|
18 | |
---|
19 | This is the gemtext package. The gemtext package offers standardized i18n |
---|
20 | (internationalization) features for GEM programs. The package is intended |
---|
21 | to help programmers to internationalize their programs. If you aren't a |
---|
22 | programmer you might want to read the file ABOUT-NLS to get an idea of |
---|
23 | national language support. But you won't need gemtext. |
---|
24 | |
---|
25 | GEM is a registered trademark of Digital Research Company. GEM is mainly |
---|
26 | used on Atari computers or the various emulations available today on other |
---|
27 | platforms. You can also find the so-called PC-GEM for IBM compatible |
---|
28 | machines. If you neither use an Atari nor emulate the Atari's OS you |
---|
29 | won't need gemtext too. Still it might be a good idea to have a look at |
---|
30 | the file ABOUT-NLS. |
---|
31 | |
---|
32 | All programs and libraries contained in this package will work on their |
---|
33 | own, only depending on some executables and libraries that can be found in |
---|
34 | most Unix-like environments. Yet, you will only benefit from gemtext if |
---|
35 | you have the GNU gettext package or another internationalization package |
---|
36 | that can be compared with gettext already installed. You will find the |
---|
37 | latest version of GNU gettext at |
---|
38 | |
---|
39 | ftp://ftp.gnu.org/pub/gnu |
---|
40 | |
---|
41 | It compiles without any problems with the GNU C-compiler and MiNTLib PL46. |
---|
42 | (Well, there's a little problem: If your msgfmt keeps on crashing with a |
---|
43 | bus error try to replace the module obstack.o in your MiNTLib with the |
---|
44 | obstack.c that comes along with GNU gettext. But this is a bug in the |
---|
45 | MiNTLib and not in GNU gettext.) |
---|
46 | |
---|
47 | In the following I will refer to any computer that can make use of |
---|
48 | xgemtext as 'Atari'. I also expect you to be familiar with the C |
---|
49 | programming language and with the well known data structures and function |
---|
50 | calls that are necessary for programming GEM applications. |
---|
51 | |
---|
52 | He, she, they... Quote from the gettext info file: |
---|
53 | "In this manual, we use *he* when speaking of the programmer or |
---|
54 | maintainer, *she* when speaking of the translator, and *they* when |
---|
55 | speaking of the installers or end users of the translated program. |
---|
56 | This is only a convenience for clarifying the documentation. It |
---|
57 | is *absolutely* not meant to imply that some roles are more |
---|
58 | appropriate to males or females. Besides, as you might guess, GNU |
---|
59 | `gettext' is meant to be useful for people using computers, |
---|
60 | whatever their sex, race, religion or nationality!" |
---|
61 | |
---|
62 | Last but not least: xgemtext is written in C++. Hence you will need a |
---|
63 | C++ compiler to compile the package. GNU C++ is a good choice if you |
---|
64 | don't already have one. If you don't have the system resources to run the |
---|
65 | compiler you will have to try to get an already compiled version. Good |
---|
66 | news: The library (which is the more important part of the gemtext |
---|
67 | package) is entirely written in plain C to allow easy porting to different |
---|
68 | compiler systems. |
---|
69 | |
---|
70 | |
---|
71 | |
---|
72 | CONTENTS |
---|
73 | ======== |
---|
74 | 1. Why gemtext? |
---|
75 | 2. Alternatives for i18n |
---|
76 | 3. How to use the GNU gettext package |
---|
77 | 4. How to use the gemtext package |
---|
78 | 5. The library rintl |
---|
79 | 6. Charsets: Atari versus ISO Latin1 |
---|
80 | 7. Miscellanea |
---|
81 | |
---|
82 | |
---|
83 | |
---|
84 | 1. Why gemtext? |
---|
85 | =============== |
---|
86 | |
---|
87 | The Atari's GUI (Graphical User Interface) offers possibilities for |
---|
88 | native language support for a long time already. All necessary graphical |
---|
89 | data and text for the user interface is usually kept in a so-called |
---|
90 | resource file. For example the program foobar.app will normally look for |
---|
91 | the resource file foobar.rsc in the same directory. A programmer aware of |
---|
92 | i18n will usually provide several of these resource file each of them |
---|
93 | containing the entire data in different languages, called e. g. en.rsc, |
---|
94 | fr.rsc, it.rsc and so on. The users have to rename the particular |
---|
95 | resource file in their language to foobar.rsc and the program will still |
---|
96 | behave the same but will display its messages in the chosen language. |
---|
97 | |
---|
98 | This procedere is suboptimal for various reasons. |
---|
99 | |
---|
100 | - The most obvious one is that you keep loads of redundant data in the |
---|
101 | extra provided resouce files. Usually the strings in the resource |
---|
102 | files occupy very little space in comparison to the graphical data. |
---|
103 | |
---|
104 | - GEM applications usually expect their resource files to reside at a |
---|
105 | fixed location and to have a fixed name. Hence, in a multi-user |
---|
106 | environment you have to choose one particular language for each |
---|
107 | application or you have to keep different copies of both your resource |
---|
108 | and other data files. |
---|
109 | |
---|
110 | - Once you have decided to include your resources into your source code |
---|
111 | you have to say goodbye to the idea of i18n. |
---|
112 | |
---|
113 | - Probably the most important disadvantage of the current system is the |
---|
114 | effort you have to take in updating your applications. Whenever you |
---|
115 | have changed the tree structure in your resource file you will have to |
---|
116 | edit every other resource file immediately if you do the translation |
---|
117 | yourself. If you let somebody else do your translations she will have |
---|
118 | enormous difficulties. She will have to click through the entire |
---|
119 | resource tree, taking care not to change the data structures |
---|
120 | unwillingly, and picking out the texts that have changed. If you |
---|
121 | haven't found some trickier system it is probably easier to restart the |
---|
122 | translation from the beginning. |
---|
123 | |
---|
124 | - Whenever your application has to display a message you have to edit |
---|
125 | your resource file even for little ones like: |
---|
126 | |
---|
127 | form_alert (1, "[1][ Memory exhausted! ][ Damned ]"); |
---|
128 | |
---|
129 | Every string that has to be translated has to appear in the resource |
---|
130 | file. Considering that most resource file formats are restricted to 64 |
---|
131 | kB of length and that most GEM libraries can handle only one single |
---|
132 | resource file this is often a severe restriction in the design of the |
---|
133 | GUI. |
---|
134 | |
---|
135 | |
---|
136 | |
---|
137 | 2. Alternatives for i18n |
---|
138 | ======================== |
---|
139 | |
---|
140 | As far as programs are concerned that have to be run via a command line |
---|
141 | interpreter, there is already a portable, standardized system for message |
---|
142 | internationalization, the GNU gettext package. It offers tools for |
---|
143 | preparing all kinds of source files for i18n, tools that help both the |
---|
144 | programmer and translator to keep track of updated versions (and the |
---|
145 | maintainers, too) and it comes along with a free C library that gives |
---|
146 | access to the translated messages at runtime of the program depending on |
---|
147 | the setting of documented environment variables. |
---|
148 | |
---|
149 | You should get a copy of the GNU gettext package now. Yet, if you are too |
---|
150 | curious to download it at once, just go ahead but you might want to reread |
---|
151 | this file later as it refers to information that is available only with |
---|
152 | the GNU gettext package. |
---|
153 | |
---|
154 | The gemtext package should also be useful with NLS-packages (Native |
---|
155 | Language Support) other than GNU gettext to the degree that GNU gettext |
---|
156 | itself is compatible with other standardized packages. Yet, it has been |
---|
157 | only tested with GNU gettext as it is the only available one for Atari. |
---|
158 | |
---|
159 | |
---|
160 | |
---|
161 | 3. How to use the GNU gettext package |
---|
162 | ===================================== |
---|
163 | |
---|
164 | Forget about the whole GUI thing for a short while to get roughly an idea |
---|
165 | of programming with the GNU gettext package. We'll come back to the GUI |
---|
166 | shortly. |
---|
167 | |
---|
168 | NOTE: This section isn't meant to be an exhaustive description of the GNU |
---|
169 | gettext package. It is intended to give you an overview. If you already |
---|
170 | know the GNU gettext package you might safely skip this section. |
---|
171 | |
---|
172 | Localizing messages in a C program is very easily done. At first you need |
---|
173 | some (usually three) lines of extra code to tell the NLS library functions |
---|
174 | where to find the translated messages. Then you have to go through your |
---|
175 | code and decide for every string whether you want to get it translated or |
---|
176 | not. Strings that should be translated have to be embedded in a function |
---|
177 | call to gettext (). Thus instead of writing: |
---|
178 | |
---|
179 | printf ("Hello world!\n"); |
---|
180 | |
---|
181 | you would now write |
---|
182 | |
---|
183 | printf (gettext ("Hello world!\n")); |
---|
184 | |
---|
185 | When you're fed up with typing g-e-t-t-e-x-t over and over again you will |
---|
186 | follow the habit of most of your colleagues and |
---|
187 | |
---|
188 | #define _(s) gettext (s) |
---|
189 | |
---|
190 | well knowing that now only three extra keystrokes will make the rest of |
---|
191 | the world happy. |
---|
192 | |
---|
193 | Very handy, very easy, isn't it? Unfortunately it doesn't work if you use |
---|
194 | strings for example in initialized structures or arrays. Really? Just to |
---|
195 | make sure that you don't abandon the whole thing already, I will tell you |
---|
196 | a secret: It still works! Read the gettext info file and follow the |
---|
197 | nodes Sources -> Special cases. |
---|
198 | |
---|
199 | After having marked all translatable strings in your sources you will want |
---|
200 | to extract them for translation by |
---|
201 | |
---|
202 | xgettext *.c |
---|
203 | |
---|
204 | producing a file messages.po that contains both the original strings and |
---|
205 | space for the translations. After the file being translated you will |
---|
206 | compile it into a binary by a call to the program msgfmt. This binary |
---|
207 | file will then usually be moved to |
---|
208 | |
---|
209 | /usr/(local/)share/locale/de/LC_MESSAGES/foobar.mo |
---|
210 | |
---|
211 | provided that your program has been translated into German ('de' is the |
---|
212 | ISO-639 2-letter country code for Germany). |
---|
213 | |
---|
214 | Now you set one of the envariables LANGUAGE, LANG or LC_ALL to 'de' and |
---|
215 | recompile your sources. Your linker will then complain about the |
---|
216 | reference to 'gettext' not being resolved and you will fix the problem by |
---|
217 | linking the program with the 'intl'-library that comes along with gettext |
---|
218 | (and gemtext, too). Surprise, surprise! Your program has learned to say |
---|
219 | hello to the world in yet another language. |
---|
220 | |
---|
221 | After long and satisfying experiences with your chef-d'oeuvre you might |
---|
222 | feel that it is not enough to say hello to the world. You want to say |
---|
223 | hello to the whole universe, too. So what now? Redo the whole thing? |
---|
224 | No! You simply update your sources and extract a new messages file. |
---|
225 | Before translating the file entirely again you should have msgmerge have a |
---|
226 | glimpse at both the original and the updated file. The program msgmerge |
---|
227 | is very clever and will probably guess what you have done. It will |
---|
228 | produce a new .po file that will already contain the strings you have |
---|
229 | translated the last time. It will also not cast away those strings that |
---|
230 | you do not care to translate any longer. It will comment them out |
---|
231 | instead, thus allowing you to change your mind again later. This feature |
---|
232 | is also very handy for corrected misspellings or minor modifications to |
---|
233 | strings. If msgmerge encounters such a case it will mark the maybe |
---|
234 | incorrect translation it guesses to be best as a "fuzzy" translation. If |
---|
235 | you agree with msgmerge, simply remove the "fuzzy" comment. |
---|
236 | |
---|
237 | Well, that's it in brief. Again, if you want to understand the GNU |
---|
238 | gettext package in its whole powerfulness you can't help reading the |
---|
239 | documentation. |
---|
240 | |
---|
241 | |
---|
242 | |
---|
243 | 4. How to use the gemtext package |
---|
244 | ================================= |
---|
245 | |
---|
246 | Probably you have already seen that it's no longer necessary to put |
---|
247 | strings for alert boxes or other free strings in your resource files. |
---|
248 | What has worked with printf will work with form_alert, too. |
---|
249 | |
---|
250 | And what about resources integrated in your source files? Why not? Most |
---|
251 | resource construction sets offer the possibility to produce a C source |
---|
252 | file as output and running a simple awk script on this file will already |
---|
253 | do the whole job for you. (An important advantage of integrated resources |
---|
254 | is that you're not restricted to 64 kB anymore). |
---|
255 | |
---|
256 | But if you don't bother to write all the routines to fix adresses of |
---|
257 | object trees and so on you will estimate the help of xgemtext from this |
---|
258 | package. |
---|
259 | |
---|
260 | Running |
---|
261 | |
---|
262 | xgemtext *.rsc |
---|
263 | |
---|
264 | in your source directory will extract all strings from your resource files |
---|
265 | placing them in a file messages.c looking more or less like this: |
---|
266 | |
---|
267 | /* This file was automatically produced by xgemtext <version> */ |
---|
268 | |
---|
269 | #ifndef gettext_noop |
---|
270 | #define gettext_noop(s) (s) |
---|
271 | #endif |
---|
272 | |
---|
273 | const char* volatile nls_rsc_strings[] = { |
---|
274 | gettext_noop (" Foobar"), |
---|
275 | gettext_noop (" File"), |
---|
276 | gettext_noop (" Options"), |
---|
277 | gettext_noop (" About Foobar..."), |
---|
278 | gettext_noop (" Open"), |
---|
279 | ... /* All other strings in your resource. */ |
---|
280 | 0L |
---|
281 | } |
---|
282 | |
---|
283 | It looks like a real C source file and it actually is one. Yet, usually |
---|
284 | you will never compile it nor link the corresponding object file. But you |
---|
285 | never know... |
---|
286 | |
---|
287 | Various options control xgemtext's behavior while extracting the strings |
---|
288 | from your resources, see the manual page for detailed information. Of |
---|
289 | course it does not extract only strings from objects of type G_TEXT, |
---|
290 | G_STRING etc. but from all kinds of objects containing text, including |
---|
291 | icons and bitmaps. |
---|
292 | |
---|
293 | So what's the purpose of messages.c if not compiling? You can run |
---|
294 | it (together with your other sources) through xgettext and now you have |
---|
295 | your resource strings in a .po file that can be processed with all the |
---|
296 | tools from the GNU gettext package. |
---|
297 | |
---|
298 | |
---|
299 | |
---|
300 | 5. The library rintl |
---|
301 | ==================== |
---|
302 | |
---|
303 | Your resource file hasn't been patched by xgemtext. So, how to get the |
---|
304 | translated strings into the objects where they should go? You load your |
---|
305 | resource as usual. Now you simply have to take the habit to call |
---|
306 | gettree() for each object tree after fixing the object addresses via |
---|
307 | rsrc_gaddr(). The library function gettree() will walk thru the specified |
---|
308 | object tree replacing each pointer to a string with a pointer to the |
---|
309 | translated versions. It will also modify some members of the internal |
---|
310 | data structures (string length etc.) to the appropriate values. |
---|
311 | |
---|
312 | For simple objects this is all that you have to do. For more complicated |
---|
313 | ones translating the strings might leave your carefully designed objects a |
---|
314 | mess, beginning with menues. Remember that all string lengths may have |
---|
315 | been arbitrarily changed, resulting in objects that might hide each other |
---|
316 | or ugly looking gaps between objects that were meant to be close to each |
---|
317 | other. |
---|
318 | |
---|
319 | You will find numerous functions in the library rintl that will try to |
---|
320 | bring your objects back to a tolerable outer appearance again, each of |
---|
321 | them being called rnl<object_type>(). You will also find a function |
---|
322 | called rnltree() that will try to do the job for entire object trees. You |
---|
323 | can control the behavior of these adapt functions in numerous ways that |
---|
324 | should meet as many requirements as possible. You can specify spaces to |
---|
325 | be left between objects, margins to the tree borders, minimum widths of |
---|
326 | button objects and so on. You can also tell the functions not to walk |
---|
327 | thru the whole object tree but stopping at a certain level, thus allowing |
---|
328 | you to process different parts of your objects each with individual values |
---|
329 | for the control flags and variables. |
---|
330 | |
---|
331 | Menus usually require special treatment. rnlmenu() will usually to the |
---|
332 | job in a satisfying manner. |
---|
333 | |
---|
334 | As you might guess the result still can't be perfect. Your objects might |
---|
335 | need a little (or a whole lot of) fine tuning after being translated. |
---|
336 | Special care is also expected from the translator. She has to follow some |
---|
337 | simple rules while doing her job. You yourself, the programmer, should |
---|
338 | follow some rules when designing your object trees. The rnltree() |
---|
339 | function will work best if it finds all object children in rows and |
---|
340 | columns of constant height. This can be easily achieved by putting object |
---|
341 | children belonging logically together into visible or invisible boxes. |
---|
342 | |
---|
343 | For each library function you will find a manual page describing its |
---|
344 | functionality in detail. |
---|
345 | |
---|
346 | In the subdirectory ``example'' after building the binaries you will find |
---|
347 | a simple example program showing all this in a simple manner. Set the |
---|
348 | envariable LANGUAGE to one of the values de (German), it (Italian), fr |
---|
349 | (French), nl (Dutch), ga (Irish) or pt (portuguese) to select |
---|
350 | your preferred language. Setting the envariable to an unknown |
---|
351 | value will make the example program choose the default values |
---|
352 | ``C'' (in this case English). |
---|
353 | |
---|
354 | Select the menu entry ``International...'' to see a simple text displayed |
---|
355 | in your selected language. The entry ``Language...'' might allow you to |
---|
356 | change the language even at runtime but this depends on the existence of |
---|
357 | the putenv() function in your standard C library. If putenv() is not |
---|
358 | found the entry will be disabled. You have to change the language on the |
---|
359 | command line. |
---|
360 | |
---|
361 | In the ``Options'' menu you can follow the metamorphosis of a GEM dialog, |
---|
362 | first without any treatment, then after a call to rnltree() and finally |
---|
363 | after some additional beauty cures. See the source and the manual |
---|
364 | pages rnltree(3) and rnlpush(3) for details. |
---|
365 | |
---|
366 | |
---|
367 | |
---|
368 | 6. Charsets: Atari versus ISO Latin1 |
---|
369 | ==================================== |
---|
370 | |
---|
371 | There's a dilemma with the i18n thing. On other platforms (especially of |
---|
372 | the workstation sector) you can not only localize the language but also |
---|
373 | the charset to utilize. AFAIK there's no C library available that allows |
---|
374 | you to do so on Atari. |
---|
375 | |
---|
376 | A couple of years ago there was but one choice for a charset in the Atari |
---|
377 | sector, the charset of the Atari's built-in system font. Now more and |
---|
378 | more Atari users have switched to the universally used ISO Latin1 charset |
---|
379 | also known as iso-8859-1, especially when using a command line interpreter. |
---|
380 | If you use already internationalized GNU packages you will come across |
---|
381 | this charset, too. (Note that both ISO Latin1 and the Atari charset are |
---|
382 | intended for use with western european languages, the Atari's charset |
---|
383 | to a certain extent also for Hebrew and Greek. Hence the following refers |
---|
384 | only to those languages). |
---|
385 | |
---|
386 | I have chosen the following way: As it is very unlikely that you use an |
---|
387 | ISO Latin1 charset with GEM, the files containing the messages for the |
---|
388 | example program - which has a GUI - have to be read with the Atari |
---|
389 | charset. But these files shouldn't go into your locale directory. The |
---|
390 | whole thing is provided as an example and should stay where it is (i. e. |
---|
391 | it isn't installed). |
---|
392 | |
---|
393 | For xgemtext you have the choice. If you use an ISO Latin1 font (as you |
---|
394 | should do) simply follow the instructions in ABOUT-NLS. If you insist on |
---|
395 | using a font with an Atari codeset set the environment variable LANGUAGE |
---|
396 | (or LC_ALL or LC_xxx) to <ll>.atarist where <ll> should specify the |
---|
397 | language you want to use. When installing xgemtext the appropriate |
---|
398 | directories in your locale directory get created. They will be called |
---|
399 | <localedir>/<ll>.atarist/LC_MESSAGES. |
---|
400 | |
---|
401 | |
---|
402 | 7. Miscellanea |
---|
403 | ============== |
---|
404 | |
---|
405 | Now something that might leave you a little uneasy: The translating |
---|
406 | project relies on the original programs being written in English. Say you |
---|
407 | have written your program in Rhaeto-Romance and you want to have it |
---|
408 | translated into Irish. Well, the diligent translator from the Aron |
---|
409 | Islands is lucky enough to understand English and she probably won't |
---|
410 | bother to learn Rhaeto-Romance. The only possibility to solve the problem |
---|
411 | is to agree upon one base language and this language is English. If you |
---|
412 | have made it until here through this document I'm sure you will manage to |
---|
413 | write the messages in your sources and resources in English, too. |
---|
414 | |
---|
415 | Of course you will have to explain your users how to benefit from the new |
---|
416 | i18n features of your program. Include the file ABOUT-NLS that is part |
---|
417 | of the GNU gettext distribution. This will tell your users the |
---|
418 | necessary measures to take. |
---|
419 | |
---|
420 | You should also include a copy of the file ATARI.NLS in your sources. |
---|
421 | This file is intended to be read by translators. They will find some |
---|
422 | useful hints for translating messages for GEM programs. |
---|
423 | |
---|
424 | Note that gemtext is *not* part of the GNU project! Bug reports, |
---|
425 | comments, compliments should be sent to the author, flames and criticism |
---|
426 | to /dev/null. Please also note that everything you find in the directory |
---|
427 | intl *is* part of the GNU gettext package. Thus, any comments concerning |
---|
428 | files in this subdirectory should be directed to the maintainer of the GNU |
---|
429 | gettext package. There are some other files that consist partly or |
---|
430 | entirely of copyrighted material by the Free Software Foundation. If in |
---|
431 | doubt check the header texts. |
---|
432 | |
---|
433 | Hope you have fun with gemtext! |
---|
434 | |
---|
435 | Guido Flohr <gufl0000@stud.uni-sb.de>. |
---|