source: project/release/3/caketext/trunk/caketext.html @ 9602

Last change on this file since 9602 was 9602, checked in by rlpowell, 12 years ago

Minor documentation changes.

  • Property svn:keywords set to Id
File size: 30.7 KB
Line 
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html401/loose.dtd"><html><head><meta name="GENERATOR" content="Mole: The Scheme Source Code Digger"><title>caketext.scm Documentation</title><meta name='keywords' content=''></head><body bgcolor='#ffffff' text='#384412'  link='#11af05' vlink='#728b09'>
2<center><h1>caketext.scm Documentation</h1></center>
3<p><br>
4<!-- Table of content -->
5<p><dl>
6<p><dt><a name='tocchapt56283' href='#chapt56283'><b>Overview And Requirements</b></a><dd>
7<p><dt><a name='tocchapt4208' href='#chapt4208'><b>Definitions</b></a><dd>
8
9<dl><dt><a name='tocsect25521' href='#sect25521'><b>language-pack</b></a><dd>
10
11f:  <a name='tocfunc63126' href='#docfunc63126' style='text-decoration:none'>new-language-pack</a><br>
12</dl>
13<p><dt><a name='tocchapt43584' href='#chapt43584'><b>Setters And Accessors</b></a><dd>
14
15f:  <a name='tocfunc24821' href='#docfunc24821' style='text-decoration:none'>set-language-pack-config!</a><br>
16
17f:  <a name='tocfunc44363' href='#docfunc44363' style='text-decoration:none'>set-language-pack-configs-from-alist!</a><br>
18
19f:  <a name='tocfunc24776' href='#docfunc24776' style='text-decoration:none'>get-language-pack-config</a><br>
20
21f:  <a name='tocfunc64934' href='#docfunc64934' style='text-decoration:none'>set-language-pack-text!</a><br>
22
23f:  <a name='tocfunc18941' href='#docfunc18941' style='text-decoration:none'>set-language-pack-texts-from-alist!</a><br>
24
25f:  <a name='tocfunc64889' href='#docfunc64889' style='text-decoration:none'>get-language-pack-text</a><br>
26
27f:  <a name='tocfunc60714' href='#docfunc60714' style='text-decoration:none'>language-pack-text-exists?</a><br>
28
29f:  <a name='tocfunc64609' href='#docfunc64609' style='text-decoration:none'>get-language-pack-func</a><br>
30
31f:  <a name='tocfunc64654' href='#docfunc64654' style='text-decoration:none'>set-language-pack-func!</a><br>
32
33f:  <a name='tocfunc18661' href='#docfunc18661' style='text-decoration:none'>set-language-pack-funcs-from-alist!</a><br>
34
35f:  <a name='tocfunc49388' href='#docfunc49388' style='text-decoration:none'>remove-language-pack-func</a><br>
36<p><dt><a name='tocchapt22057' href='#chapt22057'><b>Saving And Loading</b></a><dd>
37
38f:  <a name='tocfunc34142' href='#docfunc34142' style='text-decoration:none'>load-language-pack</a><br>
39
40f:  <a name='tocfunc38754' href='#docfunc38754' style='text-decoration:none'>dump-language-pack</a><br>
41<p><dt><a name='tocchapt42856' href='#chapt42856'><b>Actual Translation</b></a><dd>
42
43f:  <a name='tocfunc45226' href='#docfunc45226' style='text-decoration:none'>caketext-translate</a><br>
44
45f:  <a name='tocfunc46059' href='#docfunc46059' style='text-decoration:none'>my-format</a><br>
46</dl>
47<hr height='5'><center><h3><a name='chapt56283' href='#tocchapt56283'>Overview And Requirements</a></h3></center>
48
49<pre>
50This egg is a Chicken Scheme port of Locale::MakeText; see
51http://search.cpan.org/dist/Locale-Maketext/lib/Locale/Maketext/TPJ13.pod
52
53If you have any problems with this egg, or would like to suggest
54changes/additions to the documentation, please e-mail
55rlpowell@digitalkingdom.org
56
57-----
58
59Differences From Locale::MakeText
60
61Because of the history behind Common Lisp's format function, which
62Scheme has inherited, we don't use the same escape sequences.
63
64We don't turn strings into code at all, because with the 2-pass
65setup I'd need to be able to get code back from format-modular,
66and I can't.  This is a possible target for future optimization,
67if this module causes performance problems.
68
69caketext can write out auto-generated language packs; nah-nah, our
70language has code/data isomorphism and yooooours doesn't!  :)
71(More to the point, all Schemes can read/write almost all Scheme
72objects on the fly; it's a basic part of the language.)
73
74-----
75
76Requirements
77
78Also because of wanting to use a CL-style format, this egg
79requires format-modular (also, format-modular has some nice
80modularity this egg takes advantage of).
81
82-----
83
84Configuration Values
85
86onmiss:         Function to run when a miss occurs on this pack.
87                Arguments passed are the language pack and the text
88                key.  No other packs are checked.  The value
89                returned is used as the translated text.
90
91auto-add:       Boolean; if true and there's a miss on this pack,
92                add the string here.  No other packs are checked.
93
94Neither of these have any kind of fall-through options because I
95couldn't think of a case where that would be useful.  If you have
96a real-world examples, please let me know.
97
98-----
99Escape Sequences
100
101We use format-modular, and the processing of escapes is done in 2
102passes.  The first pass is a regular format-modular &quot;format&quot; pass,
103and all those escapes apply and are dealt with.
104
105The second pass uses our own function escapes, which are like so:
106
107%(function[%,argument1[%,argument2...]]%)
108
109(the [...] are indicating optionality; they are not literal)
110
111Example:
112
113        &quot;This is a test string: %(test%,~A%,~A%).&quot;
114
115Given a function stored with the name 'test in the appropriate
116language pack, this would run that test function on the next two
117caketext-translate arguments, i.e. ~A and ~A, which have already
118been substituted by the first pass, and replace the whole %(...%)
119string with the results.
120
121-----
122
123Dumping And Loading
124
125At any time, the strings in a language pack can be dumped out to a
126file using dump-language-pack.  Unlike srfi-29, no attempt is made
127to decide what the file should be named; that's up to you.
128
129Also at any time, a file full of an alist of strings can be loaded
130back into a language pack using load-language-pack.  If you do so,
131it completely replaces the pack's current strings.
132
133Similarily, you can load a file full of an alist of symbols and
134function definitons to replace the function definitions of a pack.
135The performance implications of doing so are non-trivial; see the
136documentation for the load-language-pack function for
137alternatives.
138
139-----
140
141Examples
142
143A lot of examples can be found by looking at caketext-spec.scm,
144which is the test suite.  Here's an example of normal usage;
145please e-mail me (rlpowell@digitalkingdom.org) if it is
146insufficient for you.
147
148(define english-pack (new-language-pack))
149
150(set-language-pack-config! english-pack 'auto-add #t)
151
152...
153
154(output-func
155(caketext-translate english-pack #f &quot;You found ~A files.&quot; number))
156
157This will render the output unchanged; that is, at this point you
158might as well have used (format ...), except that the string has
159been stored for future translation, which is yay.
160
161...
162
163(dump-language-pack &quot;/tmp/english-strings.dump&quot;)
164
165In that file your translator will find something like this (we
166pretty-print; lucky you):
167
168((&quot;You found ~A files.&quot;
169.
170&quot;You found ~A files.&quot;))
171
172Your translator should edit that file, perhaps to look something
173like this:
174
175((&quot;You found ~A files.&quot;
176.
177&quot;You found ~A files, eh?&quot;))
178
179and saves it to a file named, say, /tmp/canadian-strings.dump
180
181After this is done, to localize your program to Canadian English
182you'd put statements like this at the top:
183
184(define canadian-pack (new-language-pack))
185
186(load-language-pack canadian-pack &quot;/tmp/canadian-strings.dump&quot; &quot;&quot;)
187
188...
189
190(output-func
191(caketext-translate english-pack #f &quot;You found ~A files.&quot; number))
192
193Given the number 5, this will output:
194
195You found 5 files, eh?
196
197-----
198
199License And Copyright
200
201This entire egg (this file, the test cases, and the documentation)
202are all explicitely placed in the public domain by me, Robin Lee
203Powell, on 10 March 2008.  If you like the software, I'd sure
204appreciate a note, or a line of thanks in your own code or
205whatever, but if you do so be sure to thank Andy Lester, the
206Locale::Maketext guy, as well, as this is basically copycat work.
207</pre><hr height='5'><center><h3><a name='chapt4208' href='#tocchapt4208'>Definitions</a></h3></center>
208
209<pre>
210</pre>
211<hr width='40%' align='center'><center><h3><a name='sect25521' href='#tocsect25521'>language-pack</a></h3></center>
212
213<pre>
214Language packs are a 4-list: hash of config vars (as symbols) to
215values, hash of func names (as symbols) to code, hash of text key
216to value, hash of text key to code.  That last is added to
217automatically after
218</pre>
219<h4><a name='docfunc63126' href='#tocfunc63126'>new-language-pack</a></h4>
220(define (new-language-pack)<i><br> ... <a href='#codefunc63126'>Full Code</a> ... )</i>
221<pre>Just returns an empty language pack.
222</pre><p><br>
223<hr height='5'><center><h3><a name='chapt43584' href='#tocchapt43584'>Setters And Accessors</a></h3></center>
224
225<pre></pre>
226<h4><a name='docfunc24821' href='#tocfunc24821'>set-language-pack-config!</a></h4>
227(define (set-language-pack-config! pack name value)<i><br> ... <a href='#codefunc24821'>Full Code</a> ... )</i>
228<pre>Sets a configuration value.  The configuration variable's name
229must be a symbol.
230</pre><p><br>
231
232<h4><a name='docfunc44363' href='#tocfunc44363'>set-language-pack-configs-from-alist!</a></h4>
233(define (set-language-pack-configs-from-alist! pack configs-alist)<i><br> ... <a href='#codefunc44363'>Full Code</a> ... )</i>
234<pre>Can be used to set all of the config variables at once from an
235alist.  Don't know why you'd want to, though.
236</pre><p><br>
237
238<h4><a name='docfunc24776' href='#tocfunc24776'>get-language-pack-config</a></h4>
239(define (get-language-pack-config pack name)<i><br> ... <a href='#codefunc24776'>Full Code</a> ... )</i>
240<pre>Gets a configuration value; #f if not found.
241</pre><p><br>
242
243<h4><a name='docfunc64934' href='#tocfunc64934'>set-language-pack-text!</a></h4>
244(define (set-language-pack-text! pack name value)<i><br> ... <a href='#codefunc64934'>Full Code</a> ... )</i>
245<pre>Manually set a text string in a caketext language pack to a
246particular translated value.  If you're using this for anything
247other than a translation UI, odds are you're doing something
248wrong; you almost certainly want to use auto-add and/or to edit
249the language pack file by hand.
250</pre><p><br>
251
252<h4><a name='docfunc18941' href='#tocfunc18941'>set-language-pack-texts-from-alist!</a></h4>
253(define (set-language-pack-texts-from-alist! pack strings-alist)<i><br> ... <a href='#codefunc18941'>Full Code</a> ... )</i>
254<pre>Used to set all of the strings at once from an alist.  Used
255internally by the load-language-pack function.
256</pre><p><br>
257
258<h4><a name='docfunc64889' href='#tocfunc64889'>get-language-pack-text</a></h4>
259(define (get-language-pack-text pack name)<i><br> ... <a href='#codefunc64889'>Full Code</a> ... )</i>
260<pre>Even more than with set-language-pack-text!, if you're using this you
261should really think carefully about what you're doing.  The
262caketext-translate function is there almost solely to get at this
263data.  Returns #f if the string is not found.
264</pre><p><br>
265
266<h4><a name='docfunc60714' href='#tocfunc60714'>language-pack-text-exists?</a></h4>
267(define (language-pack-text-exists? pack name)<i><br> ... <a href='#codefunc60714'>Full Code</a> ... )</i>
268<pre>Check for the existence of a string
269</pre><p><br>
270
271<h4><a name='docfunc64609' href='#tocfunc64609'>get-language-pack-func</a></h4>
272(define (get-language-pack-func pack name)<i><br> ... <a href='#codefunc64609'>Full Code</a> ... )</i>
273<pre>You probably shouldn't ever need to use this, as all it's going to
274return is a procedure.
275</pre><p><br>
276
277<h4><a name='docfunc64654' href='#tocfunc64654'>set-language-pack-func!</a></h4>
278(define (set-language-pack-func! pack name func)<i><br> ... <a href='#codefunc64654'>Full Code</a> ... )</i>
279<pre>Assign a function to a symbol in this pack, for future function
280substitution.  You're probably better off writing the functions
281into the pack's function file, since the dumper won't write out
282functions.
283</pre><p><br>
284
285<h4><a name='docfunc18661' href='#tocfunc18661'>set-language-pack-funcs-from-alist!</a></h4>
286(define (set-language-pack-funcs-from-alist! pack funcs-alist)<i><br> ... <a href='#codefunc18661'>Full Code</a> ... )</i>
287<pre>This function is used to set all the functions on a language pack
288at once using an alist.  Used internally by the load-language-pack
289function.
290
291The right way to do this is to use &quot;include&quot; or &quot;-prologue&quot; or
292whatever to include, at compile time, a file that has the
293functions alist in it as a simple define; say it has:
294
295(define french-funcs
296(list
297(cons 'test (lambda (a b) (conc &quot;dump-test-func: 1. &quot; a &quot; 2. &quot; b)))))
298
299then having included it, you'd run
300
301(set-language-pack-funcs-from-alist! french-pack french-funcs)
302</pre><p><br>
303
304<h4><a name='docfunc49388' href='#tocfunc49388'>remove-language-pack-func</a></h4>
305(define (remove-language-pack-func pack name)<i><br> ... <a href='#codefunc49388'>Full Code</a> ... )</i>
306<pre>Un-define a translation function.
307</pre><p><br>
308<hr height='5'><center><h3><a name='chapt22057' href='#tocchapt22057'>Saving And Loading</a></h3></center>
309
310<pre></pre>
311<h4><a name='docfunc34142' href='#tocfunc34142'>load-language-pack</a></h4>
312(define (load-language-pack pack text-file-name func-file-name)<i><br> ... <a href='#codefunc34142'>Full Code</a> ... )</i>
313<pre>This function takes a pack (which should already be defined with
314new-language-pack) some file names.  text-file-name should contain
315an alist of strings and their translations.  func-file-name should
316contain an alist of function names and function bodies.  Because
317of the way read works, no quoting is required, so, examples:
318
319Strings:
320
321((&quot;This is a test string for dumping.&quot; &quot;This is a test string for dumping, eh?&quot;))
322
323Functions:
324
325((test (lambda (a b) (conc &quot;dump-test-func: 1. &quot; a &quot; 2. &quot; b))))
326
327I reccomend that you *not* use the func-file-name argument in any
328application where perfomance is important.  Use of this argument
329means an eval call, which may mean startup costs for a full Scheme
330interpreter.  The right way to do this is to use &quot;include&quot; or
331&quot;-prologue&quot; or whatever to include, at compile time, a file that
332has the functions alist in it as a simple define; say it has:
333
334(define french-funcs
335(list
336(cons 'test (lambda (a b) (conc &quot;dump-test-func: 1. &quot; a &quot; 2. &quot; b)))))
337
338then having included it, you'd run
339
340(set-language-pack-funcs-from-alist! french-pack french-funcs)
341</pre><p><br>
342
343<h4><a name='docfunc38754' href='#tocfunc38754'>dump-language-pack</a></h4>
344(define (dump-language-pack pack text-file-name)<i><br> ... <a href='#codefunc38754'>Full Code</a> ... )</i><p><br>
345<hr height='5'><center><h3><a name='chapt42856' href='#tocchapt42856'>Actual Translation</a></h3></center>
346
347<pre></pre>
348<h4><a name='docfunc45226' href='#tocfunc45226'>caketext-translate</a></h4>
349(define (caketext-translate lpack-list port format-string . args)<i><br> ... <a href='#codefunc45226'>Full Code</a> ... )</i>
350<pre>This function does the actual translation.  It takes the same
351arguments as format-modular's make-format-function's output,
352except the first one, which is a list of language packs in order
353of descending specificity.  They are checked in order, so place
354the most-specific one first.
355</pre><p><br>
356
357<h4><a name='docfunc46059' href='#tocfunc46059'>my-format</a></h4>
358(define (my-format lpack-list port format-string args)<i><br> ... <a href='#codefunc46059'>Full Code</a> ... )</i>
359<pre>The purpose of this function is to deal with function substitution
360in the format strings.
361
362This gets a bit complicated.  What we do is we run the string
363through format-modular as per normal, and save that output.  Then,
364in a seperate pass, we run the result through format-modular set
365up to know about our escapes, %(, %, and %), and no others.  We
366use our escapes to save the starting points of each of those.
367
368After that, we take the output of the second run and process the
369string bits in question using the positions we saved.  The first
370bit is the function, and the rest are (string) arguments to it.
371
372This function gets given the lpack-list that caketext-translate
373gets. It should walk that list as necessary to find functions it
374needs.
375
376FIXME: Optimization: Skip format calls if no ~ and/or % found.
377OTOH, if there *aren't* those characters, this means passing
378through the string at least once more, so skip this for now,
379pending need/benchmarking.
380</pre><p><br>
381<center><h1>Code</h1></center>
382
383<h4><a name='codefunc24821' href='#docfunc24821'>set-language-pack-config!</a></h4>
384<i><a href='#tocfunc24821'>Index</a></i><br>
385
386<pre>Sets a configuration value.  The configuration variable's name
387must be a symbol.
388</pre>
389<pre>(define (set-language-pack-config! pack name value)
390  (cond
391    [(symbol? name)
392     (hash-table-set! (language-pack-configs pack) name value)]
393    [else #f]))
394
395</pre>
396<h4><a name='codefunc44363' href='#docfunc44363'>set-language-pack-configs-from-alist!</a></h4>
397<i><a href='#tocfunc44363'>Index</a></i><br>
398
399<pre>Can be used to set all of the config variables at once from an
400alist.  Don't know why you'd want to, though.
401</pre>
402<pre>(define (set-language-pack-configs-from-alist! pack configs-alist)
403  (language-pack-configs-set!
404    pack
405    (alist-&gt;hash-table configs-alist eqv? hash-by-identity)))
406
407</pre>
408<h4><a name='codefunc24776' href='#docfunc24776'>get-language-pack-config</a></h4>
409<i><a href='#tocfunc24776'>Index</a></i><br>
410
411<pre>Gets a configuration value; #f if not found.
412</pre>
413<pre>(define (get-language-pack-config pack name)
414  (and
415    (hash-table-exists? (language-pack-configs pack) name)
416    (hash-table-ref (language-pack-configs pack) name)))
417
418</pre>
419<h4><a name='codefunc64934' href='#docfunc64934'>set-language-pack-text!</a></h4>
420<i><a href='#tocfunc64934'>Index</a></i><br>
421
422<pre>Manually set a text string in a caketext language pack to a
423particular translated value.  If you're using this for anything
424other than a translation UI, odds are you're doing something
425wrong; you almost certainly want to use auto-add and/or to edit
426the language pack file by hand.
427</pre>
428<pre>(define (set-language-pack-text! pack name value)
429  (hash-table-set! (language-pack-strings pack) name value))
430
431</pre>
432<h4><a name='codefunc18941' href='#docfunc18941'>set-language-pack-texts-from-alist!</a></h4>
433<i><a href='#tocfunc18941'>Index</a></i><br>
434
435<pre>Used to set all of the strings at once from an alist.  Used
436internally by the load-language-pack function.
437</pre>
438<pre>(define (set-language-pack-texts-from-alist! pack strings-alist)
439  (language-pack-strings-set!
440    pack
441    (alist-&gt;hash-table strings-alist string= string-hash)))
442
443</pre>
444<h4><a name='codefunc64889' href='#docfunc64889'>get-language-pack-text</a></h4>
445<i><a href='#tocfunc64889'>Index</a></i><br>
446
447<pre>Even more than with set-language-pack-text!, if you're using this you
448should really think carefully about what you're doing.  The
449caketext-translate function is there almost solely to get at this
450data.  Returns #f if the string is not found.
451</pre>
452<pre>(define (get-language-pack-text pack name)
453  (and
454    (hash-table-exists? (language-pack-strings pack) name)
455    (hash-table-ref (language-pack-strings pack) name)))
456</pre>
457<h4><a name='codefunc60714' href='#docfunc60714'>language-pack-text-exists?</a></h4>
458<i><a href='#tocfunc60714'>Index</a></i><br>
459
460<pre>Check for the existence of a string
461</pre>
462<pre>(define (language-pack-text-exists? pack name)
463  (hash-table-exists? (language-pack-strings pack) name))
464
465</pre>
466<h4><a name='codefunc64609' href='#docfunc64609'>get-language-pack-func</a></h4>
467<i><a href='#tocfunc64609'>Index</a></i><br>
468
469<pre>You probably shouldn't ever need to use this, as all it's going to
470return is a procedure.
471</pre>
472<pre>(define (get-language-pack-func pack name)
473  (and
474    (hash-table-exists? (language-pack-functions pack) name)
475    (hash-table-ref (language-pack-functions pack) name)))
476
477</pre>
478<h4><a name='codefunc64654' href='#docfunc64654'>set-language-pack-func!</a></h4>
479<i><a href='#tocfunc64654'>Index</a></i><br>
480
481<pre>Assign a function to a symbol in this pack, for future function
482substitution.  You're probably better off writing the functions
483into the pack's function file, since the dumper won't write out
484functions.
485</pre>
486<pre>(define (set-language-pack-func! pack name func)
487  (hash-table-set! (language-pack-functions pack) name func))
488
489</pre>
490<h4><a name='codefunc18661' href='#docfunc18661'>set-language-pack-funcs-from-alist!</a></h4>
491<i><a href='#tocfunc18661'>Index</a></i><br>
492
493<pre>This function is used to set all the functions on a language pack
494at once using an alist.  Used internally by the load-language-pack
495function.
496
497The right way to do this is to use &quot;include&quot; or &quot;-prologue&quot; or
498whatever to include, at compile time, a file that has the
499functions alist in it as a simple define; say it has:
500
501(define french-funcs
502(list
503(cons 'test (lambda (a b) (conc &quot;dump-test-func: 1. &quot; a &quot; 2. &quot; b)))))
504
505then having included it, you'd run
506
507(set-language-pack-funcs-from-alist! french-pack french-funcs)
508</pre>
509<pre>(define (set-language-pack-funcs-from-alist! pack funcs-alist)
510  (language-pack-functions-set!
511    pack
512    (alist-&gt;hash-table funcs-alist eqv? hash-by-identity)))
513
514</pre>
515<h4><a name='codefunc49388' href='#docfunc49388'>remove-language-pack-func</a></h4>
516<i><a href='#tocfunc49388'>Index</a></i><br>
517
518<pre>Un-define a translation function.
519</pre>
520<pre>(define (remove-language-pack-func pack name)
521  (hash-table-delete! (language-pack-functions pack) name))
522
523</pre>
524<h4><a name='codefunc34142' href='#docfunc34142'>load-language-pack</a></h4>
525<i><a href='#tocfunc34142'>Index</a></i><br>
526
527<pre>This function takes a pack (which should already be defined with
528new-language-pack) some file names.  text-file-name should contain
529an alist of strings and their translations.  func-file-name should
530contain an alist of function names and function bodies.  Because
531of the way read works, no quoting is required, so, examples:
532
533Strings:
534
535((&quot;This is a test string for dumping.&quot; &quot;This is a test string for dumping, eh?&quot;))
536
537Functions:
538
539((test (lambda (a b) (conc &quot;dump-test-func: 1. &quot; a &quot; 2. &quot; b))))
540
541I reccomend that you *not* use the func-file-name argument in any
542application where perfomance is important.  Use of this argument
543means an eval call, which may mean startup costs for a full Scheme
544interpreter.  The right way to do this is to use &quot;include&quot; or
545&quot;-prologue&quot; or whatever to include, at compile time, a file that
546has the functions alist in it as a simple define; say it has:
547
548(define french-funcs
549(list
550(cons 'test (lambda (a b) (conc &quot;dump-test-func: 1. &quot; a &quot; 2. &quot; b)))))
551
552then having included it, you'd run
553
554(set-language-pack-funcs-from-alist! french-pack french-funcs)
555</pre>
556<pre>(define (load-language-pack pack text-file-name func-file-name)
557  (set-language-pack-texts-from-alist!
558    pack
559    (with-input-from-file text-file-name (lambda () (read))))
560  ; Try to load the functions file if appropriate
561  (and
562    func-file-name
563    (string? func-file-name)
564    (not (string= &quot;&quot; func-file-name))
565    (set-language-pack-funcs-from-alist!
566      pack
567      ; If there's a way to do this without running eval on each
568      ; function seperately, I haven't found it.
569      (map
570        (lambda (pair)
571          ;(format #t &quot;pair: ~A.\n&quot; pair)
572          ;(format #t &quot;car: ~A.\n&quot; (car pair))
573          ;(format #t &quot;eval cdr: ~A.\n&quot; (eval (car (cdr pair)) (null-environment 5)))
574          (cons (car pair) (eval (car (cdr pair)) (null-environment 5))))
575        (with-input-from-file func-file-name (lambda () (read))))))
576  #t)
577
578</pre>
579<h4><a name='codefunc38754' href='#docfunc38754'>dump-language-pack</a></h4>
580<i><a href='#tocfunc38754'>Index</a></i><br>
581
582<pre>(define (dump-language-pack pack text-file-name)
583  (with-output-to-file text-file-name (lambda () (pretty-print (hash-table-&gt;alist (language-pack-strings pack))))))
584
585
586</pre>
587<h4><a name='codefunc45226' href='#docfunc45226'>caketext-translate</a></h4>
588<i><a href='#tocfunc45226'>Index</a></i><br>
589
590<pre>This function does the actual translation.  It takes the same
591arguments as format-modular's make-format-function's output,
592except the first one, which is a list of language packs in order
593of descending specificity.  They are checked in order, so place
594the most-specific one first.
595</pre>
596<pre>(define (caketext-translate lpack-list port format-string . args)
597  ;(format #t &quot;ct: ~A, ~A.\n&quot; lpack-list format-string)
598  ;(format #t &quot;strings: ~A.\n&quot; (hash-table-&gt;alist (language-pack-strings (car lpack-list))))
599  (letrec
600    ; Get the best (i.e. first) translated string.
601    ;
602    ; We could grab the best pack here, but we have no use for it
603    ; other than to use the string it returns, so we just grab the
604    ; first matching string we find, since get-language-pack-text
605    ; will return false if it needs to.
606    ([get-best-string
607       (lambda (l)
608         (cond
609           [(null? l) #f]
610           [else
611             (or
612               (get-language-pack-text (car l) format-string)
613               (get-best-string (cdr l)))]))]
614     [best-string
615       (get-best-string lpack-list)]
616     ; Here we find the first pack with auto-add or onmiss set.
617     [special-pack
618       (find
619         (lambda (pack)
620           (or
621             (get-language-pack-config pack 'auto-add)
622             (get-language-pack-config pack 'onmiss)))
623         lpack-list)])
624    ;(format #t &quot;best string: ~A.\n&quot; best-string)
625    ;(format #t &quot;first special: ~A.\n&quot; special-pack)
626    (cond
627      ; Is it in the strings hash?
628      [best-string
629        (my-format lpack-list port best-string args)]
630      ; Is there an auto-add/onmiss pack?
631      [special-pack
632        (cond
633          ; Is auto-add set?
634          [(get-language-pack-config special-pack 'auto-add)
635           ; Yes; copy the string in
636           (set-language-pack-text! special-pack format-string format-string)
637           (my-format lpack-list port format-string args)]
638          ; Is onmiss set?
639          [(get-language-pack-config special-pack 'onmiss)
640           ; Then run it
641           ((get-language-pack-config special-pack 'onmiss) lpack-list format-string)])]
642      [else
643        (assert #f &quot;The string was not found in this language pack list, and neither onmiss nor auto-add was set on any of the language packs in this list.&quot; lpack-list)])))
644
645</pre>
646<h4><a name='codefunc46059' href='#docfunc46059'>my-format</a></h4>
647<i><a href='#tocfunc46059'>Index</a></i><br>
648
649<pre>The purpose of this function is to deal with function substitution
650in the format strings.
651
652This gets a bit complicated.  What we do is we run the string
653through format-modular as per normal, and save that output.  Then,
654in a seperate pass, we run the result through format-modular set
655up to know about our escapes, %(, %, and %), and no others.  We
656use our escapes to save the starting points of each of those.
657
658After that, we take the output of the second run and process the
659string bits in question using the positions we saved.  The first
660bit is the function, and the rest are (string) arguments to it.
661
662This function gets given the lpack-list that caketext-translate
663gets. It should walk that list as necessary to find functions it
664needs.
665
666FIXME: Optimization: Skip format calls if no ~ and/or % found.
667OTOH, if there *aren't* those characters, this means passing
668through the string at least once more, so skip this for now,
669pending need/benchmarking.
670</pre>
671<pre>(define (my-format lpack-list port format-string args)
672
673  (define paren-bits '())
674  (define all-paren-bits '())
675  ; For each escape after the first one, subsequent string positions
676  ; will have moved 2 by the time we see them.
677  (define tosub 0)
678
679  (define (formatter-open state start params colon atsign)
680    (set! paren-bits (cons (- start tosub) paren-bits))
681    (set! tosub (+ tosub 2)))
682
683  (define (formatter-break state start params colon atsign)
684    (set! paren-bits (cons (- start tosub) paren-bits))
685    (set! tosub (+ tosub 2)))
686
687  ; Save up all the bits we've found so far and push them onto
688  ; all-paren-bits, then clear paren-bits
689  (define (formatter-close state start params colon atsign)
690    (set! paren-bits (cons (- start tosub) paren-bits))
691    (set! tosub (+ tosub 2))
692    (set! all-paren-bits (cons (reverse paren-bits) all-paren-bits))
693    (set! paren-bits '()))
694
695  (define (formatter-percent state start params colon atsign)
696    (*formatter-out-char state #\%))
697
698  (define *my-caseconv*
699    `((#\( ,(formatter-function formatter-open))
700      (#\, ,(formatter-function formatter-break))
701      (#\) ,(formatter-function formatter-close))
702      (#\% ,(formatter-function formatter-percent))))
703
704  (define *formatter-mine* `(,*my-caseconv*))
705
706  (define func-format (make-format-function #f #\% *formatter-mine*))
707
708  ; Used so we don't have to replicate format's handling of the port
709  ; argument.
710  (define no-format (make-format-function #f #f '()))
711
712  (define first-pass (apply format (cons #f (cons format-string args))))
713
714  ;(format #t &quot;First pass: ~A.\n&quot; first-pass)
715
716  (define second-pass (apply func-format (cons #f (cons first-pass args))))
717
718  ;(format #t &quot;Second pass: ~A.\n&quot; second-pass)
719
720  ; Did we find any %(...%) escapes?
721  (cond
722    ; Yes.
723    [(not (null? all-paren-bits))
724     (let
725       ([final second-pass])
726       (for-each
727         (lambda (paren-bit)
728           ;(format #t &quot;paren-bit: ~A.\n&quot; paren-bit)
729           (receive
730             (func . args)
731             ; Producer:
732             ;
733             ; Generate the actual string parts (that is, the func
734             ; name and arguments, as strings)
735             ;
736             ; We do this by mapping (e.g.) (1 3 5 7) with its cdr,
737             ; (3 5 7), to get pairs of start and end ranges for the
738             ; various paren sections
739             (apply
740               values
741               (map
742                 (lambda (start end)
743                   (string-copy final start end))
744                 paren-bit
745                 (cdr paren-bit)))
746             ; Consumer:
747             ;
748             ; Given the string parts, try to run the function in
749             ; question and put the result in the string
750             (letrec
751               ([find-func
752                  (lambda (l)
753                    (cond
754                      [(null? l) #f]
755                      [else
756                        ;(format #t &quot;find-func: ~A.\n&quot; 
757                        ;       (get-language-pack-func (car l) (string-&gt;symbol func)))
758                        (or
759                          (get-language-pack-func (car l) (string-&gt;symbol func))
760                          (find-func (cdr l)))]))]
761                [found-func
762                  (find-func lpack-list)])
763               (assert
764                 found-func
765                 (list &quot;No such function found during caketext function substitution!\n&quot; lpack-list func))
766
767               ;(format #t &quot;Bits: ~A\n&quot; paren-bit)
768
769               ;(format #t &quot;String bits, func: ~A, args: ~A\n&quot; func args)
770
771               ;(format #t &quot;Func result: ~A\n&quot; (apply found-func args))
772
773               (set! final (string-replace
774                             final
775                             (apply found-func args)
776                             (first paren-bit)
777                             (last paren-bit))))))
778         all-paren-bits)
779       ; This is just to get the port right
780       (no-format port final))]
781    ; We did not find any %(...%) escapes
782    [else (no-format port second-pass)]))
783</pre>
784<h5><a name='codeapp31903' href='#docapp31903'>define-record</a></h5>
785<i><a href='#tocapp31903'>Index</a></i><br>
786
787<pre>(define-record language-pack configs functions strings)
788
789</pre>
790<h4><a name='codefunc63126' href='#docfunc63126'>new-language-pack</a></h4>
791<i><a href='#tocfunc63126'>Index</a></i><br>
792
793<pre>Just returns an empty language pack.
794</pre>
795<pre>(define (new-language-pack)
796  (make-language-pack
797    ; Configs is a hash table by symbols
798    (make-hash-table eqv? hash-by-identity)
799    ; So is functions
800    (make-hash-table eqv? hash-by-identity)
801    ; Strings, not so much
802    (make-hash-table string= string-hash)))
803
804</pre></body></html>
Note: See TracBrowser for help on using the repository browser.