Dateianhang 'multilang-2003-01-22.diff'
Herunterladen 1 --- ../../../multilang.cvs/moin/MoinMoin/logger.py Wed Jan 22 13:44:11 2003
2 +++ logger.py Wed Jan 15 19:03:41 2003
3 @@ -0,0 +1,234 @@
4 +"""
5 + MoinMoin - generic log
6 +
7 + Copyright (c) 2000, 2001, 2002 by Florian Festi
8 + All rights reserved, see COPYING for details.
9 +
10 +"""
11 +
12 +class TextLogger:
13 + """ generic text log
14 +
15 + lots of the functionallity is still untested, use with care
16 + """
17 + def __init__(self, filename, format = None, reversed = 0, offset = None):
18 + """
19 + """
20 + self.index = 0 # for next(), peek() - user space
21 + self.__filename = filename
22 + self.filter = None
23 + self.__raw = None # raw lines
24 + self.__data = None # parsed lines
25 + self.__byte_offset = 0 # length of skiped part
26 + self.__line_offset = 0 # number skiped lines
27 + self.__reversed = reversed
28 + self.__format = format # None or "[sif]*"
29 + if self.__format:
30 + self.__formatstring = self.__format_string(self.__format)
31 + if offset:
32 + (self.__line_offset, self.__byte_offset) = offset
33 +
34 + def sanityCheck(self):
35 + """ Check for editlog file access.
36 + """
37 + if not os.access(self.filename, os.W_OK):
38 + return "The edit log '%s' is not writable!" % (self.filename,)
39 + return None
40 +
41 + def addEntry(self, *data):
42 + """ append data to the log file
43 + """
44 + logfile = open(self.__filename, 'a+')
45 + entry = self.__encode_line(data)
46 + try:
47 + # fcntl.flock(logfile.fileno(), fcntl.LOCK_EX)
48 + logfile.seek(0, 2) # to end
49 + logfile.write(entry)
50 + finally:
51 + # fcntl.flock(logfile.fileno(), fcntl.LOCK_UN)
52 + logfile.close()
53 + return entry
54 +
55 + def __format_string(self, format):
56 + """ Calculate string used for conversion data -> log line
57 + """
58 + result = ''
59 + for c in format:
60 + if not c in ['s', 'i', 'f']:
61 + raise ValueError
62 + result = result + "%" + c + '\t'
63 + result = result[:-1] + '\n'
64 + return result
65 +
66 + def __encode_line(self, data):
67 + """ converts data to line in the log file
68 + """
69 + from types import *
70 + if self.__format:
71 + return self.__formatstring % data
72 + # Use Pythonsyntax
73 + else:
74 + return `data`
75 +
76 + def __decode_line(self, line):
77 + """ converts a line from the log file zu a list of items
78 + """
79 + if self.__format:
80 + fields = string.split(string.strip(line), '\t')
81 + result = []
82 + for i in range(len(fields)):
83 + if self.__format[i] == 's':
84 + result.append(fields[i])
85 + elif self.__format[i] == 'i':
86 + try:
87 + result.append(int(fields[i]))
88 + except ValueError:
89 + result.append(0)
90 + else: # 'f'
91 + try:
92 + result.append(float(fields[i]))
93 + except ValueError:
94 + result.append(0.0)
95 + # fill missing fields
96 + for c in self.__format[len(fields):]:
97 + if c == 's': result.append('')
98 + elif c == 'i': result.append(0)
99 + elif c == 'f': result.append(0.0)
100 +
101 + # Python format
102 + else:
103 + try:
104 + return eval(line[:-1])
105 + except:
106 + return ""
107 +
108 + def __read_from_file(self):
109 + """ load log file
110 + """
111 + file = open(self._filename, 'r')
112 + self.__raw = file.readlines()
113 + self.__data = map(self.__decode_line, self.__raw)
114 +
115 + def __set_entry(self, index):
116 + """ called by next() and peek() to set attributes as side effect
117 + index is the internal index for self.__data, index is valid or None
118 + this is intended to be used for child classes
119 + """
120 + pass
121 +
122 + def __key_to_index(self, key, truncate = 1):
123 + """ calculates the intern index for __data
124 + if truncate the functions returns None if index is out of range
125 + """
126 + length = len(self.__data) + self.__line_offset
127 + offset = self.__line_offset
128 + if key < 0: key = key + length
129 + if reversed:
130 + key = length - key - 1
131 + if truncate and (key < offset or key >= length):
132 + return None
133 + else: return key
134 +
135 +### direct access
136 +
137 + def read(self):
138 + """ returns a list of all entrys which are lists of items
139 + """
140 + if not self.__data:
141 + self.__read_from_file()
142 + if self.filter:
143 + result = filter(self.__data, self.filter)
144 + else:
145 + result = self.__data[:]
146 + if self.__reversed: result.reverse()
147 + return result
148 +
149 + def __getitem__(self, key):
150 + """ returns one line as list of items
151 + """
152 + if not self.__data:
153 + self.__read_from_file()
154 + index = self.__key_to_index(key)
155 + if index != None:
156 + return self.__data[index]
157 + else:
158 + return None
159 +
160 + def keys(self):
161 + """ returns list with all valid indices
162 + """
163 + if self.__reversed:
164 + return range(len(self.__data))
165 + else:
166 + return range(self.__line_offset,
167 + len(self.__data) + self.__line_offset)
168 +
169 + def range(self):
170 + """ returns tuple of first valid and first invalid index
171 + """
172 + if self.__reversed:
173 + return (0,len(self.__data))
174 + else:
175 + return (self.__line_offset,
176 + len(self.__data) + self.__line_offset)
177 +
178 +
179 +
180 + def getOffset(self, line = None):
181 + """ returns a tuple off line number and a offset object
182 + (the byte offset for text logs). This tuple can be passed to
183 + the constructor.
184 + """
185 + if line == None:
186 + line = self.index
187 + index = self.__key_to_index(line, truncate = 0)
188 + if index > len(self.__data):
189 + index = len(self.__data)
190 + if index < 0:
191 + return (self.__line_offset, self.__byte_offset)
192 + bytes = 0
193 + for l in self.__raw[:line]:
194 + bytes = bytes + len(l)
195 + return (self.__line_offset + line, self.byte_offset + bytes)
196 +
197 +##### Iterator functions
198 +
199 + def next(self, offset = 1):
200 + """ returns next line as a list of items
201 + self.__set_entry is called (see there)
202 + """
203 + if not self.__data:
204 + self.__read_from_file()
205 + self.index = self.index + offset
206 + index = self.__key_to_index(self.index)
207 + self.__set_entry(index)
208 + if index != None: return self.__data[index]
209 + else: return None
210 +
211 + def peek(self, offset=0):
212 + """ returns a line offset away from the actual line
213 + self.__set_entry is called (see there)
214 + """
215 + if not self.__data:
216 + self.__read_from_file()
217 + index = self.__key_to_index(self.index + offset)
218 + self.__set_entry(index)
219 + if index != None: return self.__data[index]
220 + else: return None
221 +
222 + def reset(self):
223 + """ sets the index to the first line and returns it as list of items
224 + the first line may not be number 0 if there is an offset
225 + """
226 + if not self.__data:
227 + self.__read_from_file()
228 + if self.__reversed:
229 + self.index = 0
230 + else:
231 + self.index = self.__line_offset
232 + index = self.__key_to_index(self.index)
233 + self.__set_entry(index)
234 + if index != None: return self.__data[index]
235 + else: return None
236 +
237 +# self.index
238 --- ../../../multilang.cvs/moin/MoinMoin/multilang.py Tue Jan 14 22:00:44 2003
239 +++ multilang.py Fri Jan 17 19:36:16 2003
240 @@ -8,12 +8,15 @@
241 """
242
243 # Imports
244 -from MoinMoin import config, wikiutil
245 +from MoinMoin import config, wikiutil, logger
246 +from MoinMoin.i18n import _
247 import os.path
248
249 # translated page operations
250 def title_search(needle, languages = None, extended=None):
251 - """ ??? """
252 + """ searches in all or the given languages
253 + if extended translations of found pages are also found
254 + """
255 import re
256
257 if not languages:
258 @@ -77,7 +80,7 @@
259 translation_file = new_translation_file(page_name)
260 set_translation_file(page_name, translation_file)
261 set_translation_file(pages[0], translation_file)
262 - add_translation(translation_file, config.interwikilink+':'+page_name)
263 + add_translation(translation_file, config.interwikiname+':'+page_name)
264 add_translation(translation_file, pages[0])
265 else: # ambigous or no translations
266 # raise IOError ????? This triggers when creating a new page when there is no translation yet. Should not be.
267 @@ -93,9 +96,9 @@
268 translation_file = get_translation_file(page_name)
269 if translation_file:
270 translations = read_translations(translation_file)
271 - iwlen = len(config.interwikilink)
272 + iwlen = len(config.interwikiname)
273 for translation in translations:
274 - if translation[0:iwlen] == config.interwikilink:
275 + if translation[0:iwlen] == config.interwikiname:
276 translations.remove(translation)
277 return translations
278 else:
279 @@ -109,18 +112,17 @@
280 page_name = inter_language_link(_page_name)
281 to_page = inter_language_link(_to_page)
282 if not page_name:
283 - errmsg = _page_name + " is not a valid Interwikilink. "
284 + errmsg = _page_name + _(" is not a valid Interwikilink. ")
285 if not to_page:
286 - errmsg = errmsg + _to_page + " is not a valid Interwikilink. "
287 + errmsg = errmsg + _to_page + _(" is not a valid Interwikilink. ")
288 if errmsg:
289 return errmsg
290
291 translation_file = get_translation_file(to_page)
292 # page already has translations
293 if translation_file:
294 - errmsg = "added myself to" + to_page
295 if add_translation(translation_file, page_name):
296 - errmsg = to_page + " has already a translation in your language"
297 + errmsg = to_page + _(" has already a translation in your language")
298 return errmsg
299 # delete myself from my old translationfile
300 my_translation_file = get_translation_file(page_name)
301 @@ -133,12 +135,11 @@
302 # do we have translations
303 if translation_file:
304 if add_translation(translation_file, to_page):
305 - errmsg = ( 'This page "' + page_name +
306 - '" has already a translation in this language')
307 + errmsg = ( _('The page "') + page_name +
308 + _('" has already a translation in this language'))
309 else:
310 set_translation_file(to_page, translation_file)
311 else:
312 - errmsg = 'new translation file'
313 # generate new translation file
314 translation_file = new_translation_file(page_name)
315 set_translation_file(page_name, translation_file)
316 @@ -148,19 +149,19 @@
317 return errmsg
318
319 def unset_translation(_page_name):
320 - """ ??? """
321 + """ removes translation for given page """
322 errmsg = ''
323 # test page_name
324 page_name = inter_language_link(_page_name)
325 if not page_name:
326 - return _page_name + " is not a valid Interwikilink. "
327 + return _page_name + _(" is not a valid Interwikilink. ")
328
329 translation_file = get_translation_file(page_name)
330 if translation_file:
331 remove_translation(translation_file, page_name)
332 set_translation_file(page_name, None)
333 else:
334 - errmsg = 'no translation'
335 + errmsg = _('no translation')
336 return errmsg
337
338 ##### Internal functions #######################
339 @@ -178,10 +179,12 @@
340 return lang + ':' + interwiki[1]
341 return None
342 else: # is a local page
343 - return config.interwikilink + ':' + page_name
344 + return config.interwikiname + ':' + page_name
345
346 def get_translation_file(pagename):
347 - """ return file name or None """
348 + """get group file name from "per page" file
349 + returns file name or None
350 + """
351 lang_file = get_language_file(pagename)
352 if not lang_file:
353 return None
354 @@ -194,7 +197,7 @@
355 return None
356
357 def set_translation_file(pagename, translationfilename):
358 - """ ??? """
359 + """ set group file name into "per page" file """
360 lang_file = get_language_file(pagename)
361 if translationfilename:
362 if not os.path.exists(os.path.dirname(lang_file)):
363 @@ -209,7 +212,7 @@
364
365 # translation group file operations
366 def read_translations(translation_file):
367 - """ ??? """
368 + """ get all interwikinames form group file """
369 translation_file = os.path.join(config.multilingual_dir, translation_file)
370 try:
371 f = open(translation_file, 'r')
372 @@ -221,32 +224,36 @@
373 return translations
374
375 def add_translation(translationfile, interwikilink):
376 - """ ??? """
377 - translationfile = os.path.join(config.multilingual_dir, translationfile)
378 - if os.path.exists(translationfile):
379 - f = open(translationfile, 'r')
380 + """ Add interwikilink to group file """
381 + translationfilename = os.path.join(config.multilingual_dir, translationfile)
382 + if os.path.exists(translationfilename):
383 + f = open(translationfilename, 'r')
384 translations = f.readlines()
385 f.close()
386 # test if there already is a translation in our language
387 wiki, page = wikiutil.split_wiki(interwikilink)
388 if not wiki:
389 - wiki = config.interwikilink
390 + wiki = config.interwikiname
391 interwikilink = wiki + ':' + interwikilink
392 log = 'X'
393 iwlen = len(wiki)
394 for translation in translations:
395 - log = log + translation
396 if translation[0:iwlen] == wiki:
397 return 1
398 - f = open(translationfile, 'a')
399 - f. write(interwikilink + '\n')
400 + f = open(translationfilename, 'a')
401 + f.write(interwikilink + '\n')
402 f.close()
403 + mtime = os.path.getmtime(translationfilename)
404 +
405 + log = getLog()
406 + log.addEntry(mtime, interwikilink, translationfile, "SET")
407 +
408
409 def remove_translation(translationfile, interwikilink):
410 - """ ??? """
411 - translationfile = os.path.join(config.multilingual_dir, translationfile)
412 - if os.path.exists(translationfile):
413 - f = open(translationfile, 'rw')
414 + """ remove interwikiname form group file """
415 + translationfilename = os.path.join(config.multilingual_dir, translationfile)
416 + if os.path.exists(translationfilename):
417 + f = open(translationfilename, 'rw')
418 translations = f.readlines()
419 f.close()
420 for translation in translations:
421 @@ -254,14 +261,22 @@
422 translations.remove(translation)
423
424 if len(translations)>0:
425 - f = open(translationfile, 'w')
426 + f = open(translationfilename, 'w')
427 f.writelines(translations)
428 f.close()
429 + mtime = os.path.getmtime(translationfilename)
430 else:
431 - os.remove(translationfile)
432 + os.remove(translationfilename)
433 + mtime = os.path.getmtime(config.multilingual_dir)
434 + log = getLog()
435 + log.addEntry(mtime, interwikilink, translationfile, "REMOVE")
436
437 def new_translation_file(page_name):
438 - """ returns unique aund quoted filename """
439 + """ returns unique and quoted filename """
440 + # use Pagename only
441 + interwiki = page_name.split(':', 1)
442 + page_name = interwiki[-1]
443 +
444 translationfile = os.path.join(config.multilingual_dir,
445 wikiutil.quoteFilename(page_name))
446 newtranslationfile = translationfile
447 @@ -271,10 +286,11 @@
448 i = i + 1
449 return os.path.basename(newtranslationfile)
450
451 -# access to external wikis
452 +# access to files in "external" wikis
453
454 def get_interwiki_filename(interwikilink):
455 - """ returns directory or filename """
456 + """ returns a page file or a text directory belonging to a interwikiname
457 + """
458 interwiki = interwikilink.split(':', 1)
459 if len(interwiki) == 2:
460 if config.languages.has_key(interwiki[0]):
461 @@ -287,7 +303,9 @@
462 wikiutil.quoteFilename(interwiki[0]))
463
464 def get_language_file(interwikilink):
465 - """ returns directory or filename """
466 + """ returns file containing the name of the translation group
467 + this is the "per page" file
468 + """
469 interwiki = interwikilink.split(':', 1)
470 if len(interwiki) == 2:
471 if config.languages.has_key(interwiki[0]):
472 @@ -307,7 +325,7 @@
473 """ returns HTML Source for a link like "[en]" or "[en] FrontPage" """
474 tag, interwiki, tail = wikiutil.resolve_wiki(page_name)
475 if not tag:
476 - tag = config.interwikilink
477 + tag = config.interwikiname
478 interwiki = ''
479 url = interwiki + wikiutil.quoteWikiname(tail)
480 if show_name:
481 @@ -316,3 +334,12 @@
482 result = '<a href="%s">[%s]</a>' % (url, tag.lower())
483 return result
484
485 +# Logging
486 +
487 +def getLog():
488 + from MoinMoin import logger
489 + return logger.TextLogger(os.path.join(config.multilingual_dir, 'multilang.log'), format= "isss")
490 +
491 +
492 +
493 +
494 --- ../../../multilang.cvs/moin/MoinMoin/Page.py Tue Jan 14 22:00:39 2003
495 +++ Page.py Sat Jan 18 18:41:58 2003
496 @@ -167,9 +167,8 @@
497 flags = flags + ' ' + multilang.language_link(translation, 0)
498 # if none found show similar pages
499 else:
500 - pass
501 other_languages = config.languages.keys()
502 - other_languages.remove(config.interwikilink)
503 + other_languages.remove(config.interwikiname)
504 translations = multilang.title_search(self.page_name,
505 other_languages,
506 extended=None)
507 @@ -519,9 +518,9 @@
508 search = search[:-1]
509 pages = multilang.title_search(search, None, 1)
510 i = 0
511 - langlength = len(config.interwikilink)
512 + langlength = len(config.interwikiname)
513 while i < len(pages):
514 - if pages[i][0:langlength] == config.interwikilink:
515 + if pages[i][0:langlength] == config.interwikiname:
516 del pages[i]
517 else:
518 i = i + 1
519 @@ -578,7 +577,11 @@
520 else:
521 return self.page_name
522
523 - def translation(self, request):
524 + def translation_menu(self, request, msg=None, **keywords):
525 + """
526 + multilang extention
527 + Print TranlationMenu for this Page.
528 + """
529 request.clock.start('send_page')
530 import cgi
531 from MoinMoin.util import pysupport
532 @@ -601,11 +604,19 @@
533 webapi.http_headers(request)
534 sys.stdout.write(doc_leader)
535
536 - wikiutil.send_title(page_name)
537 - from MoinMoin import multilang
538 + wikiutil.send_title(page_name, msg=msg, pagename=self.page_name)
539 + from MoinMoin import multilang
540 +
541 + # Back to page
542 + print self.formatter.paragraph(1)
543 + print self.formatter.url(wikiutil.quoteWikiname(self.page_name),
544 + _("Back to ") + page_name)
545 + print self.formatter.paragraph(0)
546 +
547 + # Existing Translations
548 + print self.formatter.heading(2, 'Translations of %s' % page_name)
549 translations = multilang.get_translations(page_name)
550 if len(translations) > 0:
551 - print self.formatter.heading(2, 'Translations of %s' % page_name)
552 print self.formatter.bullet_list(1)
553 for translation in translations:
554 tag, interwiki, tail = wikiutil.resolve_wiki(translation)
555 @@ -613,10 +624,6 @@
556 # Link
557 print multilang.language_link(translation)
558 # Link for removing
559 -# print (' ( <a href="%(page_name)s?' +
560 -# 'action=TranslationMenu&do=unset&page=%(tag)s:%(tail)s">' +
561 -# 'remove from group</a> ) </li>\n' ) % vars()
562 -
563 print " ( "
564 print wikiutil.link_tag("%s?action=TranslationMenu&do=unset&page=%s" % (
565 wikiutil.quoteWikiname(self.page_name),
566 @@ -632,6 +639,7 @@
567 wikiutil.quoteWikiname(self.page_name)),
568 _("Remove this page from group"))
569 print self.formatter.paragraph(0)
570 +
571 # Show similar Pages
572 if request.form.has_key("text_title"):
573 searchtext = request.form["text_title"].value
574 @@ -644,8 +652,8 @@
575 if self.inter_wiki_link() in pages:
576 pages.remove(self.inter_wiki_link())
577 pages.sort()
578 + print self.formatter.heading(2,'Similar Pages')
579 if len(pages) > 0:
580 - print self.formatter.heading(2,'Similar Pages')
581 print self.formatter.bullet_list(1)
582 for p in pages:
583 tag, interwiki, tail = wikiutil.resolve_wiki(p)
584 @@ -657,25 +665,26 @@
585 tag + ":" + wikiutil.quoteWikiname(tail)),
586 _("Add"))
587 print " ) "
588 -# print (' ( <a href="%(page_name)s?' +
589 -# 'action=TranslationMenu&do=set&page=%(tag)s:%(tail)s">' +
590 -# 'Add</a> ) </li>\n' ) % vars()
591 print self.formatter.listitem(0)
592 print self.formatter.bullet_list(0)
593 -
594 - print """Search
595 + # Searchbox
596 + print self.formatter.paragraph(1)
597 + print _("Search")
598 + print """
599 <form method="POST" action="%s">
600 <input type="hidden" name="action" value="TranslationMenu">
601 <input type="text" name="text_title" value="%s" size="30">
602 <input type="image" src="/wiki/img/moin-search.gif" name="button_title"
603 alt="[?]" hspace="3" width="12" height="12" border="0">
604 </form>""" % ( page_name, searchtext )
605 + print self.formatter.paragraph(0)
606
607 # Insert new Translations directly
608 - print "<h2>Add new Translation</h2>"
609 - print "Insert Interwikilink and press Go"
610 + print self.formatter.heading(2,_("Add new Translation"))
611 + print _("Insert Interwikilink and press Go")
612 print macro.execute('SetTranslation', '')
613
614 + wikiutil.send_footer(request, self.page_name, showpage=1)
615 # end document output
616 sys.stdout.write(self.formatter.endDocument())
617 request.clock.stop('send_page')
618 --- ../../../multilang.cvs/moin/MoinMoin/wikimacro.py Thu Aug 1 20:07:52 2002
619 +++ wikimacro.py Wed Jan 8 14:34:59 2003
620 @@ -247,7 +247,7 @@
621 row(_('MoinMoin Version'), _('Release %s [Revision %s]') % (version.release, version.revision))
622 if ftversion:
623 row(_('4Suite Version'), ftversion)
624 - row(_('Number of pages'), len(wikiutil.getPageList(config.text_dir)))
625 + row(_('Number of pages'), _('%i (%i bytes)') % (len(wikiutil.getPageList(config.text_dir)), wikiutil.getTextSize(config.text_dir)))
626 row(_('Number of backup versions'), len(wikiutil.getBackupList(config.backup_dir, None)))
627 edlog = editlog.EditLog(self.request)
628 row(_('Entries in edit log'), _("%(logcount)s (%(logsize)s bytes)") %
629 --- ../../../multilang.cvs/moin/MoinMoin/wikiutil.py Tue Jan 14 22:00:45 2003
630 +++ wikiutil.py Tue Jan 14 22:12:16 2003
631 @@ -211,6 +211,19 @@
632 result.append(file)
633 return map(unquoteFilename, result)
634
635 +def getTextSize(text_dir):
636 + """ Returns bytes used by all pages, except for "CVS" directories,
637 + hidden files (leading '.') and temp files (leading '#')
638 + """
639 + pages = os.listdir(text_dir)
640 + result = 0
641 + for file in pages:
642 + if file[0] in ['.', '#'] or file in ['CVS']: continue
643 + try:
644 + result = result + os.path.getsize(os.path.join(text_dir, file))
645 + except os.error:
646 + pass
647 + return result
648
649 def getPageDict(text_dir):
650 """ Return a dictionary of page objects for all pages,
Gespeicherte Dateianhänge
Um Dateianhänge in eine Seite einzufügen sollte unbedingt eine Angabe wie attachment:dateiname benutzt werden, wie sie auch in der folgenden Liste der Dateien erscheint. Es sollte niemals die URL des Verweises ("laden") kopiert werden, da sich diese jederzeit ändern kann und damit der Verweis auf die Datei brechen würde.Sie dürfen keine Anhänge an diese Seite anhängen!