source: project/wiki/eggref/4/free-gettext @ 27055

Last change on this file since 27055 was 27055, checked in by Mario Domenech Goulart, 9 years ago

free-gettext (wiki): fix markup of ngettext

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