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

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

CHanged the name of the documentation file.

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