public
Description: Web-based translation and translation management tool
Homepage: http://translate.sf.net/
Clone URL: git://github.com/julen/pootle.git
pootle / pagelayout.py
100644 321 lines (289 sloc) 13.4 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2004-2007 Zuza Software Foundation
#
# This file is part of translate.
#
# translate is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# translate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with translate; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
import os
 
def localize_links(session):
  """Localize all the generic links"""
  links = {}
  links["home"] = session.localize("Home")
  links["projects"] = session.localize("All projects")
  links["languages"] = session.localize("All languages")
  links["account"] = session.localize("My account")
  links["admin"] = session.localize("Admin")
  links["doc"] = session.localize("Docs & help")
  links["doclang"] = getdoclang(session.language)
  links["logout"] = session.localize("Log out")
  links["login"] = session.localize("Log in")
  #l10n: Verb, as in "to register"
  links["register"] = session.localize("Register")
  links["activate"] = session.localize("Activate")
  return links
 
def getdoclang(language):
  """Get the language code that the docs should be displayed in."""
 
  #TODO: Determine the available languages programmatically.
  available_languages = ["en"]
  if language in available_languages:
    return language
  else:
    return "en"
 
def languagedir(language):
  """Returns whether the language is right to left"""
  shortcode = language[:3]
  if not shortcode.isalpha():
    shortcode = language[:2]
  if shortcode in ["ar", "arc", "dv", "fa", "he", "ks", "ps", "ur", "yi"]:
    return "rtl"
  return "ltr"
 
def weblanguage(language):
  """Reformats the language code from locale style (pt_BR) to web style (pt-br)"""
  return language.replace("_", "-")
 
def localelanguage(language):
  """Reformats the language code from web style (pt-br) to locale style (pt_BR)"""
  dashindex = language.find("-")
  if dashindex >= 0:
    language = language[:dashindex] + "_" + language[dashindex+1:].upper()
  return language
 
def completetemplatevars(templatevars, session, bannerheight=135):
  """fill out default values for template variables"""
  if not "instancetitle" in templatevars:
    templatevars["instancetitle"] = getattr(session.instance, "title", session.localize("Pootle Demo"))
  if not "session" in templatevars:
    templatevars["session"] = {"status": session.status, "isopen": session.isopen, "issiteadmin": session.issiteadmin()}
  if not "baseurl" in templatevars:
    templatevars["baseurl"] = getattr(session.instance, "baseurl", "/")
    if not templatevars["baseurl"].endswith("/"):
     templatevars["baseurl"] += "/"
  if not "enablealtsrc" in templatevars:
     templatevars["enablealtsrc"] = getattr(session.instance, "enablealtsrc", False)
  templatevars["logo_alttext"] = session.localize("Pootle Logo")
  templatevars["aboutlink"] = session.localize("About this Pootle server")
  templatevars["uilanguage"] = weblanguage(session.language)
  templatevars["uidir"] = languagedir(session.language)
  templatevars["links"] = localize_links(session)
  if "search" not in templatevars:
    templatevars["search"] = None
 
class PootlePage:
  """the main page"""
  def __init__(self, templatename, templatevars, session, bannerheight=135):
    if not hasattr(session.instance, "baseurl"):
      session.instance.baseurl = "/"
    if not hasattr(session.instance, "enablealtsrc"):
      session.instance.enablealtsrc = False
    self.localize = session.localize
    self.session = session
    self.templatename = templatename
    self.templatevars = templatevars
    self.completevars(bannerheight)
 
  def completevars(self, bannerheight=135):
    """fill out default values for template variables"""
    if hasattr(self, "templatevars"):
      completetemplatevars(self.templatevars, self.session, bannerheight=bannerheight)
 
  def polarizeitems(self, itemlist):
    """take an item list and alternate the background colour"""
    polarity = False
    for n, item in enumerate(itemlist):
      if isinstance(item, dict):
        item["parity"] = ["even", "odd"][n % 2]
      else:
        item.setpolarity(polarity)
      polarity = not polarity
    return itemlist
 
