| 1 | # -*- coding: utf8 -*- |
|---|
| 2 | """ Macro to show the translated pages list. """ |
|---|
| 3 | |
|---|
| 4 | __author__ = u'Dirk Stöcker' |
|---|
| 5 | ' based on a macro by Zhang Cong (ftofficer)' |
|---|
| 6 | __version__ = '2.0' |
|---|
| 7 | |
|---|
| 8 | from trac.core import * |
|---|
| 9 | from trac.wiki.macros import WikiMacroBase |
|---|
| 10 | from StringIO import StringIO |
|---|
| 11 | from trac.wiki.formatter import Formatter |
|---|
| 12 | from trac.wiki.model import WikiPage |
|---|
| 13 | from trac.wiki.api import WikiSystem |
|---|
| 14 | import re |
|---|
| 15 | |
|---|
| 16 | class TranslatedPagesMacro(WikiMacroBase): |
|---|
| 17 | """ |
|---|
| 18 | Macro to show the translated pages list. |
|---|
| 19 | """ |
|---|
| 20 | |
|---|
| 21 | TRAC_LANGUAGES_PAGE = u'TracLanguages' |
|---|
| 22 | BASE_LANG = u'En' |
|---|
| 23 | |
|---|
| 24 | def __init__(self): |
|---|
| 25 | self.languages_page_version = 0 |
|---|
| 26 | self._update_languages() |
|---|
| 27 | |
|---|
| 28 | def _parse_languages_list(self, text): |
|---|
| 29 | """ |
|---|
| 30 | Parses the list of languages in form |
|---|
| 31 | * <language code> <language name> x <description> |
|---|
| 32 | * <language code> <language name> x <description> |
|---|
| 33 | ... |
|---|
| 34 | |
|---|
| 35 | The x is used to allow better display of page for languages written right to left |
|---|
| 36 | The description contains the "Other languages" text in that language |
|---|
| 37 | """ |
|---|
| 38 | langs = {} |
|---|
| 39 | reg = re.compile(u"^ \* ([A-Z][a-z](?:_[A-Z]{2})?) +(.+?) +x +(.+)$") |
|---|
| 40 | for line in text.split(u'\r\n'): |
|---|
| 41 | regres = reg.search(line) |
|---|
| 42 | if regres == None: |
|---|
| 43 | self.env.log.warn( |
|---|
| 44 | u"Wrong line syntax while parsing languages list: %s" % line) |
|---|
| 45 | else: |
|---|
| 46 | code = regres.group(1) |
|---|
| 47 | name = regres.group(2) |
|---|
| 48 | desc = regres.group(3) |
|---|
| 49 | self.env.log.debug("Adding language %s -> %s (%s)" % (code, name, desc)) |
|---|
| 50 | langs[code] = name |
|---|
| 51 | langs["_"+code] = desc |
|---|
| 52 | return langs |
|---|
| 53 | |
|---|
| 54 | def _update_languages(self): |
|---|
| 55 | languages_page = WikiPage(self.env, self.TRAC_LANGUAGES_PAGE) |
|---|
| 56 | if not languages_page.exists: |
|---|
| 57 | self.env.log.warn(u"Can't find page %s" % self.TRAC_LANGUAGES_PAGE) |
|---|
| 58 | self.languages = {} |
|---|
| 59 | self.languages_page_version = 0 |
|---|
| 60 | else: |
|---|
| 61 | if languages_page.version > self.languages_page_version: |
|---|
| 62 | self.languages = self._parse_languages_list(languages_page.text) |
|---|
| 63 | self.languages_page_version = languages_page.version |
|---|
| 64 | |
|---|
| 65 | def _get_language_name(self, lang_code): |
|---|
| 66 | self._update_languages() |
|---|
| 67 | return self.languages.get(lang_code, lang_code) |
|---|
| 68 | |
|---|
| 69 | def _get_translated_page(self, name, lang_code): |
|---|
| 70 | if lang_code == self.BASE_LANG: |
|---|
| 71 | return name |
|---|
| 72 | else: |
|---|
| 73 | return lang_code + u':' + name |
|---|
| 74 | |
|---|
| 75 | def _get_page_info(self, page_name): |
|---|
| 76 | regres = re.compile("^([A-Z][a-z](_[A-Z][A-Z])?):(.+)$").search(page_name) |
|---|
| 77 | if regres == None: |
|---|
| 78 | return (page_name, self.BASE_LANG) |
|---|
| 79 | return (regres.group(3), regres.group(1)) |
|---|
| 80 | |
|---|
| 81 | def _get_translations(self, base_page_name): |
|---|
| 82 | for l in sorted(self.languages.keys()): |
|---|
| 83 | tr = self._get_translated_page(base_page_name, l); |
|---|
| 84 | for subpage in sorted(WikiSystem(self.env).get_pages(tr)): |
|---|
| 85 | if(subpage == tr): |
|---|
| 86 | yield l |
|---|
| 87 | |
|---|
| 88 | def _get_lang_link(self, base_name, lang_code): |
|---|
| 89 | page_name = self._get_translated_page(base_name, lang_code) |
|---|
| 90 | return u" * [wiki:%s %s]" % (page_name, self._get_language_name(lang_code)) |
|---|
| 91 | |
|---|
| 92 | def _get_current_lang_link(self, lang_code): |
|---|
| 93 | return u" * '''%s'''" % self._get_language_name(lang_code) |
|---|
| 94 | |
|---|
| 95 | def expand_macro(self, formatter, name, args): |
|---|
| 96 | """ |
|---|
| 97 | Return a list of translated pages with the native language names. |
|---|
| 98 | The list of languages supported can be configured by adding new |
|---|
| 99 | entries to TracLanguages page. Refer to ISO 639-1 for more information. |
|---|
| 100 | """ |
|---|
| 101 | |
|---|
| 102 | page_name = formatter.context.resource.id |
|---|
| 103 | (base_page_name, lang_code) = self._get_page_info(page_name) |
|---|
| 104 | |
|---|
| 105 | lang_link_list = [] |
|---|
| 106 | for translation in self._get_translations(base_page_name): |
|---|
| 107 | if translation != lang_code: |
|---|
| 108 | lang_link_list.append(self._get_lang_link(base_page_name, translation)) |
|---|
| 109 | else: |
|---|
| 110 | lang_link_list.append(self._get_current_lang_link(lang_code)) |
|---|
| 111 | |
|---|
| 112 | out = StringIO() |
|---|
| 113 | Formatter(self.env, formatter.context).format(u'\n'.join(lang_link_list), out) |
|---|
| 114 | |
|---|
| 115 | desc = "Languages" |
|---|
| 116 | if self.languages.has_key("_"+lang_code): |
|---|
| 117 | desc = self.languages["_"+lang_code] |
|---|
| 118 | return u""" |
|---|
| 119 | <div class="wiki-toc trac-nav" style="clear:both"> |
|---|
| 120 | <h4>%s:</h4> |
|---|
| 121 | %s |
|---|
| 122 | </div>""" % (desc, out.getvalue()) |
|---|
| 123 | |
|---|