Merge lp:~ken-brotherton/boots/local2 into lp:boots
- local2
- Merge into trunk
Proposed by
KenBrotherton
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~ken-brotherton/boots/local2 |
Merge into: | lp:boots |
Diff against target: |
1026 lines (+467/-58) (has conflicts) 18 files modified
boots/api/nodes/node.py (+2/-0) boots/app/client_config.py (+20/-15) boots/lib/console.py (+22/-13) boots/lib/lingos/lingo.py (+3/-1) boots/lib/lingos/lisp/builtins.py (+4/-2) boots/lib/lingos/lisp/lexer.py (+2/-1) boots/lib/lingos/lisp/lisp.py (+4/-2) boots/lib/lingos/lisp/objects.py (+10/-8) boots/lib/lingos/lisp/parser.py (+3/-1) boots/lib/lingos/piped_sql.py (+7/-5) boots/lib/ui/components/help.py (+6/-4) boots/lib/ui/components/metacommands.py (+2/-1) boots/lib/ui/plain.py (+37/-5) boots/util.py (+27/-0) localizations/README.txt (+22/-0) localizations/boots.pot (+281/-0) localizations/createpots.sh (+3/-0) localizations/potfiles.txt (+12/-0) Text conflict in boots/app/client_config.py Text conflict in boots/lib/console.py Text conflict in boots/lib/ui/plain.py |
To merge this branch: | bzr merge lp:~ken-brotherton/boots/local2 |
Related bugs: | |
Related blueprints: |
Boots Localization
(High)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Max Goodhart | Needs Fixing | ||
Review via email: mp+20415@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
KenBrotherton (ken-brotherton) wrote : | # |
Revision history for this message
Max Goodhart (chromakode) wrote : | # |
The module boots.util appears to be missing. Did you forget to add the file?
review:
Needs Fixing
Revision history for this message
KenBrotherton (ken-brotherton) wrote : | # |
Corrected. Please rereview.
On Tue, 2010-03-02 at 00:58 +0000, Chromakode wrote:
> Review: Needs Fixing
> The module boots.util appears to be missing. Did you forget to add the file?
--
*You can find me on IM as well
bedlamoid (Yahoo,AIM, MSN)
ken.brotherton@
http://
http://
lp:~ken-brotherton/boots/local2
updated
- 92. By Ken Brotherton <kennyb@capstone14>
-
Tested Full app Localizations
Revision history for this message
Max Goodhart (chromakode) wrote : | # |
Still working on merging. I think expressions like...
return ConsoleError(
...need the sting formatting operators inside the localized strings. See:
http://
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'boots/api/nodes/node.py' |
2 | --- boots/api/nodes/node.py 2010-02-27 05:40:10 +0000 |
3 | +++ boots/api/nodes/node.py 2010-03-02 01:07:12 +0000 |
4 | @@ -25,6 +25,8 @@ |
5 | from itertools import chain, tee, repeat |
6 | from threading import Thread, Event, Lock |
7 | from types import GeneratorType |
8 | +import gettext |
9 | +gettext.install("boots",localedir=None,unicode=1) |
10 | |
11 | def catch_exceptions(iterable): |
12 | try: |
13 | |
14 | === modified file 'boots/app/client_config.py' |
15 | --- boots/app/client_config.py 2010-03-01 08:03:27 +0000 |
16 | +++ boots/app/client_config.py 2010-03-02 01:07:12 +0000 |
17 | @@ -28,6 +28,7 @@ |
18 | import optparse |
19 | import os, os.path |
20 | import info |
21 | +from boots.util import set_gettext |
22 | |
23 | def find_executable(name): |
24 | # Search algorithm adapted from os._execvpe |
25 | @@ -88,71 +89,75 @@ |
26 | action = "store", |
27 | type = "string", |
28 | dest = "command", |
29 | - help = "Execute command and exit") |
30 | + help = _("Execute command and exit")) |
31 | self._cli_parser.add_option("-D", "--database", |
32 | action = "store", |
33 | type = "string", |
34 | dest = "database", |
35 | - help = "Use database") |
36 | + help = _("Use database")) |
37 | self._cli_parser.add_option("-f", "--script", |
38 | action = "store", |
39 | type = "string", |
40 | dest = "script", |
41 | - help = "Execute commands from file and exit") |
42 | + help = _("Execute commands from file and exit")) |
43 | self._cli_parser.add_option('-l', '--lingo', |
44 | action = 'store', |
45 | type = 'string', |
46 | dest = 'lingo', |
47 | - help = 'Set the lingo to use') |
48 | + help = _('Set the lingo to use')) |
49 | self._cli_parser.add_option("-X", "--norc", |
50 | action = "store_true", |
51 | dest = "norc", |
52 | - help = "Do not read user configuration file") |
53 | + help = _("Do not read user configuration file")) |
54 | self._cli_parser.add_option("-r", "--rc", |
55 | action = "store", |
56 | type = "string", |
57 | dest = "rcfile", |
58 | - help = "Filename of user configuration file") |
59 | + help = _("Filename of user configuration file")) |
60 | self._cli_parser.add_option("-H", "--host", |
61 | action = "store", |
62 | type = "string", |
63 | dest = "host", |
64 | - help = "Connect to host") |
65 | + help = _("Connect to host")) |
66 | self._cli_parser.add_option("-p", "--port", |
67 | action = "store", |
68 | type = "int", |
69 | dest = "port", |
70 | - help = "Use port number") |
71 | + help = _("Use port number")) |
72 | self._cli_parser.add_option("-u", "--user", |
73 | action = "store", |
74 | type = "string", |
75 | dest = "username", |
76 | - help = "Login with username") |
77 | + help = _("Login with username")) |
78 | self._cli_parser.add_option("-P", "--password", |
79 | action = "store", |
80 | type = "string", |
81 | dest = "password", |
82 | +<<<<<<< TREE |
83 | help = "Connect using password. If none is given, query for password") |
84 | self._cli_parser.add_option("--pager", |
85 | action = "store", |
86 | type = "string", |
87 | dest = "pager", |
88 | help = "Pipe query results to the specified pager.") |
89 | +======= |
90 | + help = _("Connect using password. If none is given, query for password")) |
91 | +>>>>>>> MERGE-SOURCE |
92 | self._cli_parser.add_option("-t", "--terminatingchar", |
93 | action = "store", |
94 | type = "string", |
95 | dest = "terminating_char", |
96 | - help = "Specify the SQL statement terminating character. Default is ';'.") |
97 | + help = _("Specify the SQL statement terminating character. Default is ';'.")) |
98 | self._cli_parser.add_option("-F", "--historyfile", |
99 | action = "store", |
100 | type = "string", |
101 | dest = "history_file", |
102 | - help = "Specify file to save history to") |
103 | + help = _("Specify file to save history to")) |
104 | self._cli_parser.add_option("-L", "--historylength", |
105 | action = "store", |
106 | type = "int", |
107 | dest = "history_length", |
108 | - help = "Specify max history file length") |
109 | + help = _("Specify max history file length")) |
110 | |
111 | def __getitem__(self, key): |
112 | """Allows one to use the [] operator to get config items.""" |
113 | @@ -200,11 +205,11 @@ |
114 | except IOError: |
115 | if filepath != info.RCFILE: |
116 | # Only print an error if a non-default rc file was specified. |
117 | - print("rcfile {0} not found".format(filepath)) |
118 | + print("rcfile {0} "+_("not found").format(filepath)) |
119 | except SyntaxError: |
120 | - print("rcfile {0} contains a syntax error".format(filepath)) |
121 | + print("rcfile {0} "+_("contains a syntax error").format(filepath)) |
122 | except Exception as e: |
123 | - print("rcfile {0} contains an error: {1}".format(filepath, e)) |
124 | + print("rcfile {0} "+_("contains an error:")+" {1}".format(filepath, e)) |
125 | return file_dict |
126 | |
127 | def get_cli_conf(self): |
128 | |
129 | === modified file 'boots/lib/console.py' |
130 | --- boots/lib/console.py 2010-02-28 22:37:03 +0000 |
131 | +++ boots/lib/console.py 2010-03-02 01:07:12 +0000 |
132 | @@ -38,8 +38,10 @@ |
133 | from boots.lib.lingos import python |
134 | from boots.lib.lingos import piped_sql |
135 | from boots.lib.lingos import sql |
136 | +from boots.util import set_gettext |
137 | import sys |
138 | |
139 | + |
140 | # Utility function. |
141 | def iterable(obj): |
142 | """Returns True if obj is iterable; otherwise, False is returned.""" |
143 | @@ -91,20 +93,20 @@ |
144 | self.hooks["load"].call() |
145 | |
146 | def _init_help(self): |
147 | - self.help = HelpTopic("boots", "Boots Help", "Help", """ |
148 | - Boots is a flexible, extensible, and multilingual shell for working with databases. To read more about a subtopic, use `help <topic>`.""") |
149 | + self.help = HelpTopic("boots", "Boots Help", "Help", _(""" |
150 | + Boots is a flexible, extensible, and multilingual shell for working with databases. To read more about a subtopic, use `help <topic>`.""")) |
151 | |
152 | self.help["commands"] = QueryIndexTopic("commands", None, |
153 | - "List of Boots commands.", |
154 | + _("List of Boots commands."), |
155 | query=("commands",)) |
156 | |
157 | - self.help["commands"].add("\quit", "quit", "Quit boots.") |
158 | - self.help["commands"].add("\help", "help", "Show help for a topic.", """ |
159 | + self.help["commands"].add("\quit", "quit", _("Quit boots.")) |
160 | + self.help["commands"].add("\help", "help", _("Show help for a topic."), _(""" |
161 | help <topic> |
162 | - Show help for \"topic\".""") |
163 | + Show help for \"topic\".""")) |
164 | |
165 | - self.help.add("lingos", "Lingos", "Documentation for loaded lingos.", """ |
166 | - A lingo is a command language usable within Boots.""") |
167 | + self.help.add("lingos", "Lingos", _("Documentation for loaded lingos."), _(""" |
168 | + A lingo is a command language usable within Boots.""")) |
169 | |
170 | def input_complete(self, command, lingo): |
171 | if self.metacommands.get_metacommand(command) is not None: |
172 | @@ -115,6 +117,7 @@ |
173 | return command |
174 | |
175 | def run(self, command, lingo="sql"): |
176 | +<<<<<<< TREE |
177 | if not lingo in self.lingos: |
178 | return ConsoleError("Invalid lingo \"{0}\" specified.".format(lingo)) |
179 | |
180 | @@ -130,6 +133,12 @@ |
181 | result_graph.link_output(self.presenter.presenter_graph) |
182 | result_graph.start() |
183 | result_graph.run() |
184 | +======= |
185 | + if lingo in self.lingos: |
186 | + return self.lingos[lingo].execute(command) |
187 | + else: |
188 | + return ConsoleError(_("Invalid lingo")+" \"{0}\" "+_("specified.").format(lingo)) |
189 | +>>>>>>> MERGE-SOURCE |
190 | |
191 | def connect(self, host, port, database): |
192 | try: |
193 | @@ -142,7 +151,7 @@ |
194 | self.servers.append(server) |
195 | return True |
196 | else: |
197 | - error = ConsoleError("Could not connect to {0}:{1}".format(host, port)) |
198 | + error = ConsoleError(_("Could not connect to")+" {0}:{1}".format(host, port)) |
199 | self.presenter.presenter_graph.put(error) |
200 | return False |
201 | |
202 | @@ -162,7 +171,7 @@ |
203 | if self.welcome_msg and self.driver.is_interactive: |
204 | server_lines = [] |
205 | for server in self.servers: |
206 | - line_format = "{0.hostname}:{0.port} (server v{0.server_version})" |
207 | + line_format = "{0.hostname}:{0.port} ("+_("server")+" v{0.server_version})" |
208 | server_lines.append(line_format.format(server)) |
209 | server_status = "\n".join(server_lines) |
210 | |
211 | @@ -182,7 +191,7 @@ |
212 | |
213 | def quit(self, exitcode = 0): |
214 | if self.driver.is_interactive: |
215 | - self.presenter.presenter_graph.put("Boots quit.") |
216 | + self.presenter.presenter_graph.put(_("Boots quit.")) |
217 | |
218 | self.hooks["unload"].call() |
219 | self.disconnect(None, None) |
220 | @@ -200,9 +209,9 @@ |
221 | self.presenter.present(topic.format(include_index=True)) |
222 | else: |
223 | paths = ", ".join("\"{0}\"".format(" ".join(path)) for path in results) |
224 | - self.presenter.present("Did you mean: {0}?".format(paths)) |
225 | + self.presenter.present(_("Did you mean:")+" {0}?".format(paths)) |
226 | else: |
227 | - self.presenter.present("No help found for \"{0}\".".format(" ".join(query))) |
228 | + self.presenter.present(_("No help found for")+" \"{0}\".".format(" ".join(query))) |
229 | |
230 | def meta_connect(self, host=None, port=None, database=None): |
231 | if host is None: |
232 | |
233 | === modified file 'boots/lib/lingos/lingo.py' |
234 | --- boots/lib/lingos/lingo.py 2010-02-27 05:40:10 +0000 |
235 | +++ boots/lib/lingos/lingo.py 2010-03-02 01:07:12 +0000 |
236 | @@ -23,6 +23,8 @@ |
237 | |
238 | import sys |
239 | |
240 | +from boots.util import set_gettext |
241 | + |
242 | class LingoRegistry(object): |
243 | def __init__(self): |
244 | self._lingos = {} |
245 | @@ -31,7 +33,7 @@ |
246 | """Registers a lingo with the given name and interpreter. Raises a KeyError if a lingo with |
247 | name is already registered.""" |
248 | if name in self._lingos: |
249 | - raise KeyError('A lingo with name {0} already exists'.format(name)) |
250 | + raise KeyError(_('A lingo with name')+' {0} '+_('already exists').format(name)) |
251 | |
252 | self._lingos[name] = interpreter |
253 | |
254 | |
255 | === modified file 'boots/lib/lingos/lisp/builtins.py' |
256 | --- boots/lib/lingos/lisp/builtins.py 2010-02-27 05:40:10 +0000 |
257 | +++ boots/lib/lingos/lisp/builtins.py 2010-03-02 01:07:12 +0000 |
258 | @@ -22,8 +22,10 @@ |
259 | # ##### END LICENSE BLOCK ##### |
260 | |
261 | from boots.lib.lingos.lisp import objects |
262 | +from boots.util import set_gettext |
263 | import sys |
264 | |
265 | + |
266 | nil = objects.Null() |
267 | t = objects.T() |
268 | |
269 | @@ -57,7 +59,7 @@ |
270 | elif isinstance(s, objects.String): |
271 | return objects.Integer(len(s.python_string())) |
272 | else: |
273 | - raise TypeError('Expected a cons, nil or a string') |
274 | + raise TypeError(_('Expected a cons, nil or a string')) |
275 | |
276 | def elt_function(s, i): |
277 | """Returns the ith element of the sequence s.""" |
278 | @@ -66,7 +68,7 @@ |
279 | elif isinstance(s, objects.String): |
280 | return s.python_string()[i.python_integer()] |
281 | else: |
282 | - raise TypeError('Expected a cons or string') |
283 | + raise TypeError(_('Expected a cons or string')) |
284 | |
285 | def gensym_function(): |
286 | """Returns a unique symbol that will never be the same as any other symbol even if it has the same name.""" |
287 | |
288 | === modified file 'boots/lib/lingos/lisp/lexer.py' |
289 | --- boots/lib/lingos/lisp/lexer.py 2010-02-27 05:40:10 +0000 |
290 | +++ boots/lib/lingos/lisp/lexer.py 2010-03-02 01:07:12 +0000 |
291 | @@ -22,6 +22,7 @@ |
292 | # ##### END LICENSE BLOCK ##### |
293 | |
294 | import ply.lex as lex |
295 | +from boots.util import set_gettext |
296 | |
297 | tokens = ('INTEGER', 'STRING', 'SYMBOL', 'QUOTE', 'LEFT_PAREN', 'RIGHT_PAREN') |
298 | |
299 | @@ -34,7 +35,7 @@ |
300 | t_ignore = ' \t\n' |
301 | |
302 | def t_error(t): |
303 | - print('illegal character {0} found'.format(t.value)) |
304 | + print(_('illegal character {0} found').format(t.value)) |
305 | token.lexer.skip(1) |
306 | |
307 | lexer = lex.lex() |
308 | |
309 | === modified file 'boots/lib/lingos/lisp/lisp.py' |
310 | --- boots/lib/lingos/lisp/lisp.py 2010-02-27 05:40:10 +0000 |
311 | +++ boots/lib/lingos/lisp/lisp.py 2010-03-02 01:07:12 +0000 |
312 | @@ -44,9 +44,11 @@ |
313 | from boots.lib.lingos.lisp import lexer |
314 | from boots.lib.lingos.lisp import objects |
315 | from boots.lib.lingos.lisp import parser |
316 | +from boots.util import set_gettext |
317 | import re |
318 | import readline |
319 | |
320 | + |
321 | def input_complete(string): |
322 | """Returns string if string is a complete lisp expression. Otherwise, None is returned.""" |
323 | # Remove strings as they may contain parentheses. |
324 | @@ -56,7 +58,7 @@ |
325 | paren_level = left_parens - right_parens |
326 | |
327 | if paren_level < 0: |
328 | - raise SyntaxError('unmatched closing ")"') |
329 | + raise SyntaxError(_('unmatched closing ")"')) |
330 | elif paren_level > 0: |
331 | return None |
332 | else: |
333 | @@ -75,7 +77,7 @@ |
334 | if isinstance(stream, file): |
335 | stream = stream.readline |
336 | elif not callable(stream): |
337 | - raise TypeError('{0} is not a stream or a callable'.format(stream)) |
338 | + raise TypeError('{0} '+_('is not a stream or a callable').format(stream)) |
339 | # Read lines until all open lisp expressions have been closed. |
340 | while True: |
341 | line = stream() |
342 | |
343 | === modified file 'boots/lib/lingos/lisp/objects.py' |
344 | --- boots/lib/lingos/lisp/objects.py 2010-02-27 05:40:10 +0000 |
345 | +++ boots/lib/lingos/lisp/objects.py 2010-03-02 01:07:12 +0000 |
346 | @@ -25,6 +25,8 @@ |
347 | import copy |
348 | import sys |
349 | |
350 | +from boots.util import set_gettext |
351 | + |
352 | _gensym_count = 1 |
353 | _symbols = {} |
354 | |
355 | @@ -96,7 +98,7 @@ |
356 | else_expression = car(cdr(cdr(cdr(self)))) |
357 | |
358 | if then_expression is Null() or cdr(cdr(cdr(cdr(self)))) is not Null(): |
359 | - raise SyntaxError('wrong number of arguments for if special form {0}'.format(self)) |
360 | + raise SyntaxError(_('wrong number of arguments for if special form')+' {0}'.format(self)) |
361 | |
362 | if condition_expression.evaluate(environment) != Null(): |
363 | return then_expression.evaluate(environment) |
364 | @@ -115,7 +117,7 @@ |
365 | values = arguments[2::2] |
366 | |
367 | if len(symbols) != len(values) or len(symbols) == 0: |
368 | - raise SyntaxError('The number of symbols must equal the number of values and must be non-zero') |
369 | + raise SyntaxError(_('The number of symbols must equal the number of values and must be non-zero')) |
370 | |
371 | for symbol, value in zip(symbols, values): |
372 | value = value.evaluate(environment) |
373 | @@ -129,7 +131,7 @@ |
374 | else: # Handle function calls. |
375 | function = self.car.evaluate(environment) |
376 | if not isinstance(function, Lambda): |
377 | - raise TypeError('Expected a function') |
378 | + raise TypeError(_('Expected a function')) |
379 | else: |
380 | return function.call((argument.evaluate(environment) for argument in self.python_list()[1:]), environment) |
381 | |
382 | @@ -165,18 +167,18 @@ |
383 | def __getitem__(self, symbol): |
384 | """Returns the value of symbol in the environment.""" |
385 | if not isinstance(symbol, Symbol): |
386 | - raise TypeError('Expected a symbol') |
387 | + raise TypeError(_('Expected a symbol')) |
388 | |
389 | try: |
390 | return self._environment[symbol][-1] |
391 | except KeyError: |
392 | - raise KeyError('No binding for {0} exists in the current environment'.format(symbol)) |
393 | + raise KeyError(_('No binding for')+' {0} '+_('exists in the current environment').format(symbol)) |
394 | |
395 | def __setitem__(self, symbol, value): |
396 | """Sets symbol to value in the environment. If no binding for symbol exists, a binding is created at the innermost |
397 | scope.""" |
398 | if not isinstance(symbol, Symbol): |
399 | - raise TypeError('Expected a symbol') |
400 | + raise TypeError(_('Expected a symbol')) |
401 | |
402 | if symbol not in self._environment: |
403 | self._environment[symbol] = [value] |
404 | @@ -188,7 +190,7 @@ |
405 | # def __delitem__(self, symbol): |
406 | # """Removes the first binding found for symbol. Returns True if the symbol is found and False otherwise.""" |
407 | # if not isinstance(symbol, Symbol): |
408 | - # raise TypeError('Expected a symbol') |
409 | + # raise TypeError(_('Expected a symbol')) |
410 | |
411 | # if symbol in self._environment: |
412 | # self._environment[symbol].pop() |
413 | @@ -215,7 +217,7 @@ |
414 | def pop(self): |
415 | """Removes the innermost scope and returns a dictionary that corresponds to its bindings.""" |
416 | if len(self._scopes) <= 1: |
417 | - raise RuntimeError('Cannot pop the innermost scope because then no scopes would remain') |
418 | + raise RuntimeError(_('Cannot pop the innermost scope because then no scopes would remain')) |
419 | symbols = self._scopes.pop() |
420 | |
421 | for symbol in symbols: |
422 | |
423 | === modified file 'boots/lib/lingos/lisp/parser.py' |
424 | --- boots/lib/lingos/lisp/parser.py 2010-02-27 05:40:10 +0000 |
425 | +++ boots/lib/lingos/lisp/parser.py 2010-03-02 01:07:12 +0000 |
426 | @@ -24,8 +24,10 @@ |
427 | from lexer import tokens |
428 | from boots.lib.lingos.lisp import builtins |
429 | from boots.lib.lingos.lisp import objects |
430 | +from boots.util import set_gettext |
431 | import ply.yacc as yacc |
432 | |
433 | + |
434 | def p_expression_integer(p): |
435 | 'expression : INTEGER' |
436 | p[0] = objects.Integer(int(p[1])) |
437 | @@ -59,7 +61,7 @@ |
438 | p[0] = objects.Cons(p[1], p[2]) |
439 | |
440 | def p_error(p): |
441 | - print('syntax error') |
442 | + print(_('syntax error')) |
443 | |
444 | # Disable debugging output and caching of parse tables. |
445 | parser = yacc.yacc(debug = 0, write_tables = 0) |
446 | |
447 | === modified file 'boots/lib/lingos/piped_sql.py' |
448 | --- boots/lib/lingos/piped_sql.py 2010-02-27 05:54:13 +0000 |
449 | +++ boots/lib/lingos/piped_sql.py 2010-03-02 01:07:12 +0000 |
450 | @@ -26,8 +26,10 @@ |
451 | from boots.lib.ui.components.help import HelpTopic |
452 | from boots.lib.lingos import lingo |
453 | from boots.lib.lingos import sql |
454 | +from boots.util import set_gettext |
455 | import re |
456 | |
457 | + |
458 | # Set this to another node constructor to change the default constructor used for output files. |
459 | output_file_node = csv_output_file_node |
460 | |
461 | @@ -40,7 +42,7 @@ |
462 | constructor_call_re = re.compile('^(?P<name>[a-zA-Z_]+)\((?P<arguments>([^,\(\)]+,)*[^,\(\)]+)?\)$') |
463 | |
464 | class PipedSQLInterpreter(sql.SQLInterpreter): |
465 | - help = HelpTopic("pipedsql", "Piped SQL Lingo", "Enhanced SQL query language supporting pipes.") |
466 | + help = HelpTopic("pipedsql", "Piped SQL Lingo", _("Enhanced SQL query language supporting pipes.")) |
467 | |
468 | def __init__(self, *args, **kwargs): |
469 | super(PipedSQLInterpreter, self).__init__(*args, **kwargs) |
470 | @@ -52,7 +54,7 @@ |
471 | match = clause_re.match(clause_string) |
472 | |
473 | if not match: |
474 | - raise SyntaxError('{0} is not in the correct function call syntax'.format(clause_string)) |
475 | + raise SyntaxError('{0} '+_('is not in the correct function call syntax').format(clause_string)) |
476 | |
477 | constructor_call = match.group('constructor_call').strip() |
478 | output_file = match.group('output_file') |
479 | @@ -63,7 +65,7 @@ |
480 | match = constructor_call_re.match(constructor_string) |
481 | |
482 | if not match: |
483 | - raise SyntaxError('{0} is not in the correct function call syntax'.format(constructor_string)) |
484 | + raise SyntaxError('{0} '+_('is not in the correct function call syntax').format(constructor_string)) |
485 | |
486 | name = match.group('name') |
487 | arguments = match.group('arguments') |
488 | @@ -90,7 +92,7 @@ |
489 | constructor_call, output_file = self._parse_clause(clause) |
490 | except SyntaxError as e: |
491 | print(e) |
492 | - print 'error1' |
493 | + print _('error1') |
494 | return [] # Return an empty list to avoid printing None. |
495 | |
496 | try: |
497 | @@ -102,7 +104,7 @@ |
498 | # SQL is only allowed for the first node. |
499 | if sql: |
500 | if not first_node: |
501 | - raise SyntaxError('SQL is only permitted for the first clause') |
502 | + raise SyntaxError(_('SQL is only permitted for the first clause')) |
503 | |
504 | # FIXME: Add support for multiple servers here. Currently only the first server |
505 | # is used. |
506 | |
507 | === modified file 'boots/lib/ui/components/help.py' |
508 | --- boots/lib/ui/components/help.py 2010-02-27 05:54:13 +0000 |
509 | +++ boots/lib/ui/components/help.py 2010-03-02 01:07:12 +0000 |
510 | @@ -21,6 +21,8 @@ |
511 | # |
512 | # ##### END LICENSE BLOCK ##### |
513 | |
514 | +from boots.util import set_gettext |
515 | + |
516 | def issubseq(subseq, seq): |
517 | """Determines if the elements the sequence subseq form a subsequence of the sequence seq.""" |
518 | for start in range(len(seq) - len(subseq) + 1): |
519 | @@ -63,11 +65,11 @@ |
520 | template += "{0.description}" |
521 | |
522 | if self.see_also: |
523 | - template += "\n\nSee also: {0.see_also}" |
524 | + template += "\n\n"+_("See also:")+" {0.see_also}" |
525 | |
526 | output = template.format(self) |
527 | if include_index and self._subtopics: |
528 | - output += "\n--- Subtopics ---\n" + self.format_index() |
529 | + output += "\n--- "+_("Subtopics")+" ---\n" + self.format_index() |
530 | |
531 | return output |
532 | |
533 | @@ -101,7 +103,7 @@ |
534 | assert isinstance(item, str) |
535 | return query |
536 | else: |
537 | - raise TypeError('query object {0} is not a string or tuple of strings'.format(query)) |
538 | + raise TypeError(_('query object')+' {0} '+_('is not a string or tuple of strings').format(query)) |
539 | |
540 | def _ensure_key(self, key): |
541 | """Creates a new subtopic that key maps to if none exists.""" |
542 | @@ -198,4 +200,4 @@ |
543 | subtopics = self._subtopics.copy() |
544 | for path in self.root.search(self.query): |
545 | subtopics.update(self.root[path]._subtopics) |
546 | - return subtopics |
547 | \ No newline at end of file |
548 | + return subtopics |
549 | |
550 | === modified file 'boots/lib/ui/components/metacommands.py' |
551 | --- boots/lib/ui/components/metacommands.py 2010-02-27 05:54:13 +0000 |
552 | +++ boots/lib/ui/components/metacommands.py 2010-03-02 01:07:12 +0000 |
553 | @@ -22,6 +22,7 @@ |
554 | # ##### END LICENSE BLOCK ##### |
555 | |
556 | import warnings |
557 | +from boots.util import set_gettext |
558 | |
559 | def parse_metacommand(commandstring): |
560 | """This function wraps str.split() for metacommands |
561 | @@ -43,7 +44,7 @@ |
562 | # FIXME: Issue warning through the UI using ui.print |
563 | # FIXME: Determine the offending command(s) (set.intersect?) |
564 | # FIXME: Print offending commands |
565 | - warnings.warn("Conflicts between metacommands detected.") |
566 | + warnings.warn(_("Conflicts between metacommands detected.")) |
567 | self.names |= newnames |
568 | |
569 | class MetaCommands(object): |
570 | |
571 | === modified file 'boots/lib/ui/plain.py' |
572 | --- boots/lib/ui/plain.py 2010-03-01 08:21:05 +0000 |
573 | +++ boots/lib/ui/plain.py 2010-03-02 01:07:12 +0000 |
574 | @@ -28,13 +28,18 @@ |
575 | import os |
576 | import time |
577 | import readline |
578 | +<<<<<<< TREE |
579 | import subprocess |
580 | import threading |
581 | +======= |
582 | + |
583 | +>>>>>>> MERGE-SOURCE |
584 | |
585 | from boots.api.nodes.node import NodeGraph, SyncNode |
586 | from boots.lib.ui.components.help import HelpTopic |
587 | from boots.lib.ui.components.metacommands import MetaCommands, parse_metacommand |
588 | from boots.lib.ui.generic import StdinDriver, StdoutPresenter |
589 | +from boots.util import set_gettext |
590 | |
591 | class PlainUI(StdinDriver, StdoutPresenter): |
592 | """Class that provides a 'plain' UI for boots. Input is taken on stdin, |
593 | @@ -42,11 +47,11 @@ |
594 | results are printed to stdout. These results are printed as tables when |
595 | they are Server packets and as string interpretations otherwise.""" |
596 | |
597 | - help = HelpTopic("plain", "Plain UI", "Plain UI documentation.", """ |
598 | - A simple, minimal user interface for Boots.""") |
599 | + help = HelpTopic("plain", "Plain UI", _("Plain UI documentation."), _(""" |
600 | + A simple, minimal user interface for Boots.""")) |
601 | |
602 | - help.add("commands", None, "List of Plain UI commands.") |
603 | - help["commands"].add("\use", "use", "Switch to a different lingo.") |
604 | + help.add("commands", None, _("List of Plain UI commands.")) |
605 | + help["commands"].add("\use", "use", _("Switch to a different lingo.")) |
606 | |
607 | def __init__(self, console): |
608 | """Initialize a UI giving it its parent console, primary prompt, |
609 | @@ -183,6 +188,7 @@ |
610 | self.last_desc = result["info"] |
611 | if result["result"]: |
612 | self.buffer.extend(result["result"]) |
613 | +<<<<<<< TREE |
614 | elif self.buffer: |
615 | printed = False |
616 | if self.pager_command and self.console.driver.is_interactive: |
617 | @@ -201,6 +207,32 @@ |
618 | sys.stdout.write("\n") |
619 | elif result is not None: |
620 | sys.stdout.write(str(result)) |
621 | +======= |
622 | + else: |
623 | + if self.buffer: |
624 | + max_widths = map(max, [(len(column[0]), column[2]) for column in self.last_desc]) |
625 | + dashes = map(lambda x: "-"*(x+2), max_widths) |
626 | + sep_line = "+" + "+".join(dashes) + "+\n" |
627 | + current_time = time.time() |
628 | + info_line = "{0} "+_("rows in set")+" ({1:.2f} "+_("seconds")+").\n".format(len(self.buffer), |
629 | + current_time - result["begin_time"]) |
630 | + names = (column[0] for column in self.last_desc) |
631 | + sys.stdout.write(sep_line) |
632 | + sys.stdout.write(padded(names, max_widths)) |
633 | + sys.stdout.write(sep_line) |
634 | + for row in self.buffer: |
635 | + sys.stdout.write(padded(map(show_NULL, row), max_widths)) |
636 | + sys.stdout.write(sep_line) |
637 | + sys.stdout.write(info_line) |
638 | + # Reset values for next result set. |
639 | + self.buffer = [] |
640 | + else: |
641 | + if isinstance(result, Exception): |
642 | + sys.stdout.write(_("ERROR ")) |
643 | + sys.stdout.write(" :: ".join(map(str, result.args))) |
644 | + else: |
645 | + sys.stdout.write(str(result)) |
646 | +>>>>>>> MERGE-SOURCE |
647 | sys.stdout.write("\n") |
648 | |
649 | @property |
650 | @@ -216,4 +248,4 @@ |
651 | if lingo in self.console.lingos: |
652 | self.lingo = lingo |
653 | else: |
654 | - self.present("The specified lingo \"{0}\" does not exist.".format(lingo)) |
655 | + self.present(_("The specified lingo")+" \"{0}\" "+_("does not exist.").format(lingo)) |
656 | |
657 | === added file 'boots/util.py' |
658 | --- boots/util.py 1970-01-01 00:00:00 +0000 |
659 | +++ boots/util.py 2010-03-02 01:07:12 +0000 |
660 | @@ -0,0 +1,27 @@ |
661 | +# Boots Client Project |
662 | +# www.launchpad.net/boots |
663 | +# |
664 | +# ##### BEGIN LICENSE BLOCK ##### |
665 | +# |
666 | +# Copyright (C) 2009-2010 Clark Boylan, Ken Brotherton, Max Goodman, |
667 | +# Victoria Lewis, David Rosenbaum, and Andreas Turriff |
668 | +# |
669 | +# This program is free software: you can redistribute it and/or modify |
670 | +# it under the terms of the GNU General Public License as published by |
671 | +# the Free Software Foundation, either version 3 of the License, or |
672 | +# (at your option) any later version. |
673 | +# |
674 | +# This program is distributed in the hope that it will be useful, |
675 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
676 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
677 | +# GNU General Public License for more details. |
678 | +# |
679 | +# You should have received a copy of the GNU General Public License |
680 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
681 | +# |
682 | +# ##### END LICENSE BLOCK ##### |
683 | + |
684 | +import locale, gettext |
685 | +def set_gettext(mo_location='/usr/share/locale'): |
686 | + locale.setlocale(locale.LC_ALL) |
687 | + gettext.install('boots', mo_location) |
688 | |
689 | === added directory 'localizations' |
690 | === added file 'localizations/README.txt' |
691 | --- localizations/README.txt 1970-01-01 00:00:00 +0000 |
692 | +++ localizations/README.txt 2010-03-02 01:07:12 +0000 |
693 | @@ -0,0 +1,22 @@ |
694 | +========When adding code that outputs a string======== |
695 | +1) Add (if not present already) to the import section of the .py file |
696 | +#========= |
697 | +import gettext |
698 | +gettext.bindtextdomain("fslint", "/usr/share/locale") #sys default used if localedir=None |
699 | +gettext.textdomain("fslint") |
700 | +_ = gettext.gettext |
701 | +#========= |
702 | +And then wrap all output strings with _("..."). |
703 | +You should do this so that if you are using dynamicly created content, that created content is not part of the wrapped string. |
704 | +Ex: |
705 | +help = "Execute commands from file and exit") |
706 | +should be wrapped as such: |
707 | +help = _("Execute commands from file and exit")) |
708 | +Ex: |
709 | +print("rcfile {0} contains a syntax error".format(filepath)) |
710 | +should be wrapped as such: |
711 | +print(_("rcfile ")+"{0} "+_("contains a syntax error").format(filepath)) |
712 | + |
713 | +2) Add your file path to the /boots/localizations/potfiles.txt file. |
714 | +3) Generate the updated .pot file by running the /boots/localization/createpots.sh script. This will overwrite the existing pot.cms file. Any prevously generated .po .mo files can then be updated from this new file. |
715 | +4) Upload new pot file to the launchpad localization section for creation or updating of .po files. (more on this later --ken) |
716 | |
717 | === added file 'localizations/boots.pot' |
718 | --- localizations/boots.pot 1970-01-01 00:00:00 +0000 |
719 | +++ localizations/boots.pot 2010-03-02 01:07:12 +0000 |
720 | @@ -0,0 +1,281 @@ |
721 | +# SOME DESCRIPTIVE TITLE. |
722 | +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
723 | +# This file is distributed under the same license as the PACKAGE package. |
724 | +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
725 | +# |
726 | +#, fuzzy |
727 | +msgid "" |
728 | +msgstr "" |
729 | +"Project-Id-Version: PACKAGE VERSION\n" |
730 | +"Report-Msgid-Bugs-To: \n" |
731 | +"POT-Creation-Date: 2010-03-01 16:40-0800\n" |
732 | +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
733 | +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
734 | +"Language-Team: LANGUAGE <LL@li.org>\n" |
735 | +"MIME-Version: 1.0\n" |
736 | +"Content-Type: text/plain; charset=CHARSET\n" |
737 | +"Content-Transfer-Encoding: 8bit\n" |
738 | + |
739 | +#: ../boots/lib/console.py:96 |
740 | +msgid "" |
741 | +"\n" |
742 | +" Boots is a flexible, extensible, and multilingual shell for " |
743 | +"working with databases. To read more about a subtopic, use `help <topic>`." |
744 | +msgstr "" |
745 | + |
746 | +#: ../boots/lib/console.py:100 |
747 | +msgid "List of Boots commands." |
748 | +msgstr "" |
749 | + |
750 | +#: ../boots/lib/console.py:103 |
751 | +msgid "Quit boots." |
752 | +msgstr "" |
753 | + |
754 | +#: ../boots/lib/console.py:104 |
755 | +msgid "Show help for a topic." |
756 | +msgstr "" |
757 | + |
758 | +#: ../boots/lib/console.py:104 |
759 | +msgid "" |
760 | +"\n" |
761 | +" help <topic>\n" |
762 | +" Show help for \"topic\"." |
763 | +msgstr "" |
764 | + |
765 | +#: ../boots/lib/console.py:108 |
766 | +msgid "Documentation for loaded lingos." |
767 | +msgstr "" |
768 | + |
769 | +#: ../boots/lib/console.py:108 |
770 | +msgid "" |
771 | +"\n" |
772 | +" A lingo is a command language usable within Boots." |
773 | +msgstr "" |
774 | + |
775 | +#: ../boots/lib/console.py:123 |
776 | +msgid "Invalid lingo" |
777 | +msgstr "" |
778 | + |
779 | +#: ../boots/lib/console.py:123 |
780 | +msgid "specified." |
781 | +msgstr "" |
782 | + |
783 | +#: ../boots/lib/console.py:136 |
784 | +msgid "Could not connect to" |
785 | +msgstr "" |
786 | + |
787 | +#: ../boots/lib/console.py:156 |
788 | +msgid "server" |
789 | +msgstr "" |
790 | + |
791 | +#: ../boots/lib/console.py:189 |
792 | +msgid "Boots quit." |
793 | +msgstr "" |
794 | + |
795 | +#: ../boots/lib/console.py:207 |
796 | +msgid "Did you mean:" |
797 | +msgstr "" |
798 | + |
799 | +#: ../boots/lib/console.py:209 |
800 | +msgid "No help found for" |
801 | +msgstr "" |
802 | + |
803 | +#: ../boots/lib/ui/plain.py:45 |
804 | +msgid "Plain UI documentation." |
805 | +msgstr "" |
806 | + |
807 | +#: ../boots/lib/ui/plain.py:45 |
808 | +msgid "" |
809 | +"\n" |
810 | +" A simple, minimal user interface for Boots." |
811 | +msgstr "" |
812 | + |
813 | +#: ../boots/lib/ui/plain.py:48 |
814 | +msgid "List of Plain UI commands." |
815 | +msgstr "" |
816 | + |
817 | +#: ../boots/lib/ui/plain.py:49 |
818 | +msgid "Switch to a different lingo." |
819 | +msgstr "" |
820 | + |
821 | +#: ../boots/lib/ui/plain.py:156 |
822 | +msgid "rows in set" |
823 | +msgstr "" |
824 | + |
825 | +#: ../boots/lib/ui/plain.py:156 |
826 | +msgid "seconds" |
827 | +msgstr "" |
828 | + |
829 | +#: ../boots/lib/ui/plain.py:170 |
830 | +msgid "ERROR " |
831 | +msgstr "" |
832 | + |
833 | +#: ../boots/lib/ui/plain.py:189 |
834 | +msgid "The specified lingo" |
835 | +msgstr "" |
836 | + |
837 | +#: ../boots/lib/ui/plain.py:189 |
838 | +msgid "does not exist." |
839 | +msgstr "" |
840 | + |
841 | +#: ../boots/lib/ui/components/metacommands.py:47 |
842 | +msgid "Conflicts between metacommands detected." |
843 | +msgstr "" |
844 | + |
845 | +#: ../boots/lib/ui/components/help.py:68 |
846 | +msgid "See also:" |
847 | +msgstr "" |
848 | + |
849 | +#: ../boots/lib/ui/components/help.py:72 |
850 | +msgid "Subtopics" |
851 | +msgstr "" |
852 | + |
853 | +#: ../boots/lib/ui/components/help.py:106 |
854 | +msgid "query object" |
855 | +msgstr "" |
856 | + |
857 | +#: ../boots/lib/ui/components/help.py:106 |
858 | +msgid "is not a string or tuple of strings" |
859 | +msgstr "" |
860 | + |
861 | +#: ../boots/lib/lingos/lingo.py:36 |
862 | +msgid "A lingo with name" |
863 | +msgstr "" |
864 | + |
865 | +#: ../boots/lib/lingos/lingo.py:36 |
866 | +msgid "already exists" |
867 | +msgstr "" |
868 | + |
869 | +#: ../boots/lib/lingos/piped_sql.py:45 |
870 | +msgid "Enhanced SQL query language supporting pipes." |
871 | +msgstr "" |
872 | + |
873 | +#: ../boots/lib/lingos/piped_sql.py:57 ../boots/lib/lingos/piped_sql.py:68 |
874 | +msgid "is not in the correct function call syntax" |
875 | +msgstr "" |
876 | + |
877 | +#: ../boots/lib/lingos/piped_sql.py:95 |
878 | +msgid "error1" |
879 | +msgstr "" |
880 | + |
881 | +#: ../boots/lib/lingos/piped_sql.py:107 |
882 | +msgid "SQL is only permitted for the first clause" |
883 | +msgstr "" |
884 | + |
885 | +#: ../boots/lib/lingos/lisp/builtins.py:62 |
886 | +msgid "Expected a cons, nil or a string" |
887 | +msgstr "" |
888 | + |
889 | +#: ../boots/lib/lingos/lisp/builtins.py:71 |
890 | +msgid "Expected a cons or string" |
891 | +msgstr "" |
892 | + |
893 | +#: ../boots/lib/lingos/lisp/lexer.py:38 |
894 | +msgid "illegal character {0} found" |
895 | +msgstr "" |
896 | + |
897 | +#: ../boots/lib/lingos/lisp/lisp.py:61 |
898 | +msgid "unmatched closing \")\"" |
899 | +msgstr "" |
900 | + |
901 | +#: ../boots/lib/lingos/lisp/lisp.py:80 |
902 | +msgid "is not a stream or a callable" |
903 | +msgstr "" |
904 | + |
905 | +#: ../boots/lib/lingos/lisp/objects.py:101 |
906 | +msgid "wrong number of arguments for if special form" |
907 | +msgstr "" |
908 | + |
909 | +#: ../boots/lib/lingos/lisp/objects.py:120 |
910 | +msgid "" |
911 | +"The number of symbols must equal the number of values and must be non-zero" |
912 | +msgstr "" |
913 | + |
914 | +#: ../boots/lib/lingos/lisp/objects.py:134 |
915 | +msgid "Expected a function" |
916 | +msgstr "" |
917 | + |
918 | +#: ../boots/lib/lingos/lisp/objects.py:170 |
919 | +#: ../boots/lib/lingos/lisp/objects.py:181 |
920 | +msgid "Expected a symbol" |
921 | +msgstr "" |
922 | + |
923 | +#: ../boots/lib/lingos/lisp/objects.py:175 |
924 | +msgid "No binding for" |
925 | +msgstr "" |
926 | + |
927 | +#: ../boots/lib/lingos/lisp/objects.py:175 |
928 | +msgid "exists in the current environment" |
929 | +msgstr "" |
930 | + |
931 | +#: ../boots/lib/lingos/lisp/objects.py:220 |
932 | +msgid "Cannot pop the innermost scope because then no scopes would remain" |
933 | +msgstr "" |
934 | + |
935 | +#: ../boots/lib/lingos/lisp/parser.py:64 |
936 | +msgid "syntax error" |
937 | +msgstr "" |
938 | + |
939 | +#: ../boots/app/client_config.py:68 |
940 | +msgid "Execute command and exit" |
941 | +msgstr "" |
942 | + |
943 | +#: ../boots/app/client_config.py:73 |
944 | +msgid "Use database" |
945 | +msgstr "" |
946 | + |
947 | +#: ../boots/app/client_config.py:78 |
948 | +msgid "Execute commands from file and exit" |
949 | +msgstr "" |
950 | + |
951 | +#: ../boots/app/client_config.py:83 |
952 | +msgid "Set the lingo to use" |
953 | +msgstr "" |
954 | + |
955 | +#: ../boots/app/client_config.py:87 |
956 | +msgid "Do not read user configuration file" |
957 | +msgstr "" |
958 | + |
959 | +#: ../boots/app/client_config.py:92 |
960 | +msgid "Filename of user configuration file" |
961 | +msgstr "" |
962 | + |
963 | +#: ../boots/app/client_config.py:97 |
964 | +msgid "Connect to host" |
965 | +msgstr "" |
966 | + |
967 | +#: ../boots/app/client_config.py:102 |
968 | +msgid "Use port number" |
969 | +msgstr "" |
970 | + |
971 | +#: ../boots/app/client_config.py:107 |
972 | +msgid "Login with username" |
973 | +msgstr "" |
974 | + |
975 | +#: ../boots/app/client_config.py:112 |
976 | +msgid "Connect using password. If none is given, query for password" |
977 | +msgstr "" |
978 | + |
979 | +#: ../boots/app/client_config.py:117 |
980 | +msgid "Specify the SQL statement terminating character. Default is ';'." |
981 | +msgstr "" |
982 | + |
983 | +#: ../boots/app/client_config.py:122 |
984 | +msgid "Specify file to save history to" |
985 | +msgstr "" |
986 | + |
987 | +#: ../boots/app/client_config.py:127 |
988 | +msgid "Specify max history file length" |
989 | +msgstr "" |
990 | + |
991 | +#: ../boots/app/client_config.py:167 |
992 | +msgid "not found" |
993 | +msgstr "" |
994 | + |
995 | +#: ../boots/app/client_config.py:169 |
996 | +msgid "contains a syntax error" |
997 | +msgstr "" |
998 | + |
999 | +#: ../boots/app/client_config.py:171 |
1000 | +msgid "contains an error:" |
1001 | +msgstr "" |
1002 | |
1003 | === added file 'localizations/createpots.sh' |
1004 | --- localizations/createpots.sh 1970-01-01 00:00:00 +0000 |
1005 | +++ localizations/createpots.sh 2010-03-02 01:07:12 +0000 |
1006 | @@ -0,0 +1,3 @@ |
1007 | +#!/bin/bash |
1008 | +xgettext --from-code=utf-8 --keyword=tr --default-domain=cms --output=boots.pot --files-from=potfiles.txt |
1009 | + |
1010 | |
1011 | === added file 'localizations/potfiles.txt' |
1012 | --- localizations/potfiles.txt 1970-01-01 00:00:00 +0000 |
1013 | +++ localizations/potfiles.txt 2010-03-02 01:07:12 +0000 |
1014 | @@ -0,0 +1,12 @@ |
1015 | +../boots/lib/console.py |
1016 | +../boots/lib/ui/plain.py |
1017 | +../boots/lib/ui/components/metacommands.py |
1018 | +../boots/lib/ui/components/help.py |
1019 | +../boots/lib/lingos/lingo.py |
1020 | +../boots/lib/lingos/piped_sql.py |
1021 | +../boots/lib/lingos/lisp/builtins.py |
1022 | +../boots/lib/lingos/lisp/lexer.py |
1023 | +../boots/lib/lingos/lisp/lisp.py |
1024 | +../boots/lib/lingos/lisp/objects.py |
1025 | +../boots/lib/lingos/lisp/parser.py |
1026 | +../boots/app/client_config.py |
Tested and working. Forced to remerged the app and lib data as the domain for the two is the same. No found way to distinguish between the two at run time.