source: project/wiki/eggref/3/free-gettext @ 13621

Last change on this file since 13621 was 13621, checked in by sjamaan, 11 years ago

Move old chicken 3 eggs over to eggref/3

File size: 7.8 KB
Line 
1[[tags: egg]]
2
3free-gettext is a drop-in compatible replacement for the gettext egg
4implemented from scratch purely in Scheme and thus available with a
5BSD license.  free-gettext is also easier to use, allowing you to
6optionally load .po files directly without compiling them to .mo
7files first, and has many advanced features such as multi-language
8locales and cascaded message domains.
9
10[[toc:]]
11
12=== Introduction
13
14 '''procedure:''' (textdomain [<name>])
15 '''procedure:''' (gettext <message>)
16
17<enscript highlight=scheme>
18(use free-gettext)
19(textdomain "myapp")
20(print (gettext "Hello, world!"))
21</enscript>
22
23The above is the most basic usage and is equivalent to the GNU
24gettext module.  TEXTDOMAIN sets the name of the current "domain",
25which is the name of the message catalog (typically the name of the
26application).  With no arguments it returns the name of that domain.
27GETTEXT then fetches the translation of the message in that domain
28in the current locale (from the LANG environment variable), or
29returns the original string if the message can't be found.
30
31Apart from actually creating the message files (which you can put
32off indefinitely), that's all you need to internationalize your
33message strings.  Since every natural language string needs to be
34translated, a common idiom is to give a short name to GETTEXT:
35
36<enscript highlight=scheme>
37(define _ gettext)
38(print (_"Hello, world!"))
39</enscript>
40
41Alternately, you could make , a prefix for all message strings:
42
43<enscript highlight=scheme>
44(define-syntax unquote
45  (syntax-rules ()
46    ((_ str) (gettext str))))
47
48(print ,"Hello, world!")
49</enscript>
50
51Note that free-gettext converts all strings to utf8 internally, to
52work best with the utf8 egg and other eggs which assume Chicken
53strings are utf8.  This is a feature - all strings are consistently
54the same encoding, and you don't need to create separate message
55files for every different encoding a user might want.  Many GUI
56toolkits like Gtk also assume utf8.  On the other hand, if you want
57to output text to a non-utf8 terminal you'll need to perform the
58translation manually.
59
60==== Plural forms
61
62There is also a procedure NGETTEXT for working with plural forms:
63
64 '''procedure:''' (ngettext <msg-singular> <msg-plural> <n>)
65
66<enscript highlight=scheme>
67(format #t (ngettext "~D file removed" "~D files removed" n) n)
68</enscript>
69
70In the case of English (or if no translation is found), this applies
71the familiar logic of using the first string (singular) if N is 1,
72and the second string (plural) otherwise.  Not all languages have
73two plural forms, however, and the NGETTEXT interface allows you to
74write message files with the proper inflections for any language and
75any value of N.  The exact details of how to write a message file is
76beyond the scope of this document - see the GNU gettext
77documentation.
78
79==== Multiple Domains
80
81As with GNU gettext, the following are provided:
82
83 '''procedure:''' (dgettext <domain> <message>)
84 '''procedure:''' (dcgettext <domain> <message> <locale>)
85 '''procedure:''' (dngettext <domain> <msg-singular> <msg-plural> <n>)
86 '''procedure:''' (dcngettext <domain> <msg-singular> <msg-plural> <n> <locale>)
87
88These let you lookup messages in domains other than that specified
89by TEXTDOMAIN.  This is just a clumsy way to make up for
90inadequacies in the traditional gettext design - if you want to work
91with multiple domains, you should use the cascaded domains described
92below.
93
94 '''procedure:''' (bindtextdomain <domain> <dirname>)
95
96Override the directory to look for the given domain in.
97
98=== Cascaded Domains
99
100A major inconvenience of gettext is that it's essentially a one
101message file per application design.  Related applications,
102applications with the same menu entries, or same error messages, all
103of these need to have their own duplicated translations of all the
104same messages.
105
106free-gettext, however, lets you specify a '''list''' of strings as
107the text domain, and for any message lookup these domains are
108searched in order.
109
110<enscript highlight=scheme>
111(textdomain '("myapp" "gimp"))  ; search 1st myapp, then gimp
112(gettext "/File/Close")         ; "Close" from gimp unless overridden
113</enscript>
114
115You can thus share messages freely between applications, and
116effectively have collections of message dictionaries.
117
118=== First-class Lookup Interface
119
120One of the most common types of application to write these days is a
121web application, for which gettext is poorly suited.  Gettext
122assumes a single locale, but for any kind of server the clients may
123each have their own locale.  free-gettext therefore provides a way
124to generate separate first class gettext procedures.
125
126 '''procedure:''' (make-gettext domain [locale] [dirs] [cdir] [cached?] [lookup-cached?])
127
128DOMAIN is the same as the first argument to TEXTDOMAIN, and may be
129similarly cascaded.
130
131LOCALE is the locale, as a string or list of strings of the form
132LANG[_REGION][.ENCODING], and defaults to the LANG or LC_ALL
133environment variable, or C if neither is set.  Multiple locales are
134also searched in order, which can be useful when you have incomplete
135translations in similar languages.
136
137DIRS (again a string or list of strings) is the search path of
138directories which should hold the LOCALE/CDIR/ directories which
139contain the actual message catalogs.  This is always appended with
140the system default, e.g.  "/usr/share/locale", and may also inherit
141from the GETTEXT_PATH colon-delimited environment variable.
142
143CDIR is the catagory directory, defaulting to either the LC_CATEGORY
144environment variable or the appropriate system default
145(e.g. LC_MESSAGES).  You generally won't need to specify this.
146
147CACHED? means to cache individual messages, and defaults to #t.
148This is a natural default (GNU gettext similarly caches messages),
149but during development it can be handy to disable caching if you
150intend to edit messages while coding.
151
152LOOKUP-CACHED? means to cache the lookup dispatch generated by these
153parameters, and defaults to #t.  Thus by default multiple calls to
154MAKE-GETTEXT with the same parameters return the same object, and
155they in turn share the same message cache.
156
157MAKE-GETTEXT returns a dispatch closure with the following
158parameters:
159
160==== Procedures
161
162* (<self> 'getter) - returns a gettext-style procedure
163* (<self> 'ngetter) - returns an ngettext-style procedure
164* (<self> 'setter) - returns a procedure for manually setting message translations
165
166==== Actions
167
168* (<self> 'get <message>) => ((<self> 'getter) <message>)
169* (<self> 'nget <msg-singular> <msg-plural> <n>) => ((<self> 'ngetter) <msg-singular> <msg-plural> <n>)
170* (<self> 'set! <message> <value>) => ((<self> 'set!) <message> <value>)
171
172==== Accessors
173
174* (<self> 'locale)
175* (<self> 'domain)
176* (<self> 'dirs)
177* (<self> 'files)
178
179==== Cache management
180
181* (<self> 'use-cache <true-or-false>) - enable or disable message caching
182* (<self> 'clear) - clears the cache
183
184Note that TEXTDOMAIN actually accepts all of the same parameters as
185MAKE-GETTEXT, so that you can specify the locale and other settings
186manually if you want.
187
188=== Quick Start Tutorial
189
190* (use free-gettext)
191
192* Replace any messages with (gettext <message>) or a shortcut.
193
194* Generate the .po file with the command "xgettext myapp.scm".
195
196** If you use a shortcut its "xgettext --keyword=_ myapp.scm".
197
198** The -a parameter will extract _all_ strings.
199
200** The default output is messages.po, but the -d<name> parameter overrides this.
201
202* Make a "locale" subdirectory tree, and move the file to "./locale/en/LC_MESSAGES/myapp.po".
203
204* When testing, "export GETTEXT_PATH=./locale/" so it can access the uninstalled files.
205
206* Optionally, compile the .po with the "msgfmt" command.
207
208* Write your .setup file to install the locale files in /usr/share/locale/.
209
210=== Why Gettext?
211
212Because you need '''some''' file format for your messages, and
213gettext is widely recognized and has extensive tool support.
214
215=== Requirements
216
217[[charconv]]
218
219[[mime]]
220
221=== License
222
223BSD
224
225=== History
226
227; 1.0 : initial release
Note: See TracBrowser for help on using the repository browser.