class PootleNavPage(PootlePage):
  def makenavbarpath_dict(self, project=None, session=None, currentfolder=None, language=None, argdict=None, dirfilter=None):
    """create the navbar location line"""
    #FIXME: Still lots of PO specific references here!
    rootlink = ""
    paramstring = ""
    if argdict:
      paramstring = "?" + "&".join(["%s=%s" % (arg, value) for arg, value in argdict.iteritems() if arg.startswith("show") or arg == "editing"])
 
    links = {"admin": None, "project": [], "language": [], "goal": [], "pathlinks": []}
    if currentfolder:
      pathlinks = []
      dirs = currentfolder.split(os.path.sep)
      if dirfilter is None:
        dirfilter = currentfolder
      
      depth = dirfilter.count(os.path.sep) + 1
      if dirfilter == "":
        depth -= 1
      elif dirfilter.endswith(".po") or dirfilter.endswith(".xlf"):
        depth = depth - 1
 
      rootlink = "/".join([".."] * depth)
      if rootlink:
        rootlink += "/"
      backlinks = ""
      for backlinkdir in dirs:
        if depth >= 0:
          backlinks = "../" * depth + backlinkdir
          depth -= 1
        else:
          backlinks += backlinkdir
        if not (backlinkdir.endswith(".po") or backlinkdir.endswith(".xlf")) and not backlinks.endswith("/"):
          backlinks = backlinks + "/"
        pathlinks.append({"href": self.getbrowseurl(backlinks), "text": backlinkdir, "sep": " / "})
      if pathlinks:
        pathlinks[-1]["sep"] = ""
      links["pathlinks"] = pathlinks
    if argdict and "goal" in argdict:
      # goallink = {"href": self.getbrowseurl("", goal=goal), "text": goal}
      links["goal"] = {"href": self.getbrowseurl(""), "text": self.localize("All goals")}
    if project:
      if isinstance(project, tuple):
        projectcode, projectname = project
        links["project"] = {"href": "/projects/%s/%s" % (projectcode, paramstring), "text": projectname}
      else:
        links["language"] = {"href": rootlink + "../index.html", "text": session.tr_lang(project.languagename)}
        # don't getbrowseurl on the project link, so sticky options won't apply here
        links["project"] = {"href": (rootlink or "index.html") + paramstring, "text": project.projectname}
        if session:
          if "admin" in project.getrights(session) or session.issiteadmin():
            links["admin"] = {"href": rootlink + "admin.html", "text": self.localize("Admin")}
    elif language:
      languagecode, languagename = language
      links["language"] = {"href": "/%s/" % languagecode, "text": session.tr_lang(languagename)}
    return links
 
  def getbrowseurl(self, basename, **newargs):
    """gets the link to browse the item"""
    if not basename or basename.endswith("/"):
      return self.makelink(basename or "index.html", **newargs)
    else:
      return self.makelink(basename, translate=1, view=1, **newargs)
 
  def makelink(self, link, **newargs):
    """constructs a link that keeps sticky arguments e.g. showchecks"""
    combinedargs = self.argdict.copy()
    combinedargs.update(newargs)
    if '?' in link:
      if not (link.endswith("&") or link.endswith("?")):
        link += "&"
    else:
      link += '?'
    # TODO: check escaping
    link += "&".join(["%s=%s" % (arg, value) for arg, value in combinedargs.iteritems() if arg != "allowmultikey"])
    return link
 
  def initpagestats(self):
    """initialise the top level (language/project) stats"""
    self.alltranslated = 0
    self.grandtotal = 0
    
  def getpagestats(self):
    """return the top level stats"""
    return (self.alltranslated*100/max(self.grandtotal, 1))
 
  def updatepagestats(self, translated, total):
    """updates the top level stats"""
    self.alltranslated += translated
    self.grandtotal += total
 
  def describestats(self, project, projectstats, numfiles):
    """returns a sentence summarizing item statistics"""
    translated = projectstats.get("translated", [])
    total = projectstats.get("total", 0)
    if "translatedsourcewords" in projectstats:
      translatedwords = projectstats["translatedsourcewords"]
    else:
      translatedwords = project.countwords(translated)
    totalwords = projectstats["totalsourcewords"]
    if isinstance(translated, list):
      translated = len(translated)
    if isinstance(total, list):
      total = len(total)
    percentfinished = (translatedwords*100/max(totalwords, 1))
    if numfiles is None:
      filestats = ""
    elif isinstance(numfiles, tuple):
      filestats = self.localize("%d/%d files", numfiles) + ", "
    else:
      #TODO: Perhaps do better?
      filestats = self.nlocalize("%d file", "%d files", numfiles, numfiles) + ", "
    wordstats = self.localize("%d/%d words (%d%%) translated", translatedwords, totalwords, percentfinished)
    stringstatstext = self.localize("%d/%d strings", translated, total)
    stringstats = ' <span class="string-statistics">[%s]</span>' % stringstatstext
    return filestats + wordstats + stringstats
 
  def getstatsheadings(self):
    """returns a dictionary of localised headings"""
    headings = {"name": self.localize("Name"),
                "translated": self.localize("Translated"),
                "translatedpercentage": self.localize("Translated percentage"),
                "translatedwords": self.localize("Translated words"),
                "fuzzy": self.localize("Fuzzy"),
                "fuzzypercentage": self.localize("Fuzzy percentage"),
                "fuzzywords": self.localize("Fuzzy words"),
                "untranslated": self.localize("Untranslated"),
                "untranslatedpercentage": self.localize("Untranslated percentage"),
                "untranslatedwords": self.localize("Untranslated words"),
                "total": self.localize("Total"),
                "totalwords": self.localize("Total words"),
                # l10n: noun. The graphical representation of translation status
                "graph": self.localize("Graph")}
    return headings
 
  def getstats(self, project, projectstats):
    """returns a list with the data items to fill a statistics table
Remember to update getstatsheadings() above as needed"""
    wanted = ["translated", "fuzzy", "total"]
    gotten = {}
    for key in wanted:
      gotten[key] = projectstats.get(key, [])
      wordkey = key + "sourcewords"
      if wordkey in projectstats:
        gotten[wordkey] = projectstats[wordkey]
      else:
        count = projectstats.get(key, [])
        gotten[wordkey] = project.countwords(count)
      if isinstance(gotten[key], list):
        #TODO: consider carefully:
        gotten[key] = len(gotten[key])
 
    gotten["untranslated"] = gotten["total"] - gotten["translated"] - gotten["fuzzy"]
    gotten["untranslatedsourcewords"] = gotten["totalsourcewords"] - gotten["translatedsourcewords"] - gotten["fuzzysourcewords"]
 
    wanted = ["translated", "fuzzy", "untranslated"]
    for key in wanted:
      percentkey = key + "percentage"
      wordkey = key + "sourcewords"
      gotten[percentkey] = gotten[wordkey]*100/max(gotten["totalsourcewords"], 1)
 
    for key in gotten:
      if key.find("check-") == 0:
        value = gotten.pop(key)
        gotten[key[len("check-"):]] = value
 
    return gotten
 
  def getsearchfields(self):
    tmpfields = [{"name": "source",
                  "text": self.localize("Source Text"),
                  "value": self.argdict.get("source", 0),
                  "checked": self.argdict.get("source", 0) == "1" and "checked" or None},
                 {"name": "target",
                  "text": self.localize("Target Text"),
                  "value": self.argdict.get("target", 0),
                  "checked": self.argdict.get("target", 0) == "1" and "checked" or None},
                 {"name": "notes",
                  "text": self.localize("Comments"),
                  "value": self.argdict.get("notes", 0),
                  "checked": self.argdict.get("notes", 0) == "1" and "checked" or None},
                 {"name": "locations",
                  "text": self.localize("Locations"),
                  "value": self.argdict.get("locations", 0),
                  "checked": self.argdict.get("locations", 0) == "1" and "checked" or None}]
 
    selection = [bool(field["checked"]) for field in tmpfields]
    if selection == [True, True, False, False]:
      # use only the default css class for the search form
      self.extra_class = False
    elif selection == [False, False, False, False]:
      # no search field selected - we use the default instead
      tmpfields[0]["checked"] = "checked"
      tmpfields[1]["checked"] = "checked"
      self.extra_class = False
    else:
      # add an extra css class to the search form
      self.extra_class = True
 
    return tmpfields