damned-lies r1064 - in branches/djamnedlies: . docs stats stats/conf stats/data stats/management stats/management/commands stats/templates
- From: claudep svn gnome org
- To: svn-commits-list gnome org
- Subject: damned-lies r1064 - in branches/djamnedlies: . docs stats stats/conf stats/data stats/management stats/management/commands stats/templates
- Date: Mon, 20 Oct 2008 21:34:37 +0000 (UTC)
Author: claudep
Date: Mon Oct 20 21:34:37 2008
New Revision: 1064
URL: http://svn.gnome.org/viewvc/damned-lies?rev=1064&view=rev
Log:
Initial commit of djangoified Damned-Lies.
Added:
branches/djamnedlies/ (props changed)
branches/djamnedlies/README
branches/djamnedlies/TODO
branches/djamnedlies/__init__.py
branches/djamnedlies/docs/
branches/djamnedlies/docs/DataModel.odg (contents, props changed)
branches/djamnedlies/manage.py
branches/djamnedlies/settings.py
branches/djamnedlies/stats/
branches/djamnedlies/stats/__init__.py
branches/djamnedlies/stats/admin.py
branches/djamnedlies/stats/conf/
branches/djamnedlies/stats/conf/__init__.py
branches/djamnedlies/stats/conf/settings.py
branches/djamnedlies/stats/data/
branches/djamnedlies/stats/data/bar.png (contents, props changed)
branches/djamnedlies/stats/data/cyan-bar.png (contents, props changed)
branches/djamnedlies/stats/data/download.png (contents, props changed)
branches/djamnedlies/stats/data/emptyimg.png (contents, props changed)
branches/djamnedlies/stats/data/error.png (contents, props changed)
branches/djamnedlies/stats/data/figure.png (contents, props changed)
branches/djamnedlies/stats/data/foot-16.png (contents, props changed)
branches/djamnedlies/stats/data/foot.png (contents, props changed)
branches/djamnedlies/stats/data/general_bg.png (contents, props changed)
branches/djamnedlies/stats/data/general_separator.png (contents, props changed)
branches/djamnedlies/stats/data/gnome-64.png (contents, props changed)
branches/djamnedlies/stats/data/gnome-gtp.png (contents, props changed)
branches/djamnedlies/stats/data/green-bar.png (contents, props changed)
branches/djamnedlies/stats/data/info.png (contents, props changed)
branches/djamnedlies/stats/data/layout.css
branches/djamnedlies/stats/data/main.css
branches/djamnedlies/stats/data/main.js
branches/djamnedlies/stats/data/nobody.png (contents, props changed)
branches/djamnedlies/stats/data/purple-bar.png (contents, props changed)
branches/djamnedlies/stats/data/red-bar.png (contents, props changed)
branches/djamnedlies/stats/data/rtl.css
branches/djamnedlies/stats/data/star.png (contents, props changed)
branches/djamnedlies/stats/data/style.css
branches/djamnedlies/stats/data/t.png (contents, props changed)
branches/djamnedlies/stats/data/tab_left.png (contents, props changed)
branches/djamnedlies/stats/data/tab_right.png (contents, props changed)
branches/djamnedlies/stats/data/warn.png (contents, props changed)
branches/djamnedlies/stats/data/webpage.png (contents, props changed)
branches/djamnedlies/stats/defaults.py
branches/djamnedlies/stats/management/
branches/djamnedlies/stats/management/__init__.py
branches/djamnedlies/stats/management/commands/
branches/djamnedlies/stats/management/commands/__init__.py
branches/djamnedlies/stats/management/commands/migrate.py
branches/djamnedlies/stats/models.py
branches/djamnedlies/stats/templates/
branches/djamnedlies/stats/templates/base.tmpl
branches/djamnedlies/stats/templates/index.tmpl
branches/djamnedlies/stats/templates/language-release-stats.tmpl
branches/djamnedlies/stats/templates/language-release.tmpl
branches/djamnedlies/stats/templates/list-languages.tmpl
branches/djamnedlies/stats/templates/list-modules.tmpl
branches/djamnedlies/stats/templates/list-releases.tmpl
branches/djamnedlies/stats/templates/list-teams.tmpl
branches/djamnedlies/stats/templates/module-images.tmpl
branches/djamnedlies/stats/templates/module.tmpl
branches/djamnedlies/stats/templates/people.tmpl
branches/djamnedlies/stats/templates/person-base.tmpl
branches/djamnedlies/stats/templates/person.tmpl
branches/djamnedlies/stats/templates/release.tmpl
branches/djamnedlies/stats/templates/show-stats.tmpl
branches/djamnedlies/stats/templates/team.tmpl
branches/djamnedlies/stats/urls.py
branches/djamnedlies/stats/utils.py
branches/djamnedlies/stats/views.py
branches/djamnedlies/urls.py
Added: branches/djamnedlies/README
==============================================================================
--- (empty file)
+++ branches/djamnedlies/README Mon Oct 20 21:34:37 2008
@@ -0,0 +1,12 @@
+This is a re-implementation of the Damned-Lies application
+in a Django app. Damned-Lies has been originally written by
+Danilo Segan (danilo gnome org). This implementation has been
+written by Claude Paroz (claude 2xlibre net).
+
+The former XML files (modules, releases, people, translation
+teams) have been replaced by a database.
+
+The Data model is in the /docs directory.
+
+The middle-term objective is to merge this code with the Transifex
+application (http://transifex.org).
Added: branches/djamnedlies/TODO
==============================================================================
--- (empty file)
+++ branches/djamnedlies/TODO Mon Oct 20 21:34:37 2008
@@ -0,0 +1,4 @@
+Things left to do:
+ * i18n (translation for strings in database?)
+ * replace entirely defaults.py by conf/settings.py
+ * implement update-stats.py script
Added: branches/djamnedlies/__init__.py
==============================================================================
Added: branches/djamnedlies/docs/DataModel.odg
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/manage.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/manage.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
Added: branches/djamnedlies/settings.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/settings.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,83 @@
+# Django settings for djamnedlies project.
+
+import os
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+ADMINS = (
+ ('Claude Paroz', 'claude 2xlibre net'),
+)
+
+MANAGERS = ADMINS
+
+DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_NAME = os.path.join(PROJECT_PATH,'database.db') # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'Europe/Zurich'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-US'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'zk!^92901p458c8lo0(fox-&k7jj(aple76_k%eva7b1)xjo8-'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+)
+
+ROOT_URLCONF = 'djamnedlies.urls'
+
+TEMPLATE_DIRS = (
+ os.path.join(PROJECT_PATH, 'stats', 'templates'),
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.admin',
+ 'stats',
+)
Added: branches/djamnedlies/stats/__init__.py
==============================================================================
Added: branches/djamnedlies/stats/admin.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/admin.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2008 Claude Paroz <claude 2xlibre net>.
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies 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.
+#
+# Damned Lies 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 Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from djamnedlies.stats.models import Statistics
+from django.contrib import admin
+
+admin.site.register(Statistics)
+
Added: branches/djamnedlies/stats/conf/__init__.py
==============================================================================
Added: branches/djamnedlies/stats/conf/settings.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/conf/settings.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,5 @@
+from django.conf import settings
+
+WEBROOT = "/stats"
+POTDIR = "/home/claude/www/damned-lies/cvs/POT"
+SCRATCHDIR = "/home/claude/www/damned-lies/cvs/"
Added: branches/djamnedlies/stats/data/bar.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/cyan-bar.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/download.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/emptyimg.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/error.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/figure.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/foot-16.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/foot.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/general_bg.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/general_separator.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/gnome-64.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/gnome-gtp.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/green-bar.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/info.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/layout.css
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/data/layout.css Mon Oct 20 21:34:37 2008
@@ -0,0 +1,442 @@
+/* Basic tags */
+body {
+ margin: 0px;
+ background-color: white;
+ font-family: sans-serif;
+ color: black;
+}
+
+#body {
+ margin: 90px 230px 0px 10px;
+ padding: 0px;
+}
+
+a img {
+ border: 0px;
+}
+
+/* Anchors */
+a {
+ color: #0000ff;
+}
+
+a:visited {
+ color: #551a8b;
+}
+
+a:active {
+ color: #ff0000;
+}
+
+/* Basic classes */
+
+.none { /* to add paragraph spacing to various elements for ttys */
+ margin: 0px;
+ padding: 0px;
+}
+
+.invisible { /* stuff that should appear when this css isn't used */
+ margin: 0px;
+ border: 0px;
+ padding: 0px;
+ height: 0px;
+ visibility: hidden;
+}
+
+.left {
+ margin: 10px;
+ padding: 0px;
+ float: left;
+}
+
+.right {
+ margin: 10px;
+ padding: 0px;
+ float: right;
+}
+
+.center {
+ text-align: center;
+}
+
+/* Common page elements: Header, footer, etc. */
+
+#logo {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ border: 0px;
+ z-index: 10;
+
+ width: 64px;
+ height: 64px;
+}
+
+#logo a img {
+ width: 64px;
+ height: 64px;
+}
+
+#hdr {
+ position: absolute;
+ z-index: 5;
+
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ width: 100%;
+ height: 48px;
+
+ text-align: right;
+
+ background-color: #e3ffc3;
+ border-bottom: 1px solid #807d74;
+}
+
+#banner {
+ position: absolute;
+ z-index: 10;
+
+ top: 0px;
+ right: 0px;
+ border: 0px;
+
+ width: 300px;
+ height: 48px;
+
+}
+
+#banner a img {
+ width: 300px;
+ height: 48px;
+}
+
+#hdrNav {
+ position: absolute;
+ top: 54px;
+ left: 0px;
+
+ margin-left: 84px;
+ text-align: left;
+ vertical-align: middle;
+ font-size: small;
+}
+
+#hdrNav a {
+ color: #000000;
+}
+
+#hdrTitle {
+ height: 48px;
+ padding: 10px 10px 0px 0px;
+ font-weight: bold;
+}
+
+
+/* Search thingy */
+
+#search {
+ font-size: small;
+ margin-bottom: 10px;
+ padding: 10px;
+ background-color: #dddddd;
+}
+
+#search input {
+ border: 1px solid #666666;
+ background-color: #ffffff;
+
+ vertical-align: middle;
+}
+
+
+/* Sidebar */
+
+#sidebar {
+ position: absolute;
+ top: 90px;
+ right: 0px;
+ width: 210px;
+
+ /*margin-right: 10px;*/
+ padding-right: 10px;
+ padding-bottom: 0px;
+ border-left: 1px dashed #dddddd;
+ background-color: #ffffff;
+}
+
+#sidebar p {
+ margin-top: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+#sidebar p.section {
+ text-align: center;
+ font-weight: bold;
+ padding-top: 3px;
+ padding-bottom: 3px;
+ color: #999999;
+ background-color: #eeeeee;
+}
+
+#sidebar ul {
+ margin: 0em;
+ margin-bottom: 15px;
+ padding-left: 10px;
+ padding-right: 10px;
+ list-style-type: none;
+}
+
+#sidebar ul ul {
+ padding-left: 2em;
+ padding-right: 0em;
+ list-style-type: square;
+}
+
+
+/* Copyright footer */
+
+#copyright {
+ text-align: center;
+ font-size: small;
+ clear: both;
+
+ margin-top: 10px;
+ padding: 5px 0px 5px 0px;
+ color: #aaaaaa;
+}
+
+#copyright a {
+ color: #aaaaff;
+}
+
+#copyright a:visited {
+ color: #ffaaaa;
+}
+
+
+/* News Sections */
+
+p.newsitem {
+ clear: left;
+ margin-bottom: 20px;
+}
+
+p.newsitem img.newsicon {
+ float: left;
+ margin: 0px 10px 10px 10px;
+ border: 0px;
+}
+
+
+/* Generic Classes */
+
+div.code {
+ background-color: #e0e0e0;
+ color: #000000;
+ white-space: pre;
+ font-family: monospace;
+}
+
+
+body {
+ margin: 0px;
+ padding: 0px;
+ font-family: sans-serif;
+ background: white url(star.png) -100px -200px no-repeat;
+ height: 101%;
+}
+
+#page {
+ margin: 0px;
+ padding: 0px;
+}
+
+div.in-column {
+ margin: 0 0 2em 1em;
+ float: right;
+ max-width: 12em;
+}
+
+hr {
+ color: #888;
+ background: #888;
+ border: 0;
+ height: 1px;
+ width: 90%;
+ text-align: center;
+ clear: both;
+}
+
+
+div.body {
+ clear: both;
+}
+
+
+div.sidebar {
+ position: absolute;
+ text-align: left;
+ right: 0px;
+ top: 60px;
+ width: 27ex;
+ padding-left: 1ex;
+ border-left: 1ex solid #eee;
+ margin-top: 4em;
+}
+
+div.sidebar h2 {
+ margin-top: 0;
+ padding: 5px 2ex 5px 2ex;
+ background: url(t.png) top left repeat-y;
+ font-size: 100%;
+}
+
+ul.toc {
+ padding: 0;
+ padding-left: 20px;
+ margin-left: 0;
+ margin-right: 10px;
+ list-style: none;
+}
+
+ul.toc li {
+ list-style: circle;
+}
+
+ul.toc li a {
+ text-decoration: none;
+ color: black;
+}
+
+ul.toc li a:hover {
+ text-decoration: underline;
+}
+
+#general {
+ list-style: none;
+ background: #2E3436 url(general_bg.png) 0 100% repeat-x;
+ text-align: right;
+ padding: 0 1ex;
+ margin: 0;
+ font-size: 70%;
+}
+
+#general li {
+ display: inline;
+ background: url(general_separator.png) 0 0 no-repeat;
+ padding-top: 10px;
+ padding-bottom: 8px;
+ margin-left: 0px;
+ margin-top: 0px;
+}
+
+#general li a {
+ font-weight: bold;
+ color: #FFFFFF;
+ margin: 0 2ex;
+ text-decoration: none;
+ line-height: 30px;
+}
+
+#general li a:hover {
+ text-decoration: underline;
+}
+
+#general .home {
+ float: left;
+ background: url(general_separator.png) 100% 0 no-repeat;
+ padding-top: 0;
+ padding-bottom: 0;
+}
+
+#general .home a {
+ float: left;
+ background: url(foot.png) 7px 50% no-repeat;
+ margin-left: 0;
+ padding-left: 27px;
+}
+
+
+#header {
+ background: #729FCF url(gnome-gtp.png) 15px 10px no-repeat;
+ float: left;
+ width: 100%;
+ font-size: 75%;
+}
+
+#header h1 {
+ margin: 0;
+ margin-left: 85px;
+ padding-top: 25px;
+ font-size: 200%;
+ color: #eeeeec;
+}
+
+#tabs {
+ background: url(bar.png) 0 100% repeat-x;
+ width: 100%;
+ float: left;
+ margin: 0;
+ padding: 0;
+}
+
+#portal-globalnav {
+ float: right;
+ list-style: none;
+ margin: 0;
+ margin-right: 3ex;
+}
+
+#portal-globalnav li {
+ float: left;
+ margin: 0;
+ margin-left: 0.2ex;
+ font-size: 2ex;
+}
+
+#portal-globalnav li a:hover {
+ color: #111111;
+}
+
+#portal-globalnav li a {
+ float: left;
+ text-decoration: none;
+ color: #555555;
+ background: url(tab_left.png) 0 0 no-repeat;
+ padding: 7px 0 7px 7px;
+ border-bottom: 2px solid #CCCCCC;
+}
+
+#portal-globalnav li span {
+ background: url(tab_right.png) 100% 0 no-repeat;
+ padding: 7px 28px 7px 19px;
+}
+
+#portal-globalnav li.selected a {
+ color: #3566A5;
+ background: url(tab_left.png) 0 -57px no-repeat;
+ border-bottom: none;
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+#portal-globalnav li.selected a span {
+ background: url(tab_right.png) 100% -57px no-repeat;
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+/* page content */
+
+div#content {
+ clear: both;
+ padding: 1em;
+ margin: 1em;
+}
+
+/*show a foot logo instead of dots in some lists*/
+ul.foot li {
+ list-style-image: url('foot-16.png');
+}
Added: branches/djamnedlies/stats/data/main.css
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/data/main.css Mon Oct 20 21:34:37 2008
@@ -0,0 +1,146 @@
+.stats th {
+ text-align: left;
+ background: gray;
+ color: white;
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+.stats td {
+ background: #f0f0f0;
+ text-align: center;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: black;
+}
+
+.stats td.leftcell {
+ text-align: left;
+}
+
+h2 {
+ width: 100%;
+ margin-top: 2em;
+ border-bottom: 1px solid gray;
+}
+
+div.graph {
+ height: 14px;
+ width: 100px;
+ border: 0px solid black;
+ position: relative;
+}
+
+div.translated {
+ position: absolute;
+ top: 0px;
+ height:100%;
+ left: 0%;
+ background: #448844;
+ background: url('green-bar.png');
+ background-repeat: repeat-x;
+ color: black;
+}
+
+div.goodchange {
+ position: absolute;
+ top: 0px;
+ height:100%;
+ background: #55DD55;
+ background: url('cyan-bar.png');
+ background-repeat: repeat-x;
+ color: black;
+}
+
+div.fuzzy {
+ position: absolute;
+ top: 0px;
+ height:100%;
+ background: #4444AA;
+ background: url('purple-bar.png');
+ background-repeat: repeat-x;
+ color: black;
+}
+
+div.untranslated {
+ position: absolute;
+ height:100%;
+ top: 0px;
+ background: #FF4444;
+ background: url('red-bar.png');
+ background-repeat: repeat-x;
+ color: black;
+}
+
+a {
+ text-decoration: none;
+ color: #406080;
+}
+
+a:hover, a:visited {
+ color: #6080a0;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+
+table {
+ width: 100%;
+}
+
+td.fuzzy {
+ background: #c98e7f;
+}
+
+img {
+ border: 0px;
+}
+
+img.people {
+ float: left;
+ margin-left: -85px;
+}
+
+img.screenshot {
+ max-width: 550px;
+ border: 0;
+}
+
+div.maintainer {
+ padding-left: 85px;
+ margin-bottom: 12px;
+ clear: both;
+}
+
+div.mainpage {
+ width:80%;
+ text-align: left;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+div.col1 { float: left }
+div.col2 { float: left }
+div.col3 { float: left }
+
+p#show, p#hide {
+ text-align: right;
+ font-style: italic;
+}
+
+.path {
+ font-size: x-small;
+ font-style: italic;
+ color: #666666;
+}
+
+.footnote {
+ text-align: center;
+ font-size: small;
+ clear: both;
+ margin-top: 20px;
+ color: #aaaaaa;
+}
+
Added: branches/djamnedlies/stats/data/main.js
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/data/main.js Mon Oct 20 21:34:37 2008
@@ -0,0 +1,30 @@
+// ***
+// This function shows or hides all modules in a release that are
+// 100% translated
+// ***
+function showHideCompleted() {
+ var regex = /complete$/i;
+
+ var tbls = document.getElementsByName("stats-table");
+ for (var tb=0; tb < tbls.length; tb++) {
+ var translations = tbls[tb].getElementsByTagName("tr");
+
+ for(var i=0;i<translations.length;i++) {
+ if ( regex.exec(translations[i].id) ) {
+ if ( translations[i].style.display != 'none' ) {
+ translations[i].style.display = 'none';
+ }
+ else {
+ translations[i].style.display = '';
+ }
+ }
+ }
+ }
+
+ var hide = document.getElementById("hide");
+ var show = document.getElementById("show");
+
+ hide.style.display = (hide.style.display != 'none' ? 'none' : '' );
+ show.style.display = (show.style.display != 'none' ? 'none' : '' );
+ return false;
+}
Added: branches/djamnedlies/stats/data/nobody.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/purple-bar.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/red-bar.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/rtl.css
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/data/rtl.css Mon Oct 20 21:34:37 2008
@@ -0,0 +1,30 @@
+.stats th {
+ text-align: right;
+ padding-right: 2px;
+ padding-left: 2px;
+}
+
+.stats td {
+ padding-right: 2px;
+ padding-left: 2px;
+}
+
+.stats td.left {
+ text-align: right;
+}
+
+div.translated {
+ right: 0%;
+}
+
+div.maintainer {
+ padding-right: 85px;
+ background-position: top right;
+}
+
+div.mainpage {
+ width:80%;
+ text-align: right;
+ margin-left: auto;
+ margin-right: auto;
+}
Added: branches/djamnedlies/stats/data/star.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/style.css
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/data/style.css Mon Oct 20 21:34:37 2008
@@ -0,0 +1,151 @@
+/**
+ * Styles that are not a part of page layout.
+ *
+ * For example:
+ * Fonts
+ * Sizes
+ * Decoration
+ * Separators
+ */
+body * {
+ font-family: verdana, arial, sans-serif;
+}
+
+div#content a {
+ color: #3465a4;
+ border-bottom: 1px dotted #888;
+ text-decoration: none;
+}
+
+div#content a:hover {
+ border-bottom: 1px solid #888;
+}
+
+
+h1.first {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+h2, h3, h4, h5, h6 {
+ color: #3f3f3f;
+}
+
+h1 {
+ font-size: 1.4em;
+}
+
+h2 {
+ font-size: 1.2em;
+}
+
+h3 {
+ font-size: 1.0em;
+}
+
+/* lists */
+.list {
+ margin-top:.5em;
+}
+.list tr td {
+ padding:.2em;
+ text-align:left;
+}
+.list td label {
+ border-bottom:1px dashed #999;
+ font-weight:normal;
+}
+.list th {
+ background: #ccf;
+ border: 1px solid #000;
+ font-weight: bold;
+ padding: 2px;
+}
+.list th a {
+ display: block;
+ padding:.2em 1.2em .2em .2em;
+ text-align: left;
+}
+.list th a:hover {
+ background-color: #fff;
+}
+.row1 {
+ background-color: #eee;
+}
+.row2 {
+ background-color: #ddd;
+}
+.row1:hover, .row2:hover {
+ background-color: #fff;
+}
+
+.record th {
+ text-align: right;
+}
+
+/* styling page content */
+
+h1 {
+ font-size: 1.5em;
+ color: #3f3f3f;
+}
+
+/* styling form widgets like bugzilla.gnome.org */
+input,textarea {
+ border: 1px solid #6f6f6f;
+/* background: #dddddd; */
+}
+
+input.login_small {
+ border-style: none;
+}
+
+input:focus,textarea:focus {
+ background-color: #f7f2d0;
+ color: #000000;
+}
+
+/* select {
+ border: groove
+} */
+
+option {
+ border: 0px none #ffffff;
+}
+
+input[type=radio] {
+ margin-left: 1em;
+}
+
+/* footer */
+
+#footer {
+ text-align: center;
+ margin: 3em 3em 1em 3em;
+ border-top: 1px solid gray;
+ padding-top: 1.5em;
+ color: #888;
+ font-size: 80%;
+ clear: both;
+}
+
+#footer ul {
+ margin: 0;
+ padding: 0;
+}
+
+#footer li {
+ display: inline;
+ padding: 0 1em;
+}
+
+#footer a {
+ color: #3465a4;
+ border-bottom: 1px dotted #888;
+ text-decoration: none;
+}
+
+#footer a:hover {
+ border-bottom: 1px solid #888
+}
+
Added: branches/djamnedlies/stats/data/t.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/tab_left.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/tab_right.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/warn.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/data/webpage.png
==============================================================================
Binary file. No diff available.
Added: branches/djamnedlies/stats/defaults.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/defaults.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+# Directory to checkout source code and dump dead bodies to
+scratchdir = u"/home/danilo/cvs/gnom"
+
+# Web root directory
+webroot = ''
+
+# whether to generate translated XML documentation (might slow down the process significantly)
+# they'll be put into os.path.join(scratchdir,"xml")
+generate_docs = 0
+
+WHEREAREWE = 'http://i18n-status.gnome.org/'
+WHOAREWE = 'danilo gnome org'
+
+# When in STRINGFREEZE, where to send notifications (gnome-i18n gnome org) on any POT changes
+notifications_to = 'gnome-i18n gnome org'
+notifications_to = 'danilo smorisa kvota net'
+
+# Whether to use fuzzy matching (much slower, but better for translators), use 0 only when testing!
+fuzzy_matching = 0
+
+# Set DEBUG to 1 to print (too) many messages on stderr about progress
+DEBUG = 1
+
+# WARNING:
+# You usually don't want to set most of the things below,
+# unless you are using Damned Lies for something other than GNOME
+
+
+# Directory to hold resulting POT/PO files
+import os.path
+potdir = os.path.join(scratchdir, "POT")
+
+# default to Gnome Bugzilla, product same as module ID and component "general"
+bugzilla = {
+ "baseurl" : u"http://bugzilla.gnome.org/",
+ "xmlrpc" : u"http://bugzilla-test.gnome.org/xmlrpc.cgi",
+ "product" : u"",
+ "component" : u"general",
+ }
+
+# default to a single "po" directory containing UI translations, and module ID for POT name
+translation_domains = {
+ u"po" : {"description" : u"UI translations", "potbase": ""} # description, base potname
+ }
+
+# default to a single "help" document containing User Guide
+documents = {
+ u"help" : {"description" : u"User Guide", "potbase" : "" }
+ }
+
+# default to anonyomus Gnome CVS
+cvsroot = u":pserver:anonymous anoncvs gnome org:/cvs/gnome"
+cvsweb = u"http://cvs.gnome.org/viewcvs/%(module)s?only_with_tag=%(branch)s"
+cvsbranch = {
+ u"HEAD": { "translation_domains": translation_domains,
+ "documents": documents,
+ }
+ }
+
+# Default language to fallback to
+language = 'en'
+
+# Right-to-left languages
+rtl_languages = [ 'ar', 'fa', 'he', 'urd', 'yi']
+
+# Dummy function for deferred translation (error messages)
+# See http://docs.python.org/lib/node742.html
+def N_(message): return message.replace("%s","###%s###")
Added: branches/djamnedlies/stats/management/__init__.py
==============================================================================
Added: branches/djamnedlies/stats/management/commands/__init__.py
==============================================================================
Added: branches/djamnedlies/stats/management/commands/migrate.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/management/commands/migrate.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,193 @@
+from django.core.management.base import BaseCommand
+import os
+import data
+from djamnedlies.stats.models import Person, Team, Language, Module, Branch, Domain, Release, Category, Statistics
+
+class Command(BaseCommand):
+ """ Before the migration:
+ 1. cp or link the legacy D-L data.py file in this directory
+ 2. set the xml_base directory where you can find the original .xml files to migrate their content """
+
+ help = "Migrate current D-L XML files into database content"
+
+ output_transaction = False
+ xml_base = ""
+
+ def handle(self, app, **options):
+ #drop table language;drop table module;drop table module_maintainer;drop table person;drop table release;drop table category;drop table team;drop table branch;
+
+ print self.migratePeople()
+ print self.migrateTeams()
+ print self.migrateModules()
+ print self.migrateReleases()
+ print self.migrateStats()
+
+ return "Migration completed."
+
+ def migratePeople(self):
+ people = data.readFromFile(os.path.join(self.xml_base, "people.xml"))
+ for key, p in people.items():
+ if not p.has_key('bugzilla-account'):
+ p['bugzilla-account'] = None
+ if p['id'][:2] != "x-":
+ p['svn-account'] = p['id']
+ else:
+ p['svn-account'] = None
+ new_p = Person(old_id=p['id'], name=p['name'],
+ email=p['email'], svn_account=p['svn-account'], image=p['icon'],
+ webpage_url=p['webpage'], irc_nick=p['nick'],
+ bugzilla_account=p['bugzilla-account'])
+ new_p.save()
+ return "People migrated successfully"
+
+ def migrateTeams(self):
+ teams = data.readFromFile(os.path.join(self.xml_base, "translation-teams.xml"))
+ for key, team in teams.items():
+ if len(team['language'].items()) <= 1:
+ team['description'] = team['language'].items()[0][1]['content']
+ coord = Person.objects.get(old_id=team['coordinator'].keys()[0])
+ if not team.has_key('mailing-list'):
+ team['mailing-list'] = None
+ if not team.has_key('mailing-list-subscribe'):
+ team['mailing-list-subscribe'] = None
+ if not team.has_key('description'):
+ team['description'] = 'Catalan'
+ print "Forced Catalan description"
+ new_t = Team(lang_code=key, description=team['description'], coordinator=coord,
+ webpage_url=team['webpage'],
+ mailing_list=team['mailing-list'],
+ mailing_list_subscribe=team['mailing-list-subscribe'])
+ new_t.save()
+ for lkey, lang in team['language'].items():
+ new_l = Language(name=lang['content'],
+ locale=lang['id'], team=new_t)
+ new_l.save()
+ return "Teams migrated successfully"
+
+ def migrateModules(self):
+ modules = data.readFromFile(os.path.join(self.xml_base, "gnome-modules.xml"))
+ for key, module in modules.items():
+ for prop in ['webpage', 'comment']:
+ if not module.has_key(prop):
+ module[prop] = None
+ new_m = Module(name=module['id'], description=module['description'],
+ homepage=module['webpage'], comment=module['comment'],
+ bugs_base=module['bugs-baseurl'], bugs_product=module['bugs-product'], bugs_component=module['bugs-component'],
+ vcs_type=module['scmroot']['type'], vcs_root=module['scmroot']['path'], vcs_web=module['scmweb'])
+ new_m.save()
+ # Adding maintainers
+ if module.has_key('maintainer'):
+ for m in module['maintainer'].items():
+ person = Person.objects.get(old_id=m[0])
+ new_m.maintainers.add(person)
+ # Adding branches
+ for bkey, bval in module['branch'].items():
+ new_b = Branch(name=bkey, module=new_m)
+ new_b.save()
+ # Adding domains (to module), if not exist
+ for dkey, dval in bval['domain'].items():
+ if dval.has_key('directory'):
+ ddir = dval['directory']
+ else:
+ ddir = 'po'
+ existing_d = Domain.objects.filter(module=new_m, dtype='ui', directory=ddir)
+ if len(existing_d) < 1:
+ if not dval.has_key('description'):
+ dval['description'] = None
+ new_domain = Domain(module=new_m, name=dkey, description=dval['description'], dtype='ui', directory=ddir)
+ new_domain.save()
+ #else:
+ for dkey, dval in bval['document'].items():
+ if dval.has_key('directory'):
+ ddir = dval['directory']
+ else:
+ ddir = 'help'
+ existing_d = Domain.objects.filter(module=new_m, dtype='doc', directory=ddir)
+ if len(existing_d) < 1:
+ if not dval.has_key('description'):
+ dval['description'] = None
+ new_domain = Domain(module=new_m, name=dkey, description=dval['description'], dtype='doc', directory=ddir)
+ new_domain.save()
+
+ return "Modules migrated successfully"
+
+ def migrateReleases(self):
+ releases = data.readFromFile(os.path.join(self.xml_base, "releases.xml"))
+ for key, release in releases.items():
+ try:
+ new_r = Release.objects.get(name=release['description'])
+ except:
+ new_r = Release(name=release['description'], stringfrozen=False, status=release['status'])
+ new_r.save()
+ if release.has_key('category'):
+ for catname, catcontent in release['category'].items():
+ relcat = Category(release=new_r, description=catcontent['description'])
+ relcat.save()
+ for mod, content in catcontent['module'].items():
+ # find the right component
+ module = Module.objects.get(name=mod)
+ if content.has_key('branch'):
+ branch_name = content['branch']
+ else:
+ if module.vcs_type == 'git':
+ branch_name = u'master'
+ else:
+ branch_name = u'HEAD'
+ # set the release field of the branch (with relcat)
+ for br in module.branch_set.all():
+ if br.name == branch_name:
+ br.category = relcat
+ br.save()
+ else:
+ relcat = Category(release=new_r, description='default')
+ relcat.save()
+ for mod, content in release['module'].items():
+ module = Module.objects.get(name=mod)
+ if content.has_key('branch'):
+ branch_name = content['branch']
+ else:
+ if module.vcs_type == 'git':
+ branch_name = u'master'
+ else:
+ branch_name = u'HEAD'
+ # set the release field of the branch (with relcat)
+ for br in module.branch_set.all():
+ if br.name == branch_name:
+ br.category = relcat
+ br.save()
+ return "Releases migrated successfully"
+
+ def migrateStats(self):
+ stats = Statistics.objects.all()
+ for stat in stats:
+ # link to Branch, Domain and Language
+ try:
+ mod = Module.objects.get(name=stat.Module)
+ except:
+ print "Unable to find module corresponding to '%s'." % stat.Module
+ continue
+ try:
+ br = Branch.objects.get(name=stat.Branch, module=mod.id)
+ except:
+ print "Unable to find branch corresponding to '%s.%s'." % (stat.Module, stat.Branch)
+ continue
+ if stat.Language is not None:
+ try:
+ lang = Language.objects.get(locale=stat.Language)
+ except:
+ lang = Language(name=stat.Language,
+ locale=stat.Language)
+ lang.save()
+ print "Unable to find language corresponding to '%s'. Language created." % (stat.Language)
+ else:
+ # The POT file
+ lang = None
+ stat.branch = br
+ stat.language = lang
+ for p in mod.domain_set.all():
+ if p.dtype == stat.Type and p.name == stat.Domain:
+ stat.domain = p
+ break
+ #import pdb; pdb.set_trace()
+ stat.save()
+ return "Statistics migrated successfully"
Added: branches/djamnedlies/stats/models.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/models.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,647 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2008 Claude Paroz <claude 2xlibre net>.
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies 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.
+#
+# Damned Lies 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 Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from django.db import models, connection
+from django.utils.translation import ungettext, ugettext as _
+from stats.conf import settings
+from stats import utils
+from time import tzname
+import os, re, commands
+
+class Person(models.Model):
+ old_id = models.CharField(max_length=50)
+ name = models.CharField(max_length=50)
+ email = models.CharField(max_length=50)
+ svn_account = models.CharField(max_length=20, null=True)
+ image = models.CharField(max_length=50, null=True)
+ webpage_url = models.CharField(max_length=50, null=True)
+ irc_nick = models.CharField(max_length=20, null=True)
+ bugzilla_account = models.CharField(max_length=50, null=True)
+ class Meta:
+ db_table = 'person'
+
+ def nospamemail(self):
+ return utils.obfuscateEmail(self.email)
+ def nospambugzillaaccount(self):
+ return utils.obfuscateEmail(self.bugzilla_account)
+
+class Language(models.Model):
+ name = models.CharField(max_length=50)
+ locale = models.CharField(max_length=15)
+ team = models.ForeignKey('Team', null=True)
+ class Meta:
+ db_table = 'language'
+
+ def bugs_url_enter(self):
+ return "http://bugzilla.gnome.org/enter_bug.cgi?product=l10n&component=%s%%20[%s]" % (self.name, self.locale)
+
+ def bugs_url_show(self):
+ return "http://bugzilla.gnome.org/buglist.cgi?product=l10n&component=%s%%20[%s]&bug_status=NEW&bug_status=REOPENED&bug_status=ASSIGNED&bug_status=UNCONFIRMED" % (self.name, self.locale)
+
+ def get_release_stats(self):
+ """ Get summary stats for all releases """
+ releases = Release.objects.all().order_by('status', '-name')
+ stats = []
+ for rel in releases:
+ stats.append(rel.total_for_lang(self))
+ return stats
+
+class Team(models.Model):
+ lang_code = models.CharField(max_length=15, unique=True)
+ description = models.TextField()
+ coordinator = models.ForeignKey('Person')
+ webpage_url = models.CharField(max_length=50, null=True)
+ mailing_list = models.CharField(max_length=50, null=True)
+ mailing_list_subscribe = models.CharField(max_length=50, null=True)
+
+ class Meta:
+ db_table = 'team'
+
+ def __unicode__(self):
+ return self.description
+
+class Module(models.Model):
+ name = models.CharField(max_length=50)
+ homepage = models.CharField(max_length=50, null=True)
+ description = models.TextField(null=True)
+ comment = models.TextField(null=True)
+ bugs_base = models.CharField(max_length=50)
+ bugs_product = models.CharField(max_length=50)
+ bugs_component = models.CharField(max_length=50)
+ vcs_type = models.CharField(max_length=5, choices=(('cvs', 'CVS'),
+ ('svn', 'Subversion'),
+ ('git', 'Git'),
+ ('hg', 'Mercurial'),
+ ('bzr', 'Bazaar')))
+ vcs_root = models.CharField(max_length=50)
+ vcs_web = models.CharField(max_length=50)
+
+ maintainers = models.ManyToManyField(Person, db_table='module_maintainer')
+ class Meta:
+ db_table = 'module'
+
+ def get_bugs_i18nurl(self):
+ if self.bugs_base.find("bugzilla") != -1 or self.bugs_base.find("freedesktop") != -1:
+ return "%sbuglist.cgi?product=%s&component=%s&keywords_type=anywords&keywords=I18N+L10N&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=NEEDINFO" % (self.bugs_base, self.bugs_product, self.bugs_component)
+ else:
+ return None
+
+ def get_bugs_enterurl(self):
+ if self.bugs_base.find("bugzilla") != -1 or self.bugs_base.find("freedesktop") != -1:
+ return "%senter_bug.cgi?product=%s&component=%s" % (self.bugs_base, self.bugs_product, self.bugs_component)
+ else:
+ return self.bugs_base
+
+ def compare_branches(self, a, b):
+ if a.name in ('HEAD', 'master'):
+ return -1
+ elif b.name in ('HEAD', 'master'):
+ return 1
+ else:
+ return cmp(a.name, b.name)*-1
+
+ def get_branches(self):
+ branches = [b for b in self.branch_set.all()]
+ branches.sort(self.compare_branches)
+ return branches
+
+class Branch(models.Model):
+ """ Branch of a module """
+ name = models.CharField(max_length=50)
+ #description = models.TextField(null=True)
+ module = models.ForeignKey(Module)
+ category = models.ForeignKey('Category', null=True)
+ class Meta:
+ db_table = 'branch'
+
+ def is_head(self):
+ if self.module.vcs_type in ('cvs', 'svn') and self.name == "HEAD":
+ return True
+ elif self.module.vcs_type == 'git' and self.name == "master":
+ return True
+ return False
+
+ def get_vcsurl(self):
+ if self.is_head():
+ return "%s/%s/trunk" % (self.module.vcs_root, self.module.name)
+ else:
+ return "%s/%s/branches/%s" % (self.module.vcs_root, self.module.name, self.name)
+
+ def get_vcsweburl(self):
+ if self.is_head():
+ return "%s/trunk" % (self.module.vcs_web)
+ else:
+ return "%s/branches/%s" % (self.module.vcs_web, self.name)
+
+ def co_path(self):
+ """ Returns the path of the local checkout for the branch """
+ return os.path.join(settings.SCRATCHDIR, self.module.vcs_type, self.module.name + "." + self.name)
+
+ def get_stats(self, typ):
+ """ Get statistics list of type typ ('ui' or 'doc'), in a dict of lists, key is domain.name (POT in 1st position)"""
+ stats = {}
+ for stat in self.statistics_set.order_by('Translated').reverse():
+ if stat.domain.dtype == typ:
+ if stats.has_key(stat.domain.name):
+ if stat.Language:
+ stats[stat.domain.name].append(stat)
+ else:
+ stats[stat.domain.name].insert(0, stat) # This is the POT file
+ else:
+ stats[stat.domain.name] = [stat,]
+ # sort by domain, then translated
+ #templist = [(obj_.domain_id, obj_.Translated, obj_) for obj_ in stats]
+ #templist.sort()
+ #return [obj_ for (key1, key2, obj_) in templist]
+ return stats
+
+ def get_docstats(self):
+ return self.get_stats('doc')
+ def get_uistats(self):
+ return self.get_stats('ui')
+
+class Domain(models.Model):
+ module = models.ForeignKey(Module)
+ name = models.CharField(max_length=50)
+ description = models.TextField(null=True)
+ dtype = models.CharField(max_length=5, choices=(('ui', 'User Interface'), ('doc', 'Documentation')))
+ directory = models.CharField(max_length=50)
+ class Meta:
+ db_table = 'domain'
+
+class Release(models.Model):
+ name = models.CharField(max_length=50)
+ stringfrozen = models.BooleanField()
+ status = models.CharField(max_length=12, choices=(('official', 'Official'), ('unofficial', 'Unofficial'), ('external', 'External')))
+ class Meta:
+ db_table = 'release'
+
+ def total_strings(self):
+ """ Returns the total number of strings in the release as a tuple (doc_total, ui_total) """
+ # TODO: transform this SQL query in a Django model query, if possible...
+ query = """ SELECT domain.dtype, SUM(stat.untranslated) FROM statistics AS stat
+ LEFT JOIN domain ON domain.id=stat.domain_id
+ LEFT JOIN branch AS br ON br.id=stat.branch_id
+ LEFT JOIN category AS cat ON br.category_id=cat.id
+ LEFT JOIN release AS rel ON rel.id = cat.release_id
+ WHERE rel.id=%s AND stat.language_id IS NULL
+ GROUP BY domain.dtype """
+ cursor = connection.cursor()
+ cursor.execute(query, (self.id,))
+ totaldoc = 0; totalui = 0
+ for row in cursor.fetchall():
+ if row[0] == 'ui':
+ totalui = row[1]
+ elif row[0] == 'doc':
+ totaldoc = row[1]
+ return (totaldoc, totalui)
+
+ def total_for_lang(self, lang):
+ """ Returns total translated/fuzzy/untranslated strings for a specific language """
+
+ total_doc, total_ui = self.total_strings()
+ query = """SELECT domain.dtype, SUM(stat.translated), SUM(stat.fuzzy) FROM statistics AS stat
+ LEFT JOIN domain ON stat.domain_id=domain.id
+ LEFT JOIN branch ON stat.branch_id=branch.id
+ LEFT JOIN category ON branch.category_id=category.id
+ WHERE language_id = %s AND category.release_id = %s
+ GROUP BY domain.dtype;"""
+ cursor = connection.cursor()
+ cursor.execute(query, (lang.id, self.id))
+ stats = {'id': self.id, 'name': _(self.name),
+ 'uitrans':0, 'uifuzzy':0, 'uitotal':total_ui,
+ 'doctrans':0, 'docfuzzy':0, 'doctotal':total_doc,
+ 'uitransperc':0, 'uifuzzyperc':0, 'uiuntransperc':0,
+ 'doctransperc':0, 'docfuzzyperc':0, 'docuntransperc':0}
+ for res in cursor.fetchall():
+ if res[0] == 'ui':
+ stats['uitrans'] = res[1]
+ stats['uifuzzy'] = res[2]
+ if res[0] == 'doc':
+ stats['doctrans'] = res[1]
+ stats['docfuzzy'] = res[2]
+ stats['uiuntrans'] = total_ui - (stats['uitrans'] + stats['uifuzzy'])
+ if total_ui > 0:
+ stats['uitransperc'] = 100*stats['uitrans']/total_ui
+ stats['uifuzzyperc'] = 100*stats['uifuzzy']/total_ui
+ stats['uiuntransperc'] = 100*stats['uiuntrans']/total_ui
+ stats['docuntrans'] = total_doc - (stats['doctrans'] + stats['docfuzzy'])
+ if total_doc > 0:
+ stats['doctransperc'] = 100*stats['doctrans']/total_doc
+ stats['docfuzzyperc'] = 100*stats['docfuzzy']/total_doc
+ stats['docuntransperc'] = 100*stats['docuntrans']/total_doc
+ return stats
+
+ def get_global_stats(self):
+ """ Get statistics for all languages in a release, grouped by language
+ Returns a sorted list: (language, doc_trans, doc_fuzzy, doc_untrans, ui_trans, ui_fuzzy, ui_untrans)"""
+
+ # TODO: transform this SQL query in a Django model query, if possible...
+ query = """SELECT lang.name, lang.locale, domain.dtype, SUM(stat.translated) AS trans, SUM(stat.fuzzy)
+ FROM statistics AS stat
+ LEFT JOIN domain ON domain.id=stat.domain_id
+ LEFT JOIN language AS lang ON stat.language_id=lang.id
+ LEFT JOIN branch AS br ON br.id=stat.branch_id
+ LEFT JOIN category ON br.category_id=category.id
+ WHERE category.release_id = %s
+ GROUP BY domain.dtype, stat.language_id
+ ORDER BY domain.dtype, trans desc;"""
+ cursor = connection.cursor()
+ cursor.execute(query, (self.id,))
+ stats = {}
+ total_docstrings, total_uistrings = self.total_strings()
+ for row in cursor.fetchall():
+ if not stats.has_key(row[1]):
+ # Initialize stats dict
+ stats[row[1]] = {'lang':row[0], 'lang_code':row[1], 'doc_trans':0, 'doc_fuzzy':0, 'doc_untrans': total_docstrings,
+ 'doc_percent':0, 'doc_percentfuzzy':0, 'doc_percentuntrans':100,
+ 'ui_trans':0, 'ui_fuzzy':0, 'ui_untrans': total_uistrings,
+ 'ui_percent':0, 'ui_percentfuzzy':0, 'ui_percentuntrans':100}
+ if row[2] == 'doc':
+ stats[row[1]]['doc_trans'] = row[3]
+ stats[row[1]]['doc_fuzzy'] = row[4]
+ stats[row[1]]['doc_untrans'] = total_docstrings - (row[3] + row[4])
+ stats[row[1]]['doc_percent'] = 100*row[3]/total_docstrings
+ stats[row[1]]['doc_percentfuzzy'] = 100*row[4]/total_docstrings
+ stats[row[1]]['doc_percentuntrans'] = 100*stats[row[1]]['doc_untrans']/total_docstrings
+ if row[2] == 'ui':
+ stats[row[1]]['ui_trans'] = row[3]
+ stats[row[1]]['ui_fuzzy'] = row[4]
+ stats[row[1]]['ui_untrans'] = total_uistrings - (row[3] + row[4])
+ stats[row[1]]['ui_percent'] = 100*row[3]/total_uistrings
+ stats[row[1]]['ui_percentfuzzy'] = 100*row[4]/total_uistrings
+ stats[row[1]]['ui_percentuntrans'] = 100*stats[row[1]]['ui_untrans']/total_uistrings
+ cursor.close()
+ results = [stat for key, stat in stats.items()]
+ results.sort(self.compare_stats)
+ return results
+
+ def compare_stats(self, a, b):
+ res = cmp(b['ui_trans'], a['ui_trans'])
+ if not res:
+ res = cmp(b['doc_trans'], a['doc_trans'])
+ if not res:
+ res = cmp(b['lang'], a['lang'])
+ return res
+
+ def get_lang_stats(self, lang):
+ """ Get statistics for a specific language, producing the stats data structure
+ Used for displaying the language-release template """
+
+ # Sorted by module to allow grouping ('fake' stats)
+ pot_stats = Statistics.objects.filter(language=None, branch__category__release=self).order_by('domain__module__id')
+ stats = {'doc':{'totaltrans':0, 'totalfuzzy':0, 'totaluntrans':0, 'categs':{}},
+ 'ui':{'totaltrans':0, 'totalfuzzy':0, 'totaluntrans':0, 'categs':{}}
+ }
+ for stat in pot_stats:
+ dtype = stat.domain.dtype
+ categdescr = stat.branch.category.description
+ domname = _(stat.domain.description)
+ modname = stat.domain.module.name
+ if not stats[dtype]['categs'].has_key(categdescr):
+ stats[dtype]['categs'][categdescr] = {'cattrans':0, 'catfuzzy':0,
+ 'catuntrans':0, 'modules':{}}
+ stats[dtype]['totaluntrans'] += stat.Untranslated
+ stats[dtype]['categs'][categdescr]['catuntrans'] += stat.Untranslated
+ if not stats[dtype]['categs'][categdescr]['modules'].has_key(modname):
+ # first element is a placeholder for a fake stat
+ stats[dtype]['categs'][categdescr]['modules'][modname] = {' fake':None, domname:stat}
+ previous_domname = domname
+ else:
+ if len(stats[dtype]['categs'][categdescr]['modules'][modname]) < 3:
+ # Create a fake statistics object for module summary
+ stats[dtype]['categs'][categdescr]['modules'][modname][' fake'] = FakeStatistics(stat.domain.module, dtype)
+ stats[dtype]['categs'][categdescr]['modules'][modname][' fake'].untrans(stats[dtype]['categs'][categdescr]['modules'][modname][previous_domname])
+ stats[dtype]['categs'][categdescr]['modules'][modname][domname] = stat
+ stats[dtype]['categs'][categdescr]['modules'][modname][' fake'].untrans(stat)
+ #stats[dtype]['categs'][categdescr]['modules']["%s-%s" % (stat.branch.id, stat.domain.id)] = stat
+
+ # Second pass for translated stats
+ tr_stats = Statistics.objects.filter(language=lang, branch__category__release=self).order_by('domain__module__id')
+ for stat in tr_stats:
+ dtype = stat.domain.dtype
+ categdescr = stat.branch.category.description
+ domname = _(stat.domain.description)
+ modname = stat.domain.module.name
+ stats[dtype]['totaltrans'] += stat.Translated
+ stats[dtype]['totalfuzzy'] += stat.Fuzzy
+ stats[dtype]['totaluntrans'] -= (stat.Translated + stat.Fuzzy)
+ stats[dtype]['categs'][categdescr]['cattrans'] += stat.Translated
+ stats[dtype]['categs'][categdescr]['catfuzzy'] += stat.Fuzzy
+ stats[dtype]['categs'][categdescr]['catuntrans'] -= (stat.Translated + stat.Fuzzy)
+ if stats[dtype]['categs'][categdescr]['modules'][modname][' fake']:
+ stats[dtype]['categs'][categdescr]['modules'][modname][' fake'].trans(stat)
+ # Replace POT stat by translated stat
+ stats[dtype]['categs'][categdescr]['modules'][modname][domname] = stat
+
+ # Compute percentages and sorting
+ for dtype in ['ui', 'doc']:
+ stats[dtype]['total'] = stats[dtype]['totaltrans'] + stats[dtype]['totalfuzzy'] + stats[dtype]['totaluntrans']
+ if stats[dtype]['total'] > 0:
+ stats[dtype]['totaltransperc'] = 100*stats[dtype]['totaltrans']/stats[dtype]['total']
+ stats[dtype]['totalfuzzyperc'] = 100*stats[dtype]['totalfuzzy']/stats[dtype]['total']
+ stats[dtype]['totaluntransperc'] = 100*stats[dtype]['totaluntrans']/stats[dtype]['total']
+ else:
+ stats[dtype]['totaltransperc'] = 0
+ stats[dtype]['totalfuzzyperc'] = 0
+ stats[dtype]['totaluntransperc'] = 0
+ for key, categ in stats[dtype]['categs'].items():
+ categ['cattotal'] = categ['cattrans'] + categ['catfuzzy'] + categ['catuntrans']
+ categ['cattransperc'] = 100*categ['cattrans']/categ['cattotal']
+ # Sort modules
+ mods = [[name,mod] for name, mod in categ['modules'].items()]
+ mods.sort()
+ categ['modules'] = mods
+ # Sort domains
+ for mod in categ['modules']:
+ doms = [(name,dom) for name, dom in mod[1].items()]
+ doms.sort()
+ mod[1] = doms
+ return stats
+
+
+class Category(models.Model):
+ release = models.ForeignKey(Release)
+ description = models.TextField()
+ class Meta:
+ db_table = 'category'
+
+
+class Statistics(models.Model):
+ # After migration, module, domain, type, branch, language can be deleted
+ branch = models.ForeignKey(Branch) #alter table statistics add branch_id integer REFERENCES "branch" ("id");
+ domain = models.ForeignKey(Domain) #alter table statistics add domain_id integer REFERENCES "domain" ("id");
+ language = models.ForeignKey(Language, null=True) #alter table statistics add language_id integer REFERENCES "language" ("id");
+
+ Module = models.TextField(db_column='module')
+ # whether this is about a document or UI translation
+ Type = models.CharField(db_column='type', max_length=3, choices=(('doc', 'Documentation'), ('ui', 'User Interface')))
+ Domain = models.TextField(db_column='domain')
+ Branch = models.TextField(db_column='branch')
+ Language = models.CharField(db_column='language', max_length=15)
+ Date = models.DateTimeField(db_column='date', auto_now_add=True)
+ Translated = models.IntegerField(db_column='translated', default=0)
+ Fuzzy = models.IntegerField(db_column='fuzzy', default=0)
+ Untranslated = models.IntegerField(db_column='untranslated', default=0)
+ class Meta:
+ db_table = 'statistics'
+
+ def __init__(self, *args, **kwargs):
+ models.Model.__init__(self, *args, **kwargs)
+ self.figures = None
+ self.modname = None
+ self.partial_po = False # True if part of a multiple po module
+
+ def __unicode__(self):
+ """ String representation of the object """
+ return "%s (%s-%s) %s (%s)" % (self.Module, self.Type, self.Domain,
+ self.Branch, self.Language)
+
+ def is_fake(self):
+ return False
+
+ def tr_percentage(self):
+ if self.pot_size() == 0:
+ return 0
+ else:
+ return 100*self.Translated/self.pot_size()
+
+ def fu_percentage(self):
+ if self.pot_size() == 0:
+ return 0
+ else:
+ return 100*self.Fuzzy/self.pot_size()
+
+ def un_percentage(self):
+ if self.pot_size() == 0:
+ return 0
+ else:
+ return 100*self.Untranslated/self.pot_size()
+
+ def get_lang(self):
+ if self.language:
+ return _("%(langname)s (%(langcode)s)") % {'langname':self.language.name, 'langcode':self.language.locale}
+ else:
+ return "pot file"
+
+ def module_name(self):
+ if not self.modname:
+ self.modname = self.branch.module.name
+ return self.modname
+
+ def module_description(self):
+ return self.branch.module.description
+
+ def get_translationstat(self):
+ return "%d%% (%d/%d/%d)" % (self.tr_percentage(), self.Translated, self.Fuzzy, self.Untranslated)
+
+ def filename(self):
+ if self.domain.name == 'po':
+ potbase = self.module_name()
+ else:
+ potbase = self.domain.name
+ if self.Language:
+ return "%s.%s.%s.po" % (potbase, self.branch.name, self.Language)
+ else:
+ return "%s.%s.pot" % (potbase, self.branch.name)
+
+ def pot_size(self):
+ return int(self.Translated) + int(self.Fuzzy) + int(self.Untranslated)
+
+ def pot_text(self):
+ msg_text = ungettext(u"%(count)s message", "%(count)s messages", self.pot_size()) % {'count': self.pot_size()}
+ upd_text = _(u"updated on %(date)s") % {'date': self.Date.strftime("%Y-%m-%d %H:%M:%S ")+tzname[0]}
+ if self.fig_count():
+ fig_text = ungettext(u"%(count)s figure", "%(count)s figures", self.fig_count()) % {'count': self.fig_count()}
+ text = _(u"POT file (%(messages)s, %(figures)s) â %(updated)s") % \
+ {'messages': msg_text, 'figures': fig_text, 'updated': upd_text}
+ else:
+ text = _(u"POT file (%(messages)s) â %(updated)s") % \
+ {'messages': msg_text, 'updated': upd_text}
+ return text
+
+ def get_figures(self):
+ if self.figures is None and self.domain.dtype == 'doc':
+ # Extract image strings: beforeline/msgid/msgstr/grep auto output a fourth line
+ command = "msgcat --no-wrap %(pofile)s| grep -A 1 -B 1 '^msgid \"@@image:'" % { 'pofile': self.po_path() }
+ (error, output) = commands.getstatusoutput(command)
+ lines = output.split('\n')
+ re_path = re.compile('^msgid \"@@image: \'([^\']*)\'')
+ self.figures = []
+
+ i = 0
+ while i < len(lines):
+ fig = {}
+ fig['fuzzy'] = lines[i]=='#, fuzzy'
+ path_match = re_path.match(lines[i+1])
+ if path_match and len(path_match.groups()):
+ fig['path'] = path_match.group(1)
+ else:
+ fig['path'] = '' # This should not happen
+ fig['translated'] = len(lines[i+2])>9 and not fig['fuzzy']
+ # Check if a translated figure really exists or if the English one is used
+ if os.path.exists(os.path.join(self.branch.co_path(), self.domain.directory, self.language.locale, fig['path'])):
+ fig['translated_file'] = True
+ else: fig['translated_file'] = False
+ self.figures.append(fig)
+ i += 4
+ return self.figures
+
+ def fig_count(self):
+ """ If stat of a document type, get the number of figures in the document """
+ return len(self.figures())
+
+ def fig_stats(self):
+ stats = {'fuzzy':0, 'translated':0, 'total':0, 'prc':0}
+ for fig in self.get_figures():
+ stats['total'] += 1
+ if fig['fuzzy']: stats['fuzzy'] += 1
+ else:
+ if fig['translated']: stats['translated'] += 1
+ stats['untranslated'] = stats['total'] - (stats['translated'] + stats['fuzzy'])
+ if stats['total'] > 0:
+ stats['prc'] = stats['translated']/stats['total']
+ return stats
+
+ def vcs_path(self):
+ """ Return the VCS path of file on remote vcs """
+ return os.path.join(self.branch.get_vcsurl(), self.domain.directory)
+
+ def vcs_webpath(self):
+ """ Return the Web interface path of file on remote vcs """
+ return os.path.join(self.branch.get_vcsweburl(), self.domain.directory)
+
+ def po_path(self):
+ """ Return path of po file on local filesystem """
+ subdir = ""
+ if self.domain.dtype == "doc":
+ subdir = "docs"
+ return os.path.join(settings.POTDIR, self.module_name()+'.'+self.branch.name, subdir, self.filename())
+
+ def po_url(self):
+ """ Return URL of po file, e.g. for downloading the file """
+ if self.domain.dtype == "doc":
+ subdir = "docs/"
+ else:
+ subdir = ""
+ #return self.filename()
+ return "/POT/%s.%s/%s%s" % (self.module_name(), self.branch.name, subdir, self.filename())
+
+ def most_important_message(self):
+ """ Return a message of type 1.'error', or 2.'warn, or 3.'warn """
+ error = None
+ for e in self.information_set.all():
+ if not error or e.Type == 'error' or (e.Type == 'warn' and error.Type == 'info'):
+ error = e
+ return error
+
+class FakeStatistics(object):
+ """ This is a fake statistics class where a summary value is needed for a multi-domain module
+ This is used in get_lang_stats for the language-release-stats template """
+ def __init__(self, module, dtype):
+ self.module = module
+ self.dtype = dtype
+ self.Translated = 0
+ self.Fuzzy = 0
+ self.Untranslated = 0
+ self.partial_po = False
+
+ def untrans(self, stat):
+ """ Called for POT file, so only Untranslated is concerned """
+ self.Untranslated += stat.Untranslated
+ stat.partial_po = True
+
+ def trans(self, stat):
+ self.Translated += stat.Translated
+ self.Fuzzy += stat.Fuzzy
+ self.Untranslated -= (stat.Translated + stat.Fuzzy)
+ stat.partial_po = True
+
+ def is_fake(self):
+ return True
+
+ def pot_size(self):
+ return int(self.Translated) + int(self.Fuzzy) + int(self.Untranslated)
+ def tr_percentage(self):
+ if self.pot_size() == 0:
+ return 0
+ else:
+ return 100*self.Translated/self.pot_size()
+ def fu_percentage(self):
+ if self.pot_size() == 0:
+ return 0
+ else:
+ return 100*self.Fuzzy/self.pot_size()
+ def un_percentage(self):
+ if self.pot_size() == 0:
+ return 0
+ else:
+ return 100*self.Untranslated/self.pot_size()
+ def module_name(self):
+ return self.module.name
+ def module_description(self):
+ return self.module.description
+
+class ArchivedStatistics(models.Model):
+ Module = models.TextField(db_column='module')
+ Type = models.CharField(db_column='type', max_length=3, choices=(('doc', 'Documentation'), ('ui', 'User Interface')))
+ Domain = models.TextField(db_column='domain')
+ Branch = models.TextField(db_column='branch')
+ Language = models.CharField(db_column='language', max_length=15)
+ Date = models.DateTimeField(db_column='date')
+ Translated = models.IntegerField(db_column='translated', default=0)
+ Fuzzy = models.IntegerField(db_column='fuzzy', default=0)
+ Untranslated = models.IntegerField(db_column='untranslated', default=0)
+ class Meta:
+ db_table = 'archived_statistics'
+
+
+class Information(models.Model):
+ Statistics = models.ForeignKey('Statistics', db_column='statistics_id')
+ Type = models.CharField(db_column='type', max_length=5,
+ choices=(('info', 'Information'), ('warn','Warning'), ('error','Error'))) # priority of a stats message
+ Description = models.TextField(db_column='description')
+ class Meta:
+ db_table = 'information'
+
+ def get_icon(self):
+ return "/data/%s.png" % self.Type
+
+ def get_description(self):
+ text = self.Description
+ matches = re.findall('###([^#]*)###',text)
+ if matches:
+ text = re.sub('###([^#]*)###', '%s', text)
+
+ text = _(text)
+
+ #FIXME: if multiple substitutions, works only if order of %s is unchanged in translated string
+ for match in matches:
+ text = text.replace('%s',match,1)
+ return text
+
+class ArchivedInformation(models.Model):
+ Statistics = models.ForeignKey('ArchivedStatistics', db_column='statistics_id')
+ Type = models.CharField(db_column='type', max_length=5,
+ choices=(('info', 'Information'), ('warn','Warning'), ('error','Error'))) # priority of a stats message
+ Description = models.TextField(db_column='description')
+ class Meta:
+ db_table = 'archived_information'
+
Added: branches/djamnedlies/stats/templates/base.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/base.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,101 @@
+{% load i18n %}
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{{ defaults.language }}" lang="{{ defaults.language }}">
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <title>{% block title %}page title{% endblock %}</title>
+ <link rel="icon" type="image/png" href="{{ webroot }}/data/foot-16.png"/>
+ <link rel="stylesheet" href="{{ webroot }}/data/main.css"/>
+ <link rel="stylesheet" href="{{ webroot }}/data/layout.css"/>
+ <link rel="stylesheet" href="{{ webroot }}/data/style.css"/>
+{% if rtl %}
+ <link rel="stylesheet" href="{{ webroot }}/data/rtl.css"/>
+{% endif %}
+ <script src="{{ webroot }}/data/main.js" type="text/javascript"></script>
+</head>
+
+{% if rtl %}
+ <body dir="rtl">
+{% else %}
+ <body>
+{% endif %}
+
+ <div id="page">
+ <ul id="general">
+ <li id="siteaction-gnome_home" class="home">
+ <a href="http://www.gnome.org/">{% trans "Home" %}</a>
+ </li>
+ <li id="siteaction-gnome_news">
+ <a href="http://news.gnome.org">{% trans "News" %}</a>
+ </li>
+ <li id="siteaction-gnome_projects">
+ <a href="http://www.gnome.org/projects/">{% trans "Projects" %}</a>
+ </li>
+ <li id="siteaction-gnome_art">
+ <a href="http://art.gnome.org">{% trans "Art" %}</a>
+ </li>
+ <li id="siteaction-gnome_support">
+ <a href="http://www.gnome.org/support/">{% trans "Support" %}</a>
+ </li>
+ <li id="siteaction-gnome_development">
+ <a href="http://developer.gnome.org">{% trans "Development" %}</a>
+ </li>
+ <li id="siteaction-gnome_community">
+ <a href="http://www.gnome.org/community/">{% trans "Community" %}</a>
+ </li>
+ </ul>
+ <div id="header">
+ <h1>{% trans "Damned Lies" %}</h1>
+ <div id="tabs">
+ <ul id="portal-globalnav">
+ <li
+{% ifequal pageSection "home" %}
+ class="selected"
+{% endifequal %}
+ ><a href="{{ webroot }}/" title="{% trans "Back to Damned Lies home page" %}"><span>{% trans "Home" %}</span></a>
+ </li>
+ <li
+{% ifequal pageSection "teams" %}
+ class="selected"
+{% endifequal %}
+ ><a href="{{ webroot }}/teams/"><span>{% trans "Teams" %}</span></a></li>
+ <li
+{% ifequal pageSection "languages" %}
+ class="selected"
+{% endifequal %}
+ ><a href="{{ webroot }}/languages/"><span>{% trans "Languages" %}</span></a></li>
+ <li
+{% ifequal pageSection "releases" %}
+ class="selected"
+{% endifequal %}
+ ><a href="{{ webroot }}/releases/"><span>{% trans "Release sets" %}</span></a></li>
+ <li
+{% ifequal pageSection "module" %}
+ class="selected"
+{% endifequal %}
+ ><a href="{{ webroot }}/module/"><span>{% trans "Modules" %}</span></a></li>
+ </ul>
+ </div> <!-- end of #tabs -->
+ </div> <!-- end of #header -->
+ </div>
+<!-- end site header -->
+
+ <div class="body">
+ <div id="content">
+ {% block content %}
+ {% endblock %}
+ </div>
+
+ <div id="footer">
+ Copyright © 2006, 2007 <a href="http://www.gnome.org/">{% trans "The GNOME Project" %}</a>.
+ <br />
+{% trans "Maintained in the <a href='http://svn.gnome.org/viewvc/damned-lies/'>damned-lies</a> module on <a href='http://svn.gnome.org/'>svn.gnome.org</a>" %}
+ <br />
+ {% trans "Hosted by" %} <a href="http://www.canonical.com/">Canonical</a>.
+ </div>
+
+</div> <!-- end of div.body -->
+</body>
+</html>
Added: branches/djamnedlies/stats/templates/index.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/index.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,50 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "Damned Lies about GNOME" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{% trans "Damned Lies about GNOME" %}</h1>
+
+<table><tr><td width="50%" valign="top">
+
+<h2><a href="teams/">{% trans "Teams" %}</a></h2>
+<p>{% trans "List of all GNOME Translation Teams, with full information such as primary contact (coordinator), web pages and mailing list information." %}
+ {% trans "If there is no team for your language, you can easily <a href='http://live.gnome.org/TranslationProject/StartingATeam/'>start your own team</a>." %}
+</p>
+
+</td><td valign="top">
+
+<h2><a href="languages/">{% trans "Languages" %}</a></h2>
+<p>{% trans "List of all languages there are <a href='teams/'>Translation Teams</a> for." %}
+ {% trans "Some teams manage more than one language (usually just simple variants), and here you can see all the languages GNOME is being translated to." %}</p>
+
+</td></tr><tr><td valign="top">
+
+<h2><a href="releases/">{% trans "Release Sets" %}</a></h2>
+<p>{% trans "List of all GNOME release sets and releases we gather stats for." %}</p>
+
+<p>{% trans "Examples of release sets are "GNOME Office", "Fifth Toe" or "GNOME 2.14"." %}
+ {% trans "Official GNOME release sets are further divided into categories such as "Desktop Applications" and "Developer Platform"." %}</p>
+
+<p>{% trans "Look here if you want to compare language support in any of these release sets." %}</p>
+</td><td valign="top">
+
+<h2><a href="module/">{% trans "Modules" %}</a></h2>
+<p>{% trans "List of all modules with statistics in here." %}</p>
+
+<p>{% trans "Modules are separate libraries or applications, with one or more branches of development included." %}
+ {% trans "They are usually taken from CVS, and we keep all relevant information on them (Bugzilla details, web page, maintainer information,...)." %}</p>
+
+</td></tr></table>
+
+{% if translator_credits %}
+<p class="footnote">
+ {% trans "Translated by:" %} {{ translator_credits }}
+</p>
+{% endif %}
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/language-release-stats.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/language-release-stats.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,70 @@
+{# parent template has to define variable modstats #}
+
+{% load i18n %}
+
+<table name="stats-table">
+<tr style="background: inherit;">
+ <td class="leftcell" style="font-size: 120%; background: inherit;" colspan="2">{{ modstats.totaltransperc }}% ({{ modstats.totaltrans }}/{{ modstats.totalfuzzy }}/{{ modstats.totaluntrans }})</td>
+ <td style="width: 108px; text-align: center; background:inherit;"><div class="graph">
+ <div class="translated" style="width: {{ modstats.totaltransperc }}px;"></div>
+ <div class="fuzzy" style="left:{{ modstats.totaltransperc }}px; width:{{ modstats.totalfuzzyperc }}px;"></div>
+ {% with modstats.totaltransperc|add:modstats.totalfuzzyperc as upos %}
+ <div class="untranslated" style="left:{{ upos }}px; width: {{ modstats.totaluntransperc }}px;"></div>
+ {% endwith %}
+ </div>
+ </td>
+</tr>
+
+{% for catname,categ in modstats.categs.items %}
+ {% ifnotequal catname "default" %}
+ <tr><td colspan="3" class="leftcell" style="background: inherit; font-size: 120%; font-weight: bold; padding-top:1em;">
+ {% with categ.cattransperc as percentage %}
+ {% blocktrans %}{{ catname }} ({{ percentage }}% translated){% endblocktrans %}
+ {% endwith %}
+ </td></tr>
+ {% endifnotequal %}
+
+ {% for module in categ.modules %}
+ {% with module.0 as modname %}
+ {% for dom in module.1 %}
+ {% with dom.0 as domname %}
+ {% if dom.1 %}
+ {% ifequal dom.1.tr_percentage 100 %}
+ <tr id="{{ modname }}-{{ domname }}-complete">
+ {% else %}
+ <tr>
+ {% endifequal %}
+ {% if dom.1.partial_po %}
+ {# This is a partial po, indented, with the domain description #}
+ <td class="leftcell" style="padding-left:2em; padding-right:2em;">
+ <a href="{{ dom.1.po_url }}"><img src="/data/download.png" alt="{% trans "Download po file" %}"></a>
+ {{ dom.1.domain.description }}
+ </td>
+ {% else %}
+ <td class="leftcell">
+ {% if not dom.1.is_fake %}
+ <a href="{{ dom.1.po_url }}"><img src="/data/download.png" alt="{% trans "Download po file" %}"></a>
+ <a href="{% url stats.views.module modname %}">
+ {% else %}
+ <a href="{% url stats.views.module modname %}" style="font-style: italic;">
+ {% endif %}
+ {{ dom.1.module_description }}</a></td>
+ {% endif %}
+ <td>{{ dom.1.tr_percentage }}% ({{ dom.1.Translated }}/{{ dom.1.Fuzzy }}/{{ dom.1.Untranslated }})</td>
+ <td style="width: 108px; text-align: center; background:inherit;"><div class="graph">
+ <div class="translated" style="width: {{ dom.1.tr_percentage }}px;"></div>
+ <div class="fuzzy" style="left:{{ dom.1.tr_percentage }}px; width:{{ dom.1.fu_percentage }}px;"></div>
+ {% with dom.1.tr_percentage|add:dom.1.fu_percentage as upos %}
+ <div class="untranslated" style="left:{{ upos }}px; width:{{ dom.1.un_percentage }}px;"></div>
+ {% endwith %}
+ </div>
+ </td>
+ </tr>
+ {% endif %}
+ {% endwith %}
+ {% endfor %}
+ {% endwith %}
+ {% endfor %}
+{% endfor %}
+</table>
+
Added: branches/djamnedlies/stats/templates/language-release.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/language-release.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,85 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans release.name %} - {% trans language.name %}{% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+{% with language.locale as lcode %}
+{% if language.team %}
+ <h1>{% blocktrans with language.team.description as lang %}{{ lang }} Translation Team â {{ lcode }}{% endblocktrans %}</h1>
+
+<table><tr><td valign="top" width="50%">
+ <h2>{% trans "Details" %}</h2>
+
+ {% if language.team.webpage_url %}
+ <strong>{% blocktrans with language.team.description as lang %}{{ lang }} Translation Team Page:{% endblocktrans %}</strong>
+ <a href="{{ language.team.webpage_url }}">{{ language.team.webpage_url }}</a><br />
+ {% endif %}
+
+ <br/><strong>{% trans "Bugzilla:" %}</strong>
+ <ul>
+ <li><a href="{{ language.bugs_url_enter|safe }}">{% trans "Report Bug in Translation" %}</a></li>
+ <li><a href="{{ language.bugs_url_show|safe }}">{% trans "Show Existing Bugs" %}</a></li>
+ </ul>
+
+ {% if language.team.mailing_list %}
+ <br/><strong>{% trans "Mailing List:" %}</strong>
+ <ul>
+ <li><a href="mailto:{{ language.team.mailing_list }}">{% trans "Send e-mail to the list" %}</a></li>
+ {% if language.team.mailing_list_subscribe %}
+ <li><a href="{{ language.team.mailing_list_subscribe }}">{% trans "Subscribe" %}</a></li>
+ {% endif %}
+ </ul>
+ {% endif %}
+
+ </td><td valign="top">
+ {% if language.team.coordinator %}
+ <h2>{% trans "Coordinator" %}</h2>
+ {% with language.team.coordinator as person %}
+ {% with 0 as printroles %}
+ {% include "person-base.tmpl" %}
+ {% endwith %}
+ {% endwith %}
+ {% endif %}
+</td></tr></table>
+{% else %}
+ <h1>{% blocktrans with language.locale as code %}Language code: {{ code }}{% endblocktrans %}</h1>
+ <p>{% blocktrans %}There is no translation team in charge of '{{ lcode }}' translation.{% endblocktrans %}</p>
+{% endif %}
+{% endwith %}
+
+<h2>{% trans release.name %}</h2>
+
+<p id="hide">
+ <a href="#" onclick="return showHideCompleted();">{% trans "Hide completed modules" %}</a>
+</p>
+
+<p id="show" style="display:none">
+ <a href="#" onclick="return showHideCompleted();">{% trans "Show completed modules" %}</a>
+</p>
+
+{% ifequal release.status "external" %}
+<p><i>{% trans "The modules of this release are not part of the GNOME SVN repository. Please check each module's web page to see where to send translations." %}</i></p>
+{% endifequal %}
+
+<table><tr>
+{% if stats.doc.total %}
+ <td valign="top" width="50%"><!-- two columns set-up -->
+ <h3>{% trans "Documentation" %}</h3>
+ {% with stats.doc as modstats %}
+ {% include "language-release-stats.tmpl" %}
+ {% endwith %}
+ </td>
+{% endif %}
+ <td valign="top"><!-- second column -->
+
+ <h3>{% trans "UI translations" %}</h3>
+ {% with stats.ui as modstats %}
+ {% include "language-release-stats.tmpl" %}
+ {% endwith %}
+</td></tr></table><!-- end two column layout -->
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/list-languages.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/list-languages.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,32 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "GNOME Languages" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{% trans "GNOME Languages" %}</h1>
+
+{% blocktrans count languages|length as numb %}
+GNOME is being translated to following {{ numb }} language.
+{% plural %}
+GNOME is being translated to following {{ numb }} languages.
+{% endblocktrans %}
+
+<div style="column-count:3;-moz-column-count:3;-webkit-column-count:3">
+<ul class="foot">
+{% for lang in languages %}
+<li style="font-size: 120%;">
+ {% if lang.name %}
+ <a href="{{ webroot }}/languages/{{ lang.locale }}">{{ lang.translated_name }}</a>
+ {% else %}
+ <a href="{{ webroot }}/languages/{{ lang.locale }}">{{ lang.locale }}</a>
+ {% endif %}
+</li>
+{% endfor %}
+</ul>
+</div>
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/list-modules.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/list-modules.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,22 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "GNOME Modules" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{% trans "GNOME modules" %}</h1>
+
+<p>{% trans "Select a module below to see some of the damned lies about it:" %}</p>
+
+<div style="column-count:3;-moz-column-count:3;-webkit-column-count:3">
+<ul class="foot">
+{% for mod in modules %}
+ <li><a href="{% url djamnedlies.stats.views.module mod.name %}">{{ mod.translated_name }} </a></li>
+{% endfor %}
+</ul>
+</div>
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/list-releases.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/list-releases.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,25 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "GNOME Releases" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{% trans "GNOME Releases" %}</h1>
+
+<p>{% trans "Select a release or a release set below to see more details about it:" %}</p>
+
+<ul class="foot">
+{% for rel in releases %}
+ {% ifchanged rel.status %}
+ </ul>
+ <ul class="foot">
+ {% endifchanged %}
+ <li style="font-size: 120%;">
+ <a href="{% url stats.views.release rel.id %}">{% trans rel.name %}</a>
+ </li>
+{% endfor %}
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/list-teams.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/list-teams.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,33 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "GNOME Translation Teams" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{% trans "GNOME Translation Teams" %}</h1>
+
+{% if teams %}
+<p>{% trans "Select a team below to see more information about it:" %}</p>
+
+ <ul class="foot">
+ {% for team in teams %}
+ <li style="font-size: 120%;">
+ <a href="{% url stats.views.team team.lang_code %}">{{ team.translated_name }}</a>
+ {% if team.webpage_url %}
+ — <a href="{{ team.webpage_url }}">{{ team.webpage_url }}</a>
+ {% endif %}
+ {% if team.coordinator_url %}
+ <br /><span style="font-size: 80%;">{% blocktrans with team.coordinator_url|safe as url %}Coordinated by {{ url }}{% endblocktrans %}</span>
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+
+{% else %}
+<p>{% trans "There are currently no translation teams in GNOME. :(" %}</p>
+{% endif %}
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/module-images.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/module-images.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,58 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% blocktrans with module.description as name %}Module Doc Figure Status: {{ name }}{% endblocktrans %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1><a href="{% url stats.views.module module.name %}">{{ module.description }}</a> {{ stat.domain.description }} ({% trans stat.language.name %})</h1>
+
+{% with stat.fig_stats as figstat %}
+<h2>{% trans "Figures translation status" %} —
+ <small>{{ figstat.prc }}% ({{ figstat.translated }}/{{ figstat.fuzzy}}/{{ figstat.untranslated }})</small></h2>
+{% endwith %}
+
+<table class="stats">
+<thead><tr><th width="50%">{% trans "Original" %}</th><th width="50%">{% trans stat.language.name %}</th></tr></thead>
+{% for fig in stat.get_figures %}
+ {% with stat.language.locale as locale %}
+ {% with stat.vcs_webpath as vcswebpath %}
+ {% with stat.vcs_path as vcspath %}
+ <tr><td valign="top">
+ <a href="{{ vcswebpath }}/C/{{ fig.path }}"><span class="path">C/{{ fig.path }}</span><br/></a>
+ <a href="{{ vcspath }}/C/{{ fig.path }}"><img class="screenshot" src="{{ vcspath }}/C/{{ fig.path }}"/></a>
+ </td>
+ <td valign="top" class="$tdclass">
+ {% if fig.translated %}
+ {% if fig.translated_file %}
+ <a href="{{ vcswebpath }}/{{ locale }}/{{ fig.path }}"><span class="path">{{ locale }}/{{ fig.path }}</span></a><br/>
+ <a href="{{ vcspath }}/{{ locale }}/{{ fig.path }}"><img class="screenshot" src="{{ vcspath }}/{{ locale }}/{{ fig.path }}"/></a>
+ {% else %}
+ <p><em>{% trans "Translated, but uses original one (maybe the figure doesn't contain any string to translate)" %}</em></p>
+ {% endif %}
+ {% else %}
+ {% if fig.fuzzy %}
+ <em>{% trans "Fuzzy" %}</em><br/>
+ {% if fig.translated_file %}
+ <a href="{{ vcswebpath }}/{{ locale }}/{{ fig.path }}"><span class="path">{{ locale }}/{{ fig.path }}</span></a><br/>
+ <a href="{{ vcspath }}/{{ locale }}/{{ fig.path }}"><img class="screenshot" src="{{ vcspath }}/{{ locale }}/{{ fig.path }}"/></a>
+ {% else %}
+ <p><em><small>{% trans "No existing file ("Technical" fuzzy)" %}</small></em></p>
+ {% endif %}
+ {% else %}
+ <em>{% trans "Not translated" %}</em><br/>
+ <img src="/data/emptyimg.png">
+ {% endif %}
+ {% endif %}
+ </td>
+ </tr>
+ {% endwith %}
+ {% endwith %}
+ {% endwith %}
+{% endfor %}
+</table>
+
+</div>
+
+{% endblock %}
Added: branches/djamnedlies/stats/templates/module.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/module.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,100 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% blocktrans with module.description as name %}Module Statistics: {{ name }}{% endblocktrans %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{{ module.translated_name }}</h1>
+
+{% if module.comment %}
+ <p>{{ module.comment|safe }}</p>
+{% else %}
+ {% ifnotequal module.vcs_root "http://svn.gnome.org/svn" %}
+ <p><i><img src="{{ webroot }}/data/warn.png" alt="Warning logo" />{% trans "This module is not part of the GNOME SVN repository. Please check the module's web page to see where to send translations." %}</i></p>
+ {% endifnotequal %}
+{% endif %}
+
+{% if module.homepage %}
+ <p><a href="{{ module.homepage }}">{{ module.homepage }}</a></p>
+{% endif %}
+
+<table><tr><td width="50%" valign="top">
+
+{% if module.maintainers.all %}
+ <h2>{% trans "Maintainers" %}</h2>
+ {% for maintainer in module.maintainers.all %}
+ <div class="maintainer">
+ {% if maintainer.image %}
+ <img class="people" src="{{ maintainer.image }}" alt="" />
+ {% else %}
+ <img class="people" src="{{ webroot }}/data/nobody.png" alt="" />
+ {% endif %}
+ <a style="font-size: 140%;" href="{% url stats.views.person maintainer.id %}">{{ maintainer.name }}</a>
+ </div>
+ {% endfor %}
+{% endif %}
+
+</td><td width="50%" valign="top">
+
+{% if module.bugs_base %}
+ <h2>{% trans "Bug reporting" %}</h2>
+ <ul>
+ {% if module.get_bugs_i18nurl %}
+ <li><a href="{{ module.get_bugs_i18nurl }}">{% trans "Show existing i18n and l10n bugs" %}</li>
+ {% endif %}
+ <li><a href="{{ module.get_bugs_enterurl }}">{% trans "Report bugs to Bugzilla" %}</a></li>
+ </ul>
+{% endif %}
+
+</td></tr></table>
+
+{% if module.branch_set.all %}
+ <!-- Links to branches of module -->
+ <p><b>{% trans "Branches:" %}</b>
+ {% for branch in module.get_branches %}
+ {% ifnotequal forloop.counter 1 %}
+ -
+ {% endifnotequal %}
+ <a href="#{{ branch.name }}">{{ branch.name }}</a>
+ {% endfor %}
+ </p>
+
+ <!-- Main loop through branches -->
+ {% for branch in module.get_branches %}
+ <h2><a name="{{ branch.name }}"></a>{{ branch.name }}
+ {% ifequal module.vcs_type "cvs" %}
+ (<a href="{{ branch.get_vcsweburl }}">{% trans "Browse CVS" %}</a>)
+ {% endifequal %}
+ {% ifequal module.vcs_type "svn" %}
+ (<a href="{{ branch.get_vcsweburl }}">{% trans "Browse SVN" %}</a>)
+ {% endifequal %}
+ </h2>
+ {% if branch.release_cat.release.stringfrozen %}
+ <p>{% trans "This branch is currently string-frozen." %}</p>
+ {% endif %}
+
+ <table><tr><td valign="top"><!-- split to two columns -->
+ {% with branch.get_docstats as stats %}
+ {% if stats|length %}
+ <h3>{% trans "Documentation" %}</h3>
+ {% include "show-stats.tmpl" %}
+ {% endif %}
+ {% endwith %}
+
+ </td><td valign="top"><!-- split to two columns -->
+ {% with branch.get_uistats as stats %}
+ {% if stats|length %}
+ <h3>{% trans "Translation" %}</h3>
+ {% include "show-stats.tmpl" %}
+ {% endif %}
+ {% endwith %}
+
+ </td></tr></table>
+
+ {% endfor %}
+{% endif %}
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/people.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/people.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,30 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "GNOME Contributors" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h2>{% trans "GNOME Contributors" %}</h2>
+
+<p>{% trans "GNOME is being developed by following people:" %}</p>
+
+<div style="column-count:3;-moz-column-count:3;-webkit-column-count:3">
+{% for person in people %}
+ <div class="maintainer">
+ {% ifnotequal person.image '/data/nobody.png' %}
+ <img class="people" src="{{ person.image }}" alt="{{ person.name }}" />
+ {% else %}
+ <img class="people" src="{{ webroot }}/data/nobody.png" alt="" />
+ {% endifnotequal %}
+ <a style="font-size: 120%;" href="{{ webroot }}/people/{{ person.id }}">{{ person.name }}</a><br />
+ {% if person.webpage_url %}
+ <a href="{{ person.webpage_url }}">{{ person.webpage_url }}</a><br />
+ {% endif %}
+ </div>
+
+{% endfor %}
+</div>
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/person-base.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/person-base.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,60 @@
+{# Variables $person and $printroles must be defined prior to calling this template #}
+{# If $printroles !=0 $roles must also be defined #}
+{# This template is included in person.tmpl, team.tmpl and language-release.tmpl #}
+
+{% load i18n %}
+
+ <div class="maintainer">
+ {% ifnotequal person.image '/data/nobody.png' %}
+ <img class="people" src="{{ person.image }}" alt="{{ person.name }}" />
+ {% else %}
+ <img class="people" src="{{ webroot }}/data/nobody.png" alt="" />
+ {% endifnotequal %}
+
+ <a style="font-size: 140%;" href="{{ webroot }}/people/{{ person.id }}">{{ person.name }}</a><br />
+
+ {% if person.nospamemail %}
+ <a href="mailto:{{ person.nospamemail }}">{{ person.nospamemail }}</a><br />
+ {% endif %}
+ {% if person.webpage_url %}
+ <a href="{{ person.webpage_url }}">{{ person.webpage_url }}</a><br />
+ {% endif %}
+
+ <br />
+ {% if person.irc_nick %}
+ <strong>{% trans "Instant messaging:" %}</strong>
+ <ul>
+ <li><em>{{ person.irc_nick }}</em> (IRC)</li>
+ </ul>
+ {% endif %}
+
+ {% if person.nospambugzillaaccount %}
+ <strong>{% trans "Bugzilla account:" %}</strong> {{ person.nospambugzillaaccount }}<br />
+ {% endif %}
+
+ {% if person.svn_account %}
+ <strong>{% trans "SVN account:" %}</strong> <a href="http://cia.vc/stats/author/{{ person.svn_account }}">{{ person.svn_account}}</a><br />
+ {% endif %}
+
+ {% if printroles %}
+ {% if roles.maintains %}
+ <h2>{% trans "Maintains:" %}</h2>
+ <ul>
+ {% for module in roles.maintains %}
+ <li><a href="{% url stats.views.module module.name%} ">{{ module.description }}</a></li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
+ {% if roles.translates %}
+ <h2>{% trans "Translates:" %}</h2>
+ <ul>
+ {% for team in roles.translates %}
+ {% url djamnedlies.stats.views.team team.lang_code as team_url %}
+ <li>{% blocktrans with team.description as teamdesc %}Coordinates <a href="{{ team_url }}">{{ teamdesc }}</a>{% endblocktrans %}
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% endif %}
+
+</div>
Added: branches/djamnedlies/stats/templates/person.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/person.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,16 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans "GNOME Contributor" %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+ <h2>{{ person.name}}</h2>
+ {% with 1 as printroles %}
+ {% include "person-base.tmpl" %}
+ {% endwith %}
+
+</div>
+
+{% endblock %}
Added: branches/djamnedlies/stats/templates/release.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/release.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,54 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %} {% trans release.name %} {% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+
+<h1>{% blocktrans with release.name as name %}{{ name }} Release{% endblocktrans %}</h1>
+
+{% ifequal release.status "external" %}
+ <p><i>{% trans "The modules of this release are not part of the GNOME SVN repository. Please check each module's web page to see where to send translations." %}</i></p>
+{% endifequal %}
+
+<table class="stats">
+<thead><tr><th>{% trans "Release" %}</th><th>{% trans "Documentation" %}</th><th>{% trans "Graph" %}</th><th>{% trans "User Interface" %}</th><th>{% trans "Graph" %}</th></tr></thead>
+
+{% for lstats in release.get_global_stats %}
+<tr>
+ <td class="leftcell" style="font-size:120%;">
+ <a href="{{ webroot }}/languages/{{ lstats.lang_code }}/{{ release.id }}">{% trans lstats.lang %}</a>
+ </td>
+
+ {% ifnotequal lstats.doc_trans|add:lstats.doc_fuzzy "0" %}
+ <td>{{ lstats.doc_percent }}% ({{ lstats.doc_trans }}/{{ lstats.doc_fuzzy }}/{{ lstats.doc_untrans }})</td>
+ {% else %}
+ <td>-</td>
+ {% endifnotequal %}
+
+ <td style="width: 108px; text-align: center;"><div class="graph">
+ <div class="translated" style="width: {{ lstats.doc_percent }}px;"></div>
+ <div class="fuzzy" style="left:{{ lstats.doc_percent }}px; width:{{ lstats.doc_percentfuzzy }}px;"></div>
+ {% with lstats.doc_percent|add:lstats.doc_percentfuzzy as upos %}
+ <div class="untranslated" style="left:{{ upos }}px; width: {{ lstats.doc_percentuntrans }}px;"></div>
+ {% endwith %}
+ </div>
+ </td>
+
+ <td>{{ lstats.ui_percent }}% ({{ lstats.ui_trans }}/{{ lstats.ui_fuzzy }}/{{ lstats.ui_untrans }})</td>
+ <td style="width: 108px; text-align: center;"><div class="graph">
+ <div class="translated" style="width: {{ lstats.ui_percent }}px;"></div>
+ <div class="fuzzy" style="left:{{ lstats.ui_percent }}px; width:{{ lstats.ui_percentfuzzy }}px;"></div>
+ {% with lstats.ui_percent|add:lstats.ui_percentfuzzy as upos %}
+ <div class="untranslated" style="left:{{ upos }}px; width: {{ lstats.ui_percentuntrans }}px;"></div>
+ {% endwith %}
+ </div>
+ </td>
+</tr>
+{% endfor %}
+</table>
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/templates/show-stats.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/show-stats.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,61 @@
+{% load i18n %}
+
+{% for dname, stat in stats.items %}
+ {% with stat|first as stat1 %}
+ <h3>{% trans stat1.domain.description %}
+ {% ifnotequal stat1.domain.directory 'help' %}
+ {% ifnotequal stat1.domain.directory 'po' %}
+ <br /><span class='path'>{{ stat1.domain.directory }}</span>
+ {% endifnotequal %}
+ {% endifnotequal %}</h3>
+ <a href="{{ stat1.po_url }}"><img src="/data/download.png" alt="Download POT file" /></a>
+ {{ stat1.pot_text }}
+
+ <!-- /* This is the title of the section that lists notices about a module */ -->
+ {% if stat1.information_set.all %}
+ <h4>{% trans "Notices" %}</h4>
+ <table>
+ {% for msg in stat1.information_set.all %}
+ <tr><td valign="top"><img src="{{ msg.get_icon }}" alt="{{ msg.Type }}" /></td><td>{{ msg.get_description|safe }}</td></tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+
+<table class="stats">
+<thead><tr><th>{% trans "Language" %}</th><th>{% trans "Translated" %}</th>
+ {% if stat1.fig_count %}
+ <th></th>
+ {% endif %}
+<th>{% trans "Graph" %}</th></tr></thead>
+
+ {% for line in stat %}
+ {% if not forloop.first %}
+ <tr>
+ <td class="leftcell"><a href="{{ line.po_url }}">{{ line.get_lang }}</a>
+ {% with line.most_important_message as msg %}
+ {% if msg %}
+ <img src="{{ msg.get_icon }}" title="{{ msg.get_description }}" alt="{{ msg.Type }}" />
+ {% endif %}
+ {% endwith %}
+ </td>
+ <td>{{ line.get_translationstat|safe }}</td>
+ {% if stat1.fig_count %}
+ <td><a href="/module/{{ module.name }}/{{ stat1.domain.name }}/{{ branch.name }}/{{ line.language.locale}}/images">
+ <img src="/data/figure.png" alt="{% trans "Display document figures" %}"></a></td>
+ {% endif %}
+ <td style="width: 108px; text-align: center;"><div class="graph">
+ <div class="translated" style="width: {{ line.tr_percentage }}px;"></div>
+ <div class="fuzzy" style="left:{{ line.tr_percentage }}px; width:{{ line.fu_percentage }}px;"></div>
+ <div class="untranslated" style="left:{{ line.tr_percentage|add:line.fu_percentage }}px; width: {{ line.un_percentage }}px;"></div>
+ </div>
+ </td>
+ </tr>
+
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+
+</table>
+
+{% endfor %}
+
Added: branches/djamnedlies/stats/templates/team.tmpl
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/templates/team.tmpl Mon Oct 20 21:34:37 2008
@@ -0,0 +1,87 @@
+{% extends "base.tmpl" %}
+{% load i18n %}
+
+{% block title %}{% trans team.description %}{% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{% blocktrans with team.description as lang %}{{ lang }} Translation Team{% endblocktrans %}</h1>
+
+
+<table><tr><td valign="top" width="50%">
+ <h2>{% trans "Details" %}</h2>
+
+ {% if team.webpage_url %}
+ <strong>{% blocktrans with team.description as lang %}{{ lang }} Translation Team Page:{% endblocktrans %}</strong>
+ <a href="{{ team.webpage_url }}">{{ team.webpage_url }}</a><br />
+ {% endif %}
+
+ <br/><strong>{% trans "Bugzilla:" %}</strong>
+ <ul>
+ <li><a href="{{ language.bugs_url_enter|safe }}">{% trans "Report Bug in Translation" %}</a></li>
+ <li><a href="{{ language.bugs_url_show|safe }}">{% trans "Show Existing Bugs" %}</a></li>
+ </ul>
+
+ {% if team.mailing_list %}
+ <br/><strong>{% trans "Mailing List:" %}</strong>
+ <ul>
+ <li><a href="mailto:{{ team.mailing_list }}">{% trans "Send e-mail to the list" %}</a></li>
+ {% if team.mailing_list_subscribe %}
+ <li><a href="{{ team.mailing_list_subscribe }}">{% trans "Subscribe" %}</a></li>
+ {% endif %}
+ </ul>
+ {% endif %}
+
+ </td><td valign="top">
+ {% if team.coordinator %}
+ <h2>{% trans "Coordinator" %}</h2>
+ {% with team.coordinator as person %}
+ {% with 0 as printroles %}
+ {% include "person-base.tmpl" %}
+ {% endwith %}
+ {% endwith %}
+ {% endif %}
+</td></tr></table>
+
+{% for lang in team.language_set.all %}
+ <h2>{% trans lang.name %}</h2>
+ <table class="stats">
+ <thead><tr><th>{% trans "Release" %}</th><th>{% trans "Documentation" %}</th><th>{% trans "Graph" %}</th>
+ <th>{% trans "User Interface" %}</th><th>{% trans "Graph" %}</th></tr></thead>
+ {% for stat in lang.get_release_stats %}
+ <tr>
+ <td class="leftcell" style="font-size:120%;">
+ <a href="{{ webroot }}/languages/{{ lang.locale }}/{{ stat.id }}">{{ stat.name }}</a>
+ </td>
+
+ {% if stat.doctotal %}
+ <td>{{ stat.doctransperc }}% ({{ stat.doctrans }}/{{ stat.docfuzzy }}/{{ stat.docuntrans }})</td>
+ <td style="width: 108px; text-align: center;"><div class="graph">
+ <div class="translated" style="width:{{ stat.doctransperc }}px;"></div>
+ <div class="fuzzy" style="left:{{ stat.doctransperc }}px; width:{{ stat.docfuzzyperc }}px;"></div>
+ {% with stat.doctransperc|add:stat.docfuzzyperc as upos %}
+ <div class="untranslated" style="left:{{ upos }}px; width:{{ stat.docuntransperc }}px;"></div>
+ {% endwith %}
+ </div>
+ </td>
+ {% else %}
+ <td>-</td><td></td>
+ {% endif %}
+
+ <td>{{ stat.uitransperc }}% ({{ stat.uitrans }}/{{ stat.uifuzzy }}/{{ stat.uiuntrans }})</td>
+ <td style="width: 108px; text-align: center;"><div class="graph">
+ <div class="translated" style="width:{{ stat.uitransperc }}px;"></div>
+ <div class="fuzzy" style="left:{{ stat.uitransperc }}px; width:{{ stat.uifuzzyperc }}px;"></div>
+ {% with stat.uitransperc|add:stat.uifuzzyperc as upos %}
+ <div class="untranslated" style="left:{{ upos }}px; width:{{ stat.uiuntransperc }}px;"></div>
+ {% endwith %}
+ </div>
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+{% endfor %}
+
+</div>
+{% endblock %}
Added: branches/djamnedlies/stats/urls.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/urls.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,29 @@
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+from django.contrib import admin
+admin.autodiscover()
+
+urlpatterns = patterns('djamnedlies.stats.views',
+ (r'^/*$', 'index'),
+ (r'^teams/*$', 'teams'),
+ (r'^teams/(?P<langcode>.*)$', 'team'),
+ (r'^languages/*$', 'languages'),
+ (r'^languages/(?P<langcode>\w+)/$', 'team'),
+ (r'^languages/(?P<langcode>\w+)/(?P<release_id>\d+)/$', 'languagerelease'),
+ (r'^people/*$', 'people'),
+ (r'^people/(?P<person_id>.*)$', 'person'),
+ (r'^module/*$', 'modules'),
+ (r'^module/(?P<module_name>[^/]+)$', 'module'),
+ (r'^module/(?P<module_name>\w+)/(?P<potbase>\w+)/(?P<branch_name>\w+)/(?P<langcode>\w+)/images/$', 'docimages'),
+ (r'^releases/*$', 'releases'),
+ (r'^releases/(?P<release_id>.*)$', 'release'),
+)
+ # Static files (should be replaced by web server redirection in production
+urlpatterns += patterns('',
+ (r'^data/(?P<path>.*)$', 'django.views.static.serve',
+ {'document_root': '/home/claude/Sauvegarde/Sites/djamnedlies/stats/data'}),
+ (r'^POT/(?P<path>.*)$', 'django.views.static.serve',
+ {'document_root': '/home/claude/www/damned-lies/cvs/POT'}),
+
+)
Added: branches/djamnedlies/stats/utils.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/utils.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2008 Claude Paroz <claude 2xlibre net>.
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies 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.
+#
+# Damned Lies 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 Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from django.utils.translation import ugettext as _
+import re, time
+
+def obfuscateEmail(email):
+ if email:
+ return email.replace('@', ' at ').replace('.', ' dot ')
+ return ""
+
+def sortObjectList(lst, tr_field):
+ """ Sort an object list with translated_name """
+ for l in lst:
+ l.translated_name = _(getattr(l, tr_field))
+ templist = [(obj_.translated_name.lower(), obj_) for obj_ in lst]
+ templist.sort()
+ return [obj_ for (key1, obj_) in templist]
+
+def multiple_replace(dct, text):
+ regex = re.compile("(%s)" % "|".join(map(re.escape, dct.keys())))
+ return regex.sub(lambda mo: dct[mo.string[mo.start():mo.end()]], text)
+
+def stripHTML(string):
+ replacements = {"<ul>": "\n", "</ul>": "\n", "<li>": " * ", "\n</li>": "", "</li>": ""}
+ return multiple_replace(replacements, string)
+
+class Profiler():
+ def __init__(self):
+ self.start = time.clock()
+
+ def time_spent(self):
+ return time.clock() - self.start
Added: branches/djamnedlies/stats/views.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/stats/views.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2008 Claude Paroz <claude 2xlibre net>.
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies 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.
+#
+# Damned Lies 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 Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from django.shortcuts import render_to_response
+from stats.models import Statistics, Team, Language, Person, Module, Release
+from stats.conf import settings
+from djamnedlies.stats import utils, defaults
+from django.http import HttpResponse
+from django.utils.translation import ugettext_lazy as _
+
+def index(request):
+ translator_credit = _("translator-credits")
+ if defaults.language == 'en' or translator_credit == "translator-credits":
+ translator_credit = ""
+ else:
+ translator_credit.replace("\n", ", ").replace("<", "<").replace(">", ">")
+ context = {'pageSection': "home",
+ 'webroot': settings.WEBROOT,
+ 'rtl': False,
+ 'translator_credit': translator_credit }
+ return render_to_response('index.tmpl', context)
+
+def teams(request):
+ all_teams = Team.objects.all()
+ for t in all_teams:
+ t.coordinator_url = "<a href='%s/people/%s'>%s</a>" % (settings.WEBROOT, t.coordinator.id, t.coordinator.name)
+
+ context = {'pageSection': "teams",
+ 'webroot': settings.WEBROOT,
+ 'teams': utils.sortObjectList(all_teams, 'description') }
+ return render_to_response('list-teams.tmpl', context)
+
+def team(request, langcode):
+ team = Team.objects.get(lang_code=langcode)
+ context = {'pageSection': "teams",
+ 'webroot': settings.WEBROOT,
+ 'team': team}
+ return render_to_response('team.tmpl', context)
+
+def languages(request):
+ all_languages = Language.objects.all()
+ context = {'pageSection': "languages",
+ 'languages': utils.sortObjectList(all_languages, 'name'),
+ 'webroot': settings.WEBROOT }
+ return render_to_response('list-languages.tmpl', context)
+
+def people(request):
+ """ Print a list of all people in database """
+ all_people = Person.objects.all()
+ context = {'pageSection': "teams",
+ 'people': all_people,
+ 'webroot': settings.WEBROOT }
+ return render_to_response('people.tmpl', context)
+
+def person(request, person_id):
+ """ Print the details of a single person """
+ person = Person.objects.get(id=person_id)
+ maintainer = person.module_set.all()
+ translator = Team.objects.filter(coordinator=person_id)
+ context = {'pageSection': "teams",
+ 'person': person,
+ 'printroles': True,
+ 'roles': {'maintains':maintainer, 'translates':translator},
+ 'webroot': settings.WEBROOT }
+ return render_to_response('person.tmpl', context)
+
+def modules(request):
+ all_modules = Module.objects.all()
+ context = {'pageSection': "module",
+ 'webroot': settings.WEBROOT,
+ 'modules': utils.sortObjectList(all_modules, 'description') }
+ return render_to_response('list-modules.tmpl', context)
+
+def module(request, module_name):
+ mod = Module.objects.get(name = module_name)
+ mod.translated_name = _(mod.description)
+ context = {'pageSection': "module",
+ 'webroot': settings.WEBROOT,
+ 'module': mod,
+ 'prof': utils.Profiler() }
+ return render_to_response('module.tmpl', context)
+
+def docimages(request, module_name, potbase, branch_name, langcode):
+ mod = Module.objects.get(name = module_name)
+ stat = Statistics.objects.get(branch__module=mod.id, branch__name=branch_name, domain__name=potbase, language__locale=langcode)
+ context = {'pageSection': "module",
+ 'webroot': settings.WEBROOT,
+ 'module': mod,
+ 'stat': stat }
+ return render_to_response('module-images.tmpl', context)
+
+def releases(request):
+ all_releases = Release.objects.order_by('status', '-name')
+ context = {'pageSection': "releases",
+ 'webroot': settings.WEBROOT,
+ 'releases': all_releases }
+ return render_to_response('list-releases.tmpl', context)
+
+def release(request, release_id):
+ rel = Release.objects.get(id=release_id)
+ context = {'pageSection': "releases",
+ 'webroot': settings.WEBROOT,
+ 'release': rel }
+ return render_to_response('release.tmpl', context)
+
+def languagerelease(request, langcode, release_id):
+ rel = Release.objects.get(id=release_id)
+ lang = Language.objects.get(locale=langcode)
+ rel_stats = rel.get_lang_stats(lang)
+ context = {'pageSection': "languages",
+ 'webroot': settings.WEBROOT,
+ 'language': lang,
+ 'release': rel,
+ 'stats': rel_stats}
+ return render_to_response('language-release.tmpl', context)
+
+
Added: branches/djamnedlies/urls.py
==============================================================================
--- (empty file)
+++ branches/djamnedlies/urls.py Mon Oct 20 21:34:37 2008
@@ -0,0 +1,16 @@
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+from django.contrib import admin
+admin.autodiscover()
+
+urlpatterns = patterns('',
+ # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+ # to INSTALLED_APPS to enable admin documentation:
+ # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ (r'^admin/(.*)', admin.site.root),
+
+ (r'^stats/', include('djamnedlies.stats.urls')),
+
+)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]