Migrate to PostgreSQL. Remove all the singletons.
A bit of cleanup and functionality enhancements.
+/webapp.conf
*.mo
*.py[co]
self.ioloop.set_blocking_log_threshold(900)
+ self.backend = backend.Backend("webapp.conf")
+
@property
def ioloop(self):
return tornado.ioloop.IOLoop.instance()
logging.debug("Next call will be in %.2f seconds." % \
(self.pc.callback_time / 1000))
+ @property
+ def backend(self):
+ return self.daemon.backend
+
+ @property
+ def settings(self):
+ return self.backend.settings
+
@property
def timeout(self):
"""
class MirrorManager(Manager):
@property
def mirrors(self):
- return backend.Mirrors()
+ return self.backend.mirrors
@property
def timeout(self):
- return backend.Config().get_int("mirror_check_interval")
+ return self.backend.settings.get_int("mirror_check_interval", 3600)
def do(self):
# Check status of all mirror servers.
class ReleaseFilesManager(Manager):
@property
def releases(self):
- return backend.Releases()
+ return self.backend.releases
@property
def timeout(self):
- return backend.Config().get_int("releasefiles_check_interval")
+ return self.settings.get_int("releasefiles_check_interval", 3600)
def do(self):
- for release in self.releases.list():
+ for release in self.releases.get_all():
release.scan_files()
padding-bottom: 10px;
}
-.ac {
+.ac, td.ac {
text-align: center;
}
{% for release in releases %}
<tr>
<td>
- <a href="/release/{{ release.id }}">{{ release.name }}</a>
+ <a href="/release/{{ release.sname }}">{{ release.name }}</a>
</td>
<td>
{% if release.stable %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("GeoIP for %s") % addr }}{% end block %}
+
+{% block body %}
+ <div class="page-header">
+ <h3>{{ _("GeoIP for %s") % addr }}</h3>
+ </div>
+
+ {% if peer %}
+ <div class="row">
+ <div class="span4">
+ <dl>
+ {% if peer.asn %}
+ <dt>{{ _("Autonomous System") }}</dt>
+ <dd>{{ peer.asn }}</dd>
+ {% end %}
+
+ <dt>{{ _("Country") }}</dt>
+ <dd>
+ {% if peer.country_name %}
+ {{ peer.country_name }} ({{ peer.country }})
+ {% else %}
+ {{ peer.country_name }}
+ {% end %}
+ </dd>
+
+ {% if peer.city %}
+ <dt>{{ _("City") }}</dt>
+ <dd>{{ peer.city }}</dd>
+
+ {% if peer.postal_code %}
+ <dt>{{ _("Postal Code") }}</dt>
+ <dd>{{ peer.postal_code }}</dd>
+ {% end %}
+ {% end %}
+ </dl>
+ </div>
+
+ <div class="span8">
+ {% module Map(peer.latitude, peer.longitude) %}
+ </div>
+ </div>
+ {% else %}
+ <div class="alert alert-info">
+ {{ _("No GeoIP information could be found for the IP address '%s'.") % addr }}
+ </div>
+ {% end %}
+
+{% end block %}
{% for item in latest_news %}
<tr>
<td class="date">
- {{ locale.format_date(item.date, relative=True, shorter=True) }} ‐
+ {{ locale.format_date(item.published, relative=True, shorter=True) }} ‐
</td>
<td class="link">
<a href="/news/{{ item.slug }}">{{ item.title }}</a>
<h1>{{ item.hostname }}</h1>
</div>
- <table class="table">
- <tr>
- <td>{{ _("Last update") }}</td>
- <td>{{ locale.format_date(item.last_update, full_format=True) }}</td>
- </tr>
- <tr>
- <td>{{ _("Owner") }}</td>
- <td>{{ item.owner }}</td>
- </tr>
- {% if item.prefer_for_countries %}
- <tr>
- <td>{{ _("Preferred for") }}</td>
- <td>{{ locale.list(item.prefer_for_countries_names) }}</td>
- </tr>
- {% end %}
- {% if client_distance %}
- <tr>
- <td>{{ _("Your distance to this mirror") }}</td>
- <td>{{ "%.1f km" % client_distance }}</td>
- </tr>
- {% end %}
- </table>
-
- <a class="btn pull-right" href="{{ item.url }}">{{ _("Go to mirror") }}</a>
-
- <br style="clear: both;">
- <hr>
-
- <h3>{{ _("Mirror location") }}</h3>
- <p>
- {{ _("The mirror <em>%s</em> is located in %s.") % (item.hostname, item.location_str) }}
- </p>
-
- {% if item.longitude and item.latitude %}
- <iframe width="100%" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"
- src="http://www.openstreetmap.org/export/embed.html?bbox={{ item.longitude - 4 }},{{ item.latitude - 4 }},{{ item.longitude + 4 }},{{ item.latitude + 4 }}&layer=mapquest&marker={{ item.latitude }},{{ item.longitude }}" style="border: 1px solid black">
- </iframe>
- <p>
- <a href="http://www.openstreetmap.org/?lat={{ item.latitude }}&lon={{ item.longitude }}&zoom=8&layers=M&mlat={{ item.latitude }}&mlon={{ item.longitude }}" target="_blank">{{ _("View larger map") }}</a>
- -
- © <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> contributors, CC-BY-SA
- </p>
- <p class="muted ac">
- {{ _("The location of the mirror server is estimated by the IP address.") }}
- </p>
- {% else %}
- {{ _("The location of the mirror server could not be estimated.") }}
- {% end %}
+ <div class="row">
+ <div class="span4">
+ {% if item.owner %}
+ <dt>{{ _("Owner") }}</dt>
+ <dd>{{ item.owner }}</dd>
+ {% end %}
+
+ {% if item.location_str %}
+ <hr>
+
+ <dt>{{ _("Location") }}</dt>
+ <dd>{{ item.location_str }}</dd>
+ {% elif item.location %}
+ <hr>
+
+ {% if item.country_name %}
+ <dt>{{ _("Country") }}</dt>
+ <dd>{{ item.country_name }}</dd>
+ {% end %}
+
+ {% if item.location.city %}
+ <dt>{{ _("City") }}</dt>
+ <dd>{{ item.location.city }}</dd>
+ {% end %}
+ {% end %}
+
+ {% if item.prefer_for_countries %}
+ <dt>{{ _("Preferred for") }}</dt>
+ <dd>
+ {{ locale.list(item.prefer_for_countries_names) }}
+ </dd>
+ {% end %}
+
+ {% if client_distance %}
+ <dt>{{ _("Estimated distance to you") }}</dt>
+ <dd>{{ "%.0fkm" % client_distance }}</dd>
+ {% end %}
+
+ <hr>
+
+ {% if item.asn %}
+ <dt>{{ _("Autonomous System") }}</dt>
+ <dd>{{ item.asn }}</dd>
+ {% end %}
+
+ <dt>{{ _("IP Addresses") }}</dt>
+ <dd>
+ {% for addr in item.addresses6 + item.addresses4 %}
+ {{ addr }}<br>
+ {% end %}
+ </dd>
+
+ {% if item.enabled %}
+ <hr>
+
+ <dt>{{ _("Last updated") }}</dt>
+ <dd>
+ <abbr title="{{ locale.format_date(item.last_update, full_format=True) }} UTC">
+ {{ locale.format_date(item.last_update, relative=True) }}
+ </abbr>
+ </dd>
+ {% end %}
+
+ <hr>
+
+ <p class="ac">
+ <a class="btn" href="{{ item.url }}">{{ _("Go to mirror") }}</a>
+ </p>
+ </div>
+
+ <div class="span8">
+ {% if item.location %}
+ {% module Map(item.latitude, item.longitude) %}
+ <p class="muted ac">
+ {{ _("The location of the mirror server is estimated by the IP address.") }}
+ </p>
+ {% else %}
+ <p class="ac muted">
+ {{ _("The location of this mirror server could not be estimated.") }}
+ </p>
+ {% end %}
+ </div>
+ </div>
{% end block %}
</p>
{% end %}
- {% if preferred_mirrors %}
- <h2>{{ _("Mirror servers nearby") }}</h2>
- {% module MirrorsTable(preferred_mirrors) %}
+ <hr>
- <h2>{{ _("Worldwide mirror servers") }}</h2>
- {% module MirrorsTable(other_mirrors) %}
- {% else %}
- <h2>{{ _("Worldwide mirror servers") }}</h2>
- {% module MirrorsTable(other_mirrors) %}
- {% end %}
+ {% module MirrorsTable(mirrors, preferred_mirrors) %}
{% end block %}
--- /dev/null
+<iframe width="100%" height="500" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"
+ src="http://www.openstreetmap.org/export/embed.html?bbox={{ longitude - 4 }},{{ latitude - 4 }},{{ longitude + 4 }},{{ latitude + 4 }}&layer=mapquest&marker={{ latitude }},{{ longitude }}" style="border: 1px solid black">
+</iframe>
+<p>
+ <a href="http://www.openstreetmap.org/?lat={{ latitude }}&lon={{ longitude }}&zoom=8&layers=M&mlat={{ latitude }}&mlon={{ longitude }}" target="_blank">{{ _("View larger map") }}</a>
+ -
+ © <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> contributors, CC-BY-SA
+ <span class="pull-right">
+ {% if latitude >= 0 %}
+ {{ latitude }} N,
+ {% else %}
+ {{ -latitude }} S,
+ {% end %}
+ {% if longitude >= 0 %}
+ {{ longitude }} E
+ {% else %}
+ {{ -longitude }} W
+ {% end %}
+ </span>
+</p>
<table class="table table-striped">
{% for mirror in mirrors %}
<tr>
+ <td class="ac">
+ {% if mirror.country_code %}
+ <img src="{{ static_url("images/flags/%s.png" % mirror.country_code.lower()) }}" alt="{{ mirror.country_code }}" />
+ <br>
+ {% if mirror.country_name %}
+ <abbr title="{{ mirror.country_name }}">{{ mirror.country_code }}</abbr>
+ {% else %}
+ {{ mirror.country_code }}
+ {% end %}
+ {% if mirror in preferred_mirrors %}*{% end %}
+ {% end %}
+ </td>
+
{% if mirror.state == "UP" %}
<td style="background-color: green;">
</td>
{% else %}
<td style="background-color: grey;">
-
+ {{ mirror.state }}
</td>
{% end %}
<td>
- <a href="/mirror/{{ mirror.id }}">{{ mirror.hostname }}</a>
- </td>
- <td>
- {{ mirror.owner }}
- <br>
- <img src="{{ static_url("images/flags/%s.png" % mirror.country_code) }}" alt="{{ mirror.country_code }}" />
- {{ mirror.location_str }}
+ {% if mirror.state in ("OUTOFSYNC", "DOWN") %}
+ <span class="text-error pull-right">
+ {{ _("Last update: %s") % locale.format_date(mirror.last_update, relative=True) }}
+ </span>
+ {% end %}
+
+ <a href="/mirror/{{ mirror.hostname }}">{{ mirror.hostname }}</a>
+ <br>{{ mirror.owner }}
</td>
</tr>
{% end %}
{% if announcement %}
{{ _("Announcement") }}:
{% end %}
- <a href="/news/{{ escape(item.slug) }}">{{ escape(item.title) }}</a>
+ <a href="/news/{{ item.slug }}">{{ item.title }}</a>
</h2>
{% end %}
<div class="span12">
<p class="pull-right">
<a href="/author/{{ item.author_id }}">{{ item.author }}</a> -
- {{ locale.format_date(item.date, full_format=True) }}
+ {{ locale.format_date(item.published, full_format=True) }}
</p>
</div>
</div>
<li>
<a href="/news/{{ n.slug }}"><strong>{{ n.title }}</strong></a>
<br>
- {{ locale.format_date(n.date, shorter=True) }}
+ {{ locale.format_date(n.published, shorter=True) }}
<br>
</li>
{% end %}
--- /dev/null
+label {{ release.sname }}
+ menu label {{ release.name }}
+
+ text help
+{{ _("Install %s...") % release.name }}
+ endtext
+
+ kernel {{ release.netboot_kernel }}
+ initrd {{ release.netboot_initrd }}
+ append {{ release.netboot_append }}
+
--- /dev/null
+menu begin {{ id }}
+ menu title {{ title }}
+
+ label {{ id }}.back
+ menu label {{ _("Back...") }}
+ menu exit
+
+ {% module NetBootMenuSeparator() %}
+
+ {% for r in [r for r in releases if r.is_netboot_capable()] %}{% module NetBootMenuConfig(r) %}{% end %}
+menu end
--- /dev/null
+menu separator
prompt 0
allowoptions 0
-menu title IPFire boot menu
+menu title {{ _("IPFire boot menu") }}
-{{ menu }}
+{% module NetBootMenuConfig(latest_release) %}
+{% module NetBootMenuSeparator() %}
+
+{% module NetBootMenuHeader(_("Stable releases"), stable_releases) %}
+{% module NetBootMenuHeader(_("Development releases"), development_releases) %}
</div>
<div class="span4 ac">
- {% if wish.remaining_days >= 0 %}
- <p class="lead">{{ wish.remaining_days }}</p>
- <p>{{ _("day to go", "days to go", wish.remaining_days) }}</p>
+ {% if wish.status == "running" %}
+ {% if wish.remaining_days %}
+ <p class="lead">{{ wish.remaining_days }}</p>
+ <p>{{ _("day to go", "days to go", wish.remaining_days) }}</p>
+ {% else %}
+ <p class="lead">{% raw _("%s €") % (wish.goal - wish.donated) %}</p>
+ <p>{{ _("to go") }}</p>
+ {% end %}
{% elif wish.status == "in_progress" %}
<p class="lead">{{ _("In progress") }}</p>
{% elif wish.status == "finished" %}
<p class="ac">
<i class="icon-calendar"></i>
- {{ _("Launched: %s") % wish.date_start }}
+ {{ _("Launched: %s") % locale.format_date(wish.date_start, full_format=True) }}
•
- <i class="icon-time"></i>
- {{ _("Funding ends: %s") % wish.date_end }}
+ {% if wish.date_end %}
+ <i class="icon-time"></i>
+ {{ _("Funding ends: %s") % locale.format_date(wish.date_end, full_format=True) }}
+ {% else %}
+ {{ _("This funding runs until the goal is reached.") }}
+ {% end %}
</p>
{% end block %}
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-07-22 11:43+0200\n"
+"POT-Creation-Date: 2013-12-27 11:53+0100\n"
"PO-Revision-Date: 2013-07-22 11:44+0100\n"
"Last-Translator: Michael Tremer <michael.tremer@ipfire.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.5.4\n"
-#: webapp/handlers_news.py:43 webapp/ui_modules.py:76
-msgid "Unknown author"
-msgstr "Unbekannter Autor"
+#: webapp/backend/iuse.py:162
+#, python-format
+msgid "Mem: %s"
+msgstr "RAM: %s"
-#: webapp/__init__.py:285
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "January"
-msgstr "Januar"
+#: webapp/backend/iuse.py:165
+#, python-format
+msgid "Disk: %s"
+msgstr "HDD: %s"
-#: webapp/__init__.py:287
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "February"
-msgstr "Februar"
+#: webapp/backend/iuse.py:177
+#, python-format
+msgid "Networks: %s"
+msgstr "Netzwerke: %s"
-#: webapp/__init__.py:289
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "March"
-msgstr "März"
+#: webapp/backend/countries.py:7
+#, fuzzy
+msgid "Andorra"
+msgstr "Hersteller"
-#: webapp/__init__.py:291
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "April"
-msgstr "April"
+#: webapp/backend/countries.py:8
+msgid "United Arab Emirates"
+msgstr ""
-#: webapp/__init__.py:293
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "May"
-msgstr "Mai"
+#: webapp/backend/countries.py:9
+msgid "Afghanistan"
+msgstr ""
-#: webapp/__init__.py:295
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "June"
-msgstr "Juni"
+#: webapp/backend/countries.py:10
+msgid "Antigua and Barbuda"
+msgstr ""
-#: webapp/__init__.py:297
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "July"
-msgstr "Juli"
+#: webapp/backend/countries.py:11
+msgid "Aanguilla"
+msgstr ""
-#: webapp/__init__.py:299
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "August"
-msgstr "August"
+#: webapp/backend/countries.py:12
+msgid "Albania"
+msgstr ""
-#: webapp/__init__.py:301
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "September"
-msgstr "September"
+#: webapp/backend/countries.py:13
+msgid "Armenia"
+msgstr ""
-#: webapp/__init__.py:303
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "October"
-msgstr "Oktober"
+#: webapp/backend/countries.py:14
+msgid "Angola"
+msgstr ""
-#: webapp/__init__.py:305
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "November"
-msgstr "November"
+#: webapp/backend/countries.py:15
+msgid "Antarctica"
+msgstr ""
-#: webapp/__init__.py:307
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "December"
-msgstr "Dezember"
+#: webapp/backend/countries.py:16
+msgid "Argentina"
+msgstr ""
-#: webapp/ui_modules.py:239
-#, python-format
-msgid "%s to %s"
-msgstr "%s nach %s"
+#: webapp/backend/countries.py:17
+msgid "American Samoa"
+msgstr ""
-#: webapp/backend/wishlist.py:187
-msgid "Checkout this crowdfunding wish from #ipfire:"
+#: webapp/backend/countries.py:18
+msgid "Austria"
msgstr ""
-#: webapp/backend/releases.py:96
-msgid "Image for the armv5tel architecture"
-msgstr "Image für die armv5tel-Architektur"
+#: webapp/backend/countries.py:19
+msgid "Australia"
+msgstr ""
-#: webapp/backend/releases.py:97
-msgid "armv5tel image for boards with serial console"
-msgstr "armv5tel-Image für Boards mit serieller Konsole"
+#: webapp/backend/countries.py:20
+msgid "Aruba"
+msgstr ""
-#: webapp/backend/releases.py:98
-msgid "Installable CD image"
-msgstr "Bootbares CD-Image"
+#: webapp/backend/countries.py:21
+msgid "Ã…land Islands"
+msgstr ""
-#: webapp/backend/releases.py:99
-msgid "Torrent file"
-msgstr "Torrentdatei"
+#: webapp/backend/countries.py:22
+msgid "Azerbaijan"
+msgstr ""
-#: webapp/backend/releases.py:100
-msgid "Flash image"
-msgstr "Flash-Image"
+#: webapp/backend/countries.py:23
+msgid "Bosnia and Herzegovina"
+msgstr ""
-#: webapp/backend/releases.py:101
-msgid "Alix image"
-msgstr "Alix-Image"
+#: webapp/backend/countries.py:24
+msgid "Barbados"
+msgstr ""
-#: webapp/backend/releases.py:102
-msgid "USB FDD Image"
-msgstr "USB-FDD-Image"
+#: webapp/backend/countries.py:25
+msgid "Bangladesh"
+msgstr ""
-#: webapp/backend/releases.py:103
-msgid "USB HDD Image"
-msgstr "USB-HDD-Image"
+#: webapp/backend/countries.py:26
+msgid "Belgium"
+msgstr ""
-#: webapp/backend/releases.py:104
-msgid "Pregenerated Xen image"
-msgstr "Vorgefertigtes Xen-Image"
+#: webapp/backend/countries.py:27
+msgid "Burkina Faso"
+msgstr ""
-#: webapp/backend/releases.py:110 webapp/backend/releases.py:150
-msgid "Unknown image type"
-msgstr "Unbekanntes Imageformat"
+#: webapp/backend/countries.py:28
+msgid "Bulgaria"
+msgstr ""
-#: webapp/backend/releases.py:136
-msgid "This image runs on many ARM-based boards"
-msgstr "Dieses Image läuft auf vielen ARM-basierten Boards"
+#: webapp/backend/countries.py:29
+msgid "Bahrain"
+msgstr ""
-#: webapp/backend/releases.py:137
-msgid "This image runs on ARM boards with a serial console"
-msgstr "Dieses Image läuft auf ARM-Boards mit serieller Konsole"
+#: webapp/backend/countries.py:30
+msgid "Burundi"
+msgstr ""
-#: webapp/backend/releases.py:138
-msgid "Use this image to burn a CD and install IPFire from it."
+#: webapp/backend/countries.py:31
+msgid "Benin"
msgstr ""
-"Nutze dieses Image um eine CD zu erstellen und IPFire von dieser zu "
-"installieren."
-#: webapp/backend/releases.py:139
-msgid "Download the CD image from the torrent network."
-msgstr "CD-Image mit aus dem Torrentnetzwerk laden"
+#: webapp/backend/countries.py:32
+msgid "Saint Barthélemy"
+msgstr ""
-#: webapp/backend/releases.py:140
-msgid "An image that is meant to run on embedded devices."
-msgstr "Ein Image, das für eingebettete Systeme optimiert ist."
+#: webapp/backend/countries.py:33
+msgid "Bermuda"
+msgstr ""
-#: webapp/backend/releases.py:141
-msgid "Flash image where a serial console is enabled by default."
-msgstr "Image, bei welchem die serielle Konsole eingeschaltet ist."
+#: webapp/backend/countries.py:34
+msgid "Brunei Darussalam"
+msgstr ""
-#: webapp/backend/releases.py:142
-msgid "Install IPFire from a floppy-formated USB key."
-msgstr "IPFire von einem Floppy-formatiertem USB-Stick installieren."
+#: webapp/backend/countries.py:35
+msgid "Plurinational State of Bolivia"
+msgstr ""
-#: webapp/backend/releases.py:143
-msgid "If the floppy image doesn't work, use this image instead."
-msgstr "Wenn das Floppy-Image nicht funktioniert, dieses verwenden."
+#: webapp/backend/countries.py:36
+msgid "Sint Eustatius and Saba Bonaire"
+msgstr ""
-#: webapp/backend/releases.py:144
-msgid "A ready-to-run image for Xen."
-msgstr "Ein fertiges Image für Xen."
+#: webapp/backend/countries.py:37
+msgid "Brazil"
+msgstr ""
-#: webapp/backend/iuse.py:165
-#, python-format
-msgid "Mem: %s"
-msgstr "RAM: %s"
+#: webapp/backend/countries.py:38
+msgid "Bahamas"
+msgstr ""
-#: webapp/backend/iuse.py:168
-#, python-format
-msgid "Disk: %s"
-msgstr "HDD: %s"
+#: webapp/backend/countries.py:39
+msgid "Bhutan"
+msgstr ""
-#: webapp/backend/iuse.py:180
-#, python-format
-msgid "Networks: %s"
-msgstr "Netzwerke: %s"
+#: webapp/backend/countries.py:40
+msgid "Bouvet Island"
+msgstr ""
-#: templates/wishlist/wish.html:3
-msgid "Wish"
-msgstr "Wunsch"
+#: webapp/backend/countries.py:41
+msgid "Botswana"
+msgstr ""
-#: templates/wishlist/wish.html:18
-#, python-format
-msgid "Launched: %s"
-msgstr "Gestarted: %s"
+#: webapp/backend/countries.py:42
+msgid "Belarus"
+msgstr ""
-#: templates/wishlist/wish.html:23
-#, python-format
-msgid "Funding ends: %s"
-msgstr "Sammlung endet: %s"
+#: webapp/backend/countries.py:43
+msgid "Belize"
+msgstr ""
-#: templates/wishlist/closed.html:3 templates/wishlist/closed.html:13
-msgid "Closed wishes"
-msgstr "Beendete Wünsche"
+#: webapp/backend/countries.py:44
+msgid "Canada"
+msgstr ""
-#: templates/wishlist/closed.html:9
-msgid "Wishes open for donation"
-msgstr "Noch laufende Wünsche"
+#: webapp/backend/countries.py:45
+msgid "Cocos (Keeling) Islands"
+msgstr ""
-#: templates/wishlist/closed.html:36 templates/wishlist/closed.html:40
-msgid "Older"
-msgstr "Älter"
+#: webapp/backend/countries.py:46
+msgid "The Democratic Republic of the Congo"
+msgstr ""
-#: templates/wishlist/closed.html:46 templates/wishlist/closed.html:50
-msgid "Newer"
-msgstr "Neuer"
+#: webapp/backend/countries.py:47
+msgid "Central African Republic"
+msgstr ""
-#: templates/wishlist/base.html:6 templates/index.html:175
-msgid "IPFire Wishlist"
-msgstr "IPFire Wunschliste"
+#: webapp/backend/countries.py:48
+msgid "Congo"
+msgstr ""
-#: templates/wishlist/base.html:8
-msgid "Crowd funding for the IPFire project"
-msgstr "Crowdfunding für das IPFire-Projekt"
+#: webapp/backend/countries.py:49
+msgid "Switzerland"
+msgstr ""
-#: templates/wishlist/modules/wish.html:6
-msgid "Only a few days left!"
-msgstr "Nur noch wenige Tage!"
+#: webapp/backend/countries.py:50
+msgid "Côte d'Ivoire"
+msgstr ""
-#: templates/wishlist/modules/wish.html:26 templates/wishlist/donate.html:3
-#: templates/download-splash.html:37 templates/modules/menu.html:47
-#: templates/static/getinvolved.html:120 templates/static/donation.html:3
-#: templates/static/donation.html:8
-msgid "Donate"
-msgstr "Spenden"
+#: webapp/backend/countries.py:51
+msgid "Cook Islands"
+msgstr ""
-#: templates/wishlist/modules/wish.html:36
-msgid "funded"
-msgstr "gesammelt"
+#: webapp/backend/countries.py:52
+msgid "Chile"
+msgstr ""
-#: templates/wishlist/modules/wish.html:40
-#, python-format
-msgid "%s €"
-msgstr "%s €"
+#: webapp/backend/countries.py:53
+msgid "Cameroon"
+msgstr ""
-#: templates/wishlist/modules/wish.html:41
-msgid "donated"
-msgstr "gespendet"
+#: webapp/backend/countries.py:54
+msgid "China"
+msgstr ""
-#: templates/wishlist/modules/wish.html:47
-msgid "day to go"
-msgid_plural "days to go"
-msgstr[0] "Tag übrig"
-msgstr[1] "Tage übrig"
+#: webapp/backend/countries.py:55
+msgid "Colombia"
+msgstr ""
-#: templates/wishlist/modules/wish.html:49
-msgid "In progress"
-msgstr "In Entwicklung"
+#: webapp/backend/countries.py:56
+msgid "Costa Rica"
+msgstr ""
-#: templates/wishlist/modules/wish.html:51
-msgid "Finished"
-msgstr "Beendet"
+#: webapp/backend/countries.py:57
+msgid "Cuba"
+msgstr ""
-#: templates/wishlist/modules/wish.html:53
-msgid "Funding ended"
-msgstr "Sammlung beendet"
+#: webapp/backend/countries.py:58
+msgid "Cape Verde"
+msgstr ""
-#: templates/wishlist/modules/wish.html:63
-msgid "Share this wish with your friends and help us promote it!"
+#: webapp/backend/countries.py:59
+msgid "Curaçao"
msgstr ""
-"Teile diesen Wunsch mit deinen Freunden und hilf diesen bekannter zu machen!"
-#: templates/wishlist/index.html:3 templates/index.html:3
-msgid "Home"
-msgstr "Startseite"
+#: webapp/backend/countries.py:60
+msgid "Chrismas Islands"
+msgstr ""
-#: templates/wishlist/donate.html:13 templates/wishlist/donate.html:23
-#: templates/wishlist/terms.html:3 templates/wishlist/terms.html:7
-#: templates/base.html:78
-msgid "Terms & Conditions"
-msgstr "Allgemeine Bedingungen"
+#: webapp/backend/countries.py:61
+msgid "Cyprus"
+msgstr ""
-#: templates/downloads-index.html:3
-msgid "Download Center"
-msgstr "Downloadcenter"
+#: webapp/backend/countries.py:62
+msgid "Czech Republic"
+msgstr ""
-#: templates/downloads-index.html:7
-msgid "IPFire Download Center"
-msgstr "IPFire Download-Center"
+#: webapp/backend/countries.py:63
+msgid "Germany"
+msgstr ""
-#: templates/downloads-index.html:30
-msgid "Available releases"
-msgstr "Verfügbare Releases"
+#: webapp/backend/countries.py:64
+#, fuzzy
+msgid "Djibouti"
+msgstr "Ãœber"
-#: templates/downloads-index.html:35 templates/downloads-older.html:25
-#: templates/tracker-torrents.html:32
-msgid "Release"
-msgstr "Release"
+#: webapp/backend/countries.py:65
+msgid "Denmark"
+msgstr ""
-#: templates/downloads-index.html:36
-msgid "Release type"
-msgstr "Release-Typ"
+#: webapp/backend/countries.py:66
+msgid "Dominica"
+msgstr ""
-#: templates/downloads-index.html:37
-msgid "Release date"
-msgstr "Veröffentlichungsdatum"
+#: webapp/backend/countries.py:67
+msgid "Dominican Republic"
+msgstr ""
-#: templates/downloads-index.html:48
-msgid "Stable"
-msgstr "Stabil"
+#: webapp/backend/countries.py:68
+msgid "Algeria"
+msgstr ""
-#: templates/downloads-index.html:50 templates/modules/menu.html:65
-#: templates/static/development.html:3 templates/static/development.html:8
-#: templates/static/getinvolved.html:153
-msgid "Development"
-msgstr "Entwicklung"
+#: webapp/backend/countries.py:69
+msgid "Ecuador"
+msgstr ""
-#: templates/admin-downloads-base.html:5
-msgid "Back to home"
-msgstr "Zurück zur Startseite"
+#: webapp/backend/countries.py:70
+msgid "Estonia"
+msgstr ""
-#: templates/admin-downloads-base.html:8 templates/admin-base.html:6
-msgid "Options"
-msgstr "Optionen"
+#: webapp/backend/countries.py:71
+msgid "Egypt"
+msgstr ""
-#: templates/admin-downloads-base.html:11
-msgid "Mirror stats"
-msgstr "Mirrorstatistiken"
+#: webapp/backend/countries.py:72
+msgid "Western Sahara"
+msgstr ""
-#: templates/downloads-older.html:3 templates/downloads-older.html:7
-msgid "Ancient downloads"
-msgstr "Veraltete Downloads"
+#: webapp/backend/countries.py:73
+msgid "Eritrea"
+msgstr ""
-#: templates/downloads-older.html:9 templates/downloads-all.html:9
-msgid ""
-"These are the ancient downloads of IPFire. They are just saved for "
-"historical reasons and should not be used in a productive environment."
+#: webapp/backend/countries.py:74
+msgid "Spain"
msgstr ""
-"Dieses sind veraltete Downloads von IPFire. Sie wurden hier archiviert und "
-"sollten nicht in produktiven Umgebungen eingesetzt werden."
-#: templates/downloads-older.html:13
-msgid ""
-"Beware that these releases could lack possible security-fixes\tand so it is "
-"recommended to use the <em>latest</em> version."
+#: webapp/backend/countries.py:75
+msgid "Ethiopia"
msgstr ""
-"Achtung! Diese Releases könnten potentielle Sicherheitsprobleme aufweisen. "
-"Daher wird empfohlen die <em>neueste</em> Version einzusetzen."
-#: templates/downloads-older.html:17 templates/downloads-all.html:13
-msgid "Go back to latest stable downloads."
-msgstr "Zurück zu den neuesten stabilen Downloads."
+#: webapp/backend/countries.py:76
+msgid "Finland"
+msgstr ""
-#: templates/downloads-older.html:26
-msgid "Published on"
-msgstr "Veröffentlicht am"
+#: webapp/backend/countries.py:77
+msgid "Fiji"
+msgstr ""
-#: templates/admin-login.html:3
-msgid "Please login"
-msgstr "Bitte einloggen"
+#: webapp/backend/countries.py:78
+msgid "Falkland Islands (Malvinas)"
+msgstr ""
-#: templates/mirrors-item.html:3
-#, python-format
-msgid "Mirror %s"
-msgstr "Mirror %s"
+#: webapp/backend/countries.py:79
+msgid "Federated States of Micronesia"
+msgstr ""
-#: templates/mirrors-item.html:8
-msgid "Up"
-msgstr "Verfügbar"
+#: webapp/backend/countries.py:80
+msgid "Faroe Islands"
+msgstr ""
-#: templates/mirrors-item.html:10
-msgid "Down"
-msgstr "Nicht verfügbar"
+#: webapp/backend/countries.py:81
+#, fuzzy
+msgid "France"
+msgstr "Abbrechen"
-#: templates/mirrors-item.html:12
-msgid "Out of sync"
-msgstr "Nicht synchronisiert"
+#: webapp/backend/countries.py:82
+msgid "Gabon"
+msgstr ""
-#: templates/mirrors-item.html:14 templates/fireinfo/profile-detail.html:74
-#: templates/fireinfo/profile-detail.html:82
-msgid "Unknown"
-msgstr "Unbekannt"
+#: webapp/backend/countries.py:83
+msgid "United Kingdom"
+msgstr ""
-#: templates/mirrors-item.html:22 templates/downloads-mirrors.html:50
-#: templates/fireinfo/profile-detail.html:231
-#: templates/download-mirror-detail.html:20 templates/admin-mirrors.html:15
-msgid "Last update"
-msgstr "Letztes Update"
+#: webapp/backend/countries.py:84
+msgid "Grenada"
+msgstr ""
-#: templates/mirrors-item.html:26 templates/downloads-mirrors.html:47
-#: templates/admin-mirrors-create.html:20
-#: templates/download-mirror-detail.html:16
-#: templates/admin-mirrors-details.html:21
-msgid "Owner"
-msgstr "Eigentümer"
+#: webapp/backend/countries.py:85
+msgid "Georgia"
+msgstr ""
-#: templates/mirrors-item.html:31
-msgid "Preferred for"
-msgstr "Bevorzugt für"
+#: webapp/backend/countries.py:86
+msgid "French Guiana"
+msgstr ""
-#: templates/mirrors-item.html:37
-msgid "Your distance to this mirror"
-msgstr "Deine Entfernung zu diesem Mirror"
+#: webapp/backend/countries.py:87
+msgid "Guersey"
+msgstr ""
-#: templates/mirrors-item.html:43
-msgid "Go to mirror"
-msgstr "Zum Mirror"
+#: webapp/backend/countries.py:88
+msgid "Ghana"
+msgstr ""
-#: templates/mirrors-item.html:48
-msgid "Mirror location"
-msgstr "Mirrorort"
+#: webapp/backend/countries.py:89
+msgid "Gibraltar"
+msgstr ""
-#: templates/mirrors-item.html:50
-#, python-format
-msgid "The mirror <em>%s</em> is located in %s."
-msgstr "Der Mirrorserver <em>%s</em> befindet sich in %s."
+#: webapp/backend/countries.py:90
+msgid "Greenland"
+msgstr ""
-#: templates/mirrors-item.html:58
-msgid "View larger map"
-msgstr "Größere Karte ansehen"
+#: webapp/backend/countries.py:91
+msgid "Gambia"
+msgstr ""
-#: templates/mirrors-item.html:63
-msgid "The location of the mirror server is estimated by the IP address."
+#: webapp/backend/countries.py:92
+msgid "Guinea"
msgstr ""
-"Der Standort dieses Mirrorservers wurde anhand der IP-Adresse geschätzt."
-#: templates/mirrors-item.html:66
-msgid "The location of the mirror server could not be estimated."
-msgstr "Der Standort dieses Mirrorservers konnte nicht ermittelt werden."
+#: webapp/backend/countries.py:93
+msgid "Guadeloupe"
+msgstr ""
-#: templates/admin-downloads-mirrors.html:5 templates/admin-downloads.html:5
-msgid "Download statistics"
-msgstr "Downloadstatistiken"
+#: webapp/backend/countries.py:94
+msgid "Equatorial Guinea"
+msgstr ""
-#: templates/admin-downloads-mirrors.html:7
-msgid "Mirror load from today"
-msgstr "Mirrorauslastung von heute"
+#: webapp/backend/countries.py:95
+msgid "Greece"
+msgstr ""
-#: templates/admin-downloads-mirrors.html:10
-msgid "Mirror load"
-msgstr "Mirrorauslastung"
+#: webapp/backend/countries.py:96
+msgid "South Georgia and the South Sandwich Islands"
+msgstr ""
-#: templates/news-year.html:3 templates/news.html:3
-msgid "News"
-msgstr "Neuigkeiten"
+#: webapp/backend/countries.py:97
+msgid "Guatemala"
+msgstr ""
-#: templates/news-year.html:7
-#, python-format
-msgid "News from %(year)s"
-msgstr "Neuigkeiten aus %(year)s"
+#: webapp/backend/countries.py:98
+msgid "Guam"
+msgstr ""
-#: templates/tracker-torrent-detail.html:3
-#: templates/tracker-torrent-detail.html:18
-#: templates/modules/release-item.html:115
-msgid "Torrent download"
-msgstr "Torrent-Download"
+#: webapp/backend/countries.py:99
+msgid "Guinea-Bissau"
+msgstr ""
-#: templates/tracker-torrent-detail.html:15
-#: templates/modules/release-item.html:114
-msgid "Magnet link"
-msgstr "Magnet-Link"
+#: webapp/backend/countries.py:100
+msgid "Guyana"
+msgstr ""
-#: templates/tracker-torrent-detail.html:23 templates/tracker-torrents.html:34
-msgid "Peers"
-msgstr "Peers"
+#: webapp/backend/countries.py:101
+msgid "Hong Kong"
+msgstr ""
-#: templates/tracker-torrent-detail.html:28
-msgid "Seeds"
-msgstr "Seeds"
+#: webapp/backend/countries.py:102
+msgid "Heard Island and McDonald Islands"
+msgstr ""
-#: templates/sources.html:3
-msgid "Sources"
-msgstr "Quellen"
+#: webapp/backend/countries.py:103
+msgid "Honduras"
+msgstr ""
-#: templates/sources.html:6 templates/static/development.html:263
-msgid "Source Code"
-msgstr "Quellcode"
+#: webapp/backend/countries.py:104
+msgid "Croatia"
+msgstr ""
-#: templates/sources.html:9
-#, python-format
-msgid "There are %s source files on the server."
-msgstr "Es befinden sich %s Quelldateien auf dem Server."
+#: webapp/backend/countries.py:105
+msgid "Haiti"
+msgstr ""
-#: templates/news-author.html:7
-#, python-format
-msgid "%s's announcements"
-msgstr "%ss Ankündigungen"
+#: webapp/backend/countries.py:106
+msgid "Hungary"
+msgstr ""
-#: templates/admin-index.html:5
-msgid "Admin Area"
-msgstr "Adminbereich"
+#: webapp/backend/countries.py:107
+msgid "Indonesia"
+msgstr ""
-#: templates/admin-base.html:3
-msgid "IPFire Admin Area"
-msgstr "IPFire Adminbereich"
+#: webapp/backend/countries.py:108
+msgid "Ireland"
+msgstr ""
-#: templates/admin-base.html:9
-msgid "Accounts"
-msgstr "Accounts"
+#: webapp/backend/countries.py:109
+msgid "Israel"
+msgstr ""
-#: templates/admin-base.html:10 templates/modules/menu.html:110
-msgid "Mirrors"
-msgstr "Mirrors"
+#: webapp/backend/countries.py:110
+msgid "Isle of Man"
+msgstr ""
-#: templates/admin-base.html:11 templates/modules/menu.html:92
-msgid "Planet"
-msgstr "Planet"
+#: webapp/backend/countries.py:111
+msgid "India"
+msgstr ""
-#: templates/admin-base.html:12
-msgid "Downloads"
-msgstr "Downloads"
+#: webapp/backend/countries.py:112
+msgid "British Indian Ocean Territory"
+msgstr ""
-#: templates/admin-planet-compose.html:5 templates/admin-planet.html:8
-msgid "Compose new entry"
-msgstr "Neuen Beitrag erstellen"
+#: webapp/backend/countries.py:113
+msgid "Iraq"
+msgstr ""
-#: templates/admin-planet-compose.html:16 templates/admin-planet.html:14
-msgid "Title"
-msgstr "Titel"
+#: webapp/backend/countries.py:114
+msgid "Islamic Republic of Iran"
+msgstr ""
-#: templates/admin-planet-compose.html:33 templates/planet/posting.html:19
-msgid "Tags"
-msgstr "Tags"
+#: webapp/backend/countries.py:115
+msgid "Iceland"
+msgstr ""
-#: templates/admin-planet-compose.html:41
-msgid "Save"
-msgstr "Speichern"
+#: webapp/backend/countries.py:116
+msgid "Italy"
+msgstr ""
-#: templates/admin-planet-compose.html:42
-msgid "Preview"
-msgstr "Vorschau"
+#: webapp/backend/countries.py:117
+msgid "Jersey"
+msgstr ""
-#: templates/admin-planet-compose.html:43
-msgid "Cancel"
-msgstr "Abbrechen"
+#: webapp/backend/countries.py:118
+msgid "Jamaica"
+msgstr ""
-#: templates/download-splash.html:3 templates/download-splash.html:7
-msgid "Thanks for downloading IPFire!"
-msgstr "Vielen Dank, für das Herunterladen von IPFire! "
+#: webapp/backend/countries.py:119
+msgid "Jordan"
+msgstr ""
-#: templates/download-splash.html:61
-msgid "Next steps"
-msgstr "Nächste Schritte"
+#: webapp/backend/countries.py:120
+msgid "Japan"
+msgstr ""
-#: templates/download-splash.html:66
-msgid "Install IPFire"
-msgstr "IPFire installieren"
+#: webapp/backend/countries.py:121
+msgid "Kenya"
+msgstr ""
-#: templates/download-splash.html:82
-msgid "Access documentation"
-msgstr "Dokumentation lesen"
+#: webapp/backend/countries.py:122
+msgid "Kyrgyzstan"
+msgstr ""
-#: templates/download-splash.html:100
-msgid "Join the community"
-msgstr "Der Community beitreten"
+#: webapp/backend/countries.py:123
+msgid "Cambodia"
+msgstr ""
-#: templates/downloads-development.html:3
-#: templates/downloads-development.html:6
-msgid "Development Downloads"
-msgstr "Development Downloads"
+#: webapp/backend/countries.py:124
+msgid "Kiribati"
+msgstr ""
-#: templates/error-500.html:6
-msgid "Detailed information"
-msgstr "Mehr Informationen"
+#: webapp/backend/countries.py:125
+msgid "Comoros"
+msgstr ""
-#: templates/admin-planet.html:5
-msgid "Planet Administrator"
-msgstr "Planet Administrator"
+#: webapp/backend/countries.py:126
+msgid "Saint Kitts and Nevis"
+msgstr ""
-#: templates/admin-planet.html:13
-msgid "Author"
-msgstr "Autor"
+#: webapp/backend/countries.py:127
+msgid "Democratic People's Republic of Korea"
+msgstr ""
-#: templates/admin-planet.html:21 templates/admin-mirrors.html:24
-#: templates/admin-accounts.html:20
-msgid "Edit"
-msgstr "Bearbeiten"
+#: webapp/backend/countries.py:128
+msgid "Republic of Korea"
+msgstr ""
-#: templates/downloads-mirrors.html:3 templates/download-mirror-detail.html:3
-msgid "Mirror-Server"
-msgstr "Mirrorserver"
+#: webapp/backend/countries.py:129
+msgid "Kuwait"
+msgstr ""
-#: templates/downloads-mirrors.html:8 templates/download-mirror-detail.html:8
-msgid "IPFire Mirrors"
-msgstr "IPFire Mirrors"
+#: webapp/backend/countries.py:130
+msgid "Cayman Islands"
+msgstr ""
-#: templates/downloads-mirrors.html:48 templates/admin-mirrors-create.html:12
-#: templates/download-mirror-detail.html:12 templates/admin-mirrors.html:14
-#: templates/admin-mirrors-details.html:13
-msgid "Hostname"
-msgstr "Hostname"
+#: webapp/backend/countries.py:131
+msgid "Kazakhstan"
+msgstr ""
-#: templates/downloads-mirrors.html:49 templates/admin-mirrors-create.html:24
-#: templates/admin-mirrors-details.html:25
-msgid "Location"
-msgstr "Standort"
+#: webapp/backend/countries.py:132
+msgid "Lao People's Democratic Public"
+msgstr ""
-#: templates/downloads-mirrors.html:63
-msgid "details"
-msgstr "Details"
+#: webapp/backend/countries.py:133
+msgid "Lebanon"
+msgstr ""
-#: templates/fireinfo/stats.html:3 templates/modules/menu.html:136
-msgid "Statistics"
-msgstr "Statistiken"
+#: webapp/backend/countries.py:134
+msgid "Saint Lucia"
+msgstr ""
-#: templates/fireinfo/stats.html:7
-msgid "fireinfo statistics"
-msgstr "Fireinfo Statistiken"
+#: webapp/backend/countries.py:135
+msgid "Liechtenstein"
+msgstr ""
-#: templates/fireinfo/stats.html:17
-msgid "IPFire versions"
-msgstr "IPFire-Versionen"
+#: webapp/backend/countries.py:136
+msgid "Sri Lanka"
+msgstr ""
-#: templates/fireinfo/stats.html:38 templates/fireinfo/stats-geo.html:3
-#: templates/fireinfo/stats-geo.html:7
-msgid "Geo locations"
-msgstr "Geographischer Standort"
+#: webapp/backend/countries.py:137
+msgid "Liberia"
+msgstr ""
-#: templates/fireinfo/stats.html:59 templates/fireinfo/stats-cpus.html:7
-msgid "Hardware: CPUs"
-msgstr "Hardware: CPUs"
+#: webapp/backend/countries.py:138
+msgid "Lesotho"
+msgstr ""
-#: templates/fireinfo/stats.html:73
-msgid "CPU features"
-msgstr "CPU-Funktionen"
+#: webapp/backend/countries.py:139
+msgid "Lithuania"
+msgstr ""
-#: templates/fireinfo/stats.html:85
-msgid "Hardware: Memory"
-msgstr "Hardware: Arbeitsspeicher"
+#: webapp/backend/countries.py:140
+msgid "Luxembourg"
+msgstr ""
-#: templates/fireinfo/stats.html:106 templates/fireinfo/stats-network.html:3
-#: templates/fireinfo/profile-detail.html:95
-msgid "Network"
-msgstr "Netzwerk"
+#: webapp/backend/countries.py:141
+msgid "Latvia"
+msgstr ""
-#: templates/fireinfo/stats.html:127 templates/fireinfo/stats-virtual.html:3
-#: templates/base-feature.html:65 templates/static/features.html:1179
-#: templates/static/features.html:1404
-msgid "Virtualization"
-msgstr "Virtualisierung"
+#: webapp/backend/countries.py:142
+msgid "Libya"
+msgstr ""
-#: templates/fireinfo/stats-network.html:7
-msgid "Network configuration"
-msgstr "Netzwerkkonfiguration"
+#: webapp/backend/countries.py:143
+msgid "Morocco"
+msgstr ""
-#: templates/fireinfo/stats-oses.html:3
-#: templates/fireinfo/profile-detail.html:12
-msgid "Operating system"
-msgstr "Betriebssystem"
+#: webapp/backend/countries.py:144
+msgid "Monaco"
+msgstr ""
-#: templates/fireinfo/stats-oses.html:7
-msgid "Releases"
-msgstr "Releases"
+#: webapp/backend/countries.py:145
+msgid "Republic of Moldova"
+msgstr ""
-#: templates/fireinfo/stats-oses.html:18
-msgid "Architectures"
-msgstr "Architekturen"
+#: webapp/backend/countries.py:146
+msgid "Montenegro"
+msgstr ""
-#: templates/fireinfo/stats-oses.html:25
-msgid "Kernels"
-msgstr "Kernel"
+#: webapp/backend/countries.py:147
+msgid "Saint Martin (French Part)"
+msgstr ""
-#: templates/fireinfo/profile-notfound.html:3
-#: templates/fireinfo/profile-notfound.html:8
-msgid "Profile not found"
-msgstr "Profil nicht gefunden"
+#: webapp/backend/countries.py:148
+msgid "Madagascar"
+msgstr ""
-#: templates/fireinfo/stats-virtual.html:7
-msgid "Virtualization support"
-msgstr "Virtualisierungsunterstützung"
+#: webapp/backend/countries.py:149
+msgid "Marshall Islands"
+msgstr ""
-#: templates/fireinfo/stats-virtual.html:35
-msgid "Hypervisors"
-msgstr "Hypervisoren"
+#: webapp/backend/countries.py:150
+msgid "The former Yugoslav Republic of Macedonia"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:3
-#: templates/fireinfo/profile-detail.html:7
-msgid "Profile"
-msgstr "Profil"
+#: webapp/backend/countries.py:151
+msgid "Mali"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:16
-msgid "Version"
-msgstr "Version"
+#: webapp/backend/countries.py:152
+msgid "Myanmar"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:24
-msgid "Architecture"
-msgstr "Architektur"
+#: webapp/backend/countries.py:153
+msgid "Mongolia"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:32
-msgid "Kernel version"
-msgstr "Kernelversion"
+#: webapp/backend/countries.py:154
+msgid "Macao"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:43
-msgid "Hypervisor"
-msgstr "Hypervisor"
+#: webapp/backend/countries.py:155
+msgid "Northern Mariana Islands"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:45
-msgid "This machine is running in a virtual environment."
-msgstr "Diese Maschine läuft in einer virtuellen Umgebung."
+#: webapp/backend/countries.py:156
+msgid "Martinique"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:51
-#: templates/fireinfo/profile-detail.html:71
-#: templates/fireinfo/profile-detail.html:130
-msgid "Vendor"
-msgstr "Hersteller"
+#: webapp/backend/countries.py:157
+msgid "Mauritania"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:59
-msgid "Type"
-msgstr "Typ"
+#: webapp/backend/countries.py:158
+msgid "Montserrat"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:67
-msgid "Hardware vendor"
-msgstr "Hardwarehersteller"
+#: webapp/backend/countries.py:159
+msgid "Malta"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:79
-#: templates/fireinfo/profile-detail.html:138
-msgid "Model"
-msgstr "Modell"
+#: webapp/backend/countries.py:160
+msgid "Mauritius"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:97
-msgid "Enabled network zones"
-msgstr "Eingeschaltete Netzwerkzonen"
+#: webapp/backend/countries.py:161
+msgid "Maldives"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:119 templates/base-feature.html:62
-#: templates/static/features.html:1104 templates/static/features.html:1399
-msgid "Hardware"
-msgstr "Hardware"
+#: webapp/backend/countries.py:162
+msgid "Malawi"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:125
-msgid "CPU"
-msgstr "CPU"
+#: webapp/backend/countries.py:163
+msgid "Mexico"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:141
-msgid "Not available"
-msgstr "Nicht verfügbar"
+#: webapp/backend/countries.py:164
+msgid "Malaysia"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:146
-msgid "Cores"
-msgstr "Kerne"
+#: webapp/backend/countries.py:165
+msgid "Mozambique"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:154
-#: templates/fireinfo/stats-cpus.html:36
-msgid "Speed"
-msgstr "Geschwindigkeit"
+#: webapp/backend/countries.py:166
+msgid "Namibia"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:166
-msgid "Supported features"
-msgstr "Unterstützte Funktionen"
+#: webapp/backend/countries.py:167
+msgid "New Caledonia"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:170
-msgid "64 bit capable"
-msgstr "64-Bit fähig"
+#: webapp/backend/countries.py:168
+msgid "Niger"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:174
-msgid "PAE capable"
-msgstr "PAE fähig"
+#: webapp/backend/countries.py:169
+msgid "Norfolk Island"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:178
-msgid "VT-x/AMD-V"
-msgstr "VT-x/AMD-V"
+#: webapp/backend/countries.py:170
+msgid "Nigeria"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:190
-msgid "Memory size"
-msgstr "Arbeitsspeichergröße"
+#: webapp/backend/countries.py:171
+msgid "Nicaragua"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:198
-msgid "System disk size"
-msgstr "Systemplattengröße"
+#: webapp/backend/countries.py:172
+msgid "Netherlands"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:211
-msgid "Peripherial devices"
-msgstr "Peripheriegeräte"
+#: webapp/backend/countries.py:173
+msgid "Norway"
+msgstr ""
-#: templates/fireinfo/profile-detail.html:216
-msgid "Signature images"
-msgstr "Signaturbilder"
+#: webapp/backend/countries.py:174
+msgid "Nepal"
+msgstr ""
-#: templates/fireinfo/base.html:6 templates/modules/menu.html:98
-msgid "Fireinfo"
-msgstr "Fireinfo"
+#: webapp/backend/countries.py:175
+msgid "Nauru"
+msgstr ""
-#: templates/fireinfo/base.html:7
-msgid "A hardware data collection tool for IPFire"
-msgstr "Ein Hardwaredatensammeltool für IPFire"
+#: webapp/backend/countries.py:176
+msgid "Niue"
+msgstr ""
-#: templates/fireinfo/stats-cpus.html:3
-msgid "Processors"
-msgstr "Prozessoren"
+#: webapp/backend/countries.py:177
+msgid "New Zealand"
+msgstr ""
-#: templates/fireinfo/stats-cpus.html:12
-msgid "See statistics about common CPU flags"
-msgstr "Statistiken über CPU-Funktionen"
+#: webapp/backend/countries.py:178
+msgid "Oman"
+msgstr ""
-#: templates/fireinfo/stats-cpus.html:19
-msgid "Vendors"
-msgstr "Hersteller"
+#: webapp/backend/countries.py:179
+msgid "Panama"
+msgstr ""
-#: templates/fireinfo/stats-cpus.html:38
-#, python-format
-msgid ""
-"The average speed of all systems in the database is: <strong>%.2f MHz</"
-"strong>."
+#: webapp/backend/countries.py:180
+msgid "Peru"
msgstr ""
-"Die durchschnittliche Geschwindigkeit aller System ist: <strong>%.2f MHz</"
-"strong>."
-#: templates/fireinfo/stats-cpus.html:40
-#, python-format
-msgid "All together, there are <strong>%s bogomips</strong> out there."
-msgstr "Zusammengenomen sind es <strong>%s Bogomips</strong>."
+#: webapp/backend/countries.py:181
+msgid "French Polynesia"
+msgstr ""
-#: templates/fireinfo/stats-cpus.html:48
-msgid "CPU core counter"
-msgstr "CPU-Kerne"
+#: webapp/backend/countries.py:182
+msgid "Papua New Guinea"
+msgstr ""
-#: templates/fireinfo/stats-cpus.html:50
-msgid ""
-"See a breakdown of the CPU cores that are installed on the IPFire systems."
-msgstr "Eine Übersicht über die CPU Kerne, der IPFire Systeme."
+#: webapp/backend/countries.py:183
+msgid "Philipplines"
+msgstr ""
-#: templates/fireinfo/index.html:52
-msgid "Show"
-msgstr "Anzeigen"
+#: webapp/backend/countries.py:184
+msgid "Pakistan"
+msgstr ""
-#: templates/fireinfo/model-detail.html:11
-#, python-format
-msgid "This device is installed on approximately %.2f%% of all systems."
-msgstr "Dieses Gerät ist in etwa %.2f%% aller Systeme installiert."
+#: webapp/backend/countries.py:185
+msgid "Poland"
+msgstr ""
-#: templates/fireinfo/model-detail.html:14
-msgid "Feedback"
-msgstr "Feedback"
+#: webapp/backend/countries.py:186
+msgid "Saint Pierre and Miquelon"
+msgstr ""
-#: templates/fireinfo/model-detail.html:28
-msgid "Go to the wiki"
-msgstr "Zum Wiki"
+#: webapp/backend/countries.py:187
+msgid "Pitcairn"
+msgstr ""
-#: templates/fireinfo/stats-memory.html:3
-#: templates/fireinfo/stats-memory.html:7
-msgid "Memory"
-msgstr "Arbeitsspeicher"
+#: webapp/backend/countries.py:188
+msgid "Puerto Rico"
+msgstr ""
-#: templates/fireinfo/stats-memory.html:13
-#, python-format
-msgid ""
-"The average amount of memory of all systems in the database is: <strong>%.2f "
-"MB</strong>."
+#: webapp/backend/countries.py:189
+msgid "Palestinian Territory, occupied"
msgstr ""
-"Die durchschnittliche Menge an Arbeitsspeicher aller System ist: <strong>"
-"%.2f MB</strong>."
-#: templates/fireinfo/stats-geo.html:28
-msgid "Language selection"
-msgstr "Sprachauswahl"
+#: webapp/backend/countries.py:190
+msgid "Portugal"
+msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:3
-msgid "CPU flags"
-msgstr "CPU Flags"
+#: webapp/backend/countries.py:191
+msgid "Palau"
+msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:7
-msgid "Processor flags"
-msgstr "Prozessor-Flags"
+#: webapp/backend/countries.py:192
+msgid "Paraguay"
+msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:30
-msgid "CPUs that support 64 bits"
-msgstr "CPUs, die 64 Bit unterstützen"
+#: webapp/backend/countries.py:193
+msgid "Qatar"
+msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:46
-msgid "CPUs with PAE"
-msgstr "CPUs mit PAE"
+#: webapp/backend/countries.py:194
+msgid "Réunion"
+msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:62
-msgid "CPUs that support virtualization"
-msgstr "CPUs, die Virtualisierung unterstützen"
+#: webapp/backend/countries.py:195
+msgid "Romania"
+msgstr ""
-#: templates/fireinfo/stats-admin.html:3
-msgid "Admin"
-msgstr "Administrator"
+#: webapp/backend/countries.py:196
+msgid "Serbia"
+msgstr ""
-#: templates/fireinfo/stats-admin.html:11
-msgid "Sending profiles"
-msgstr "Senden Profile"
+#: webapp/backend/countries.py:197
+msgid "Russian Federation"
+msgstr ""
-#: templates/fireinfo/stats-admin.html:19
-msgid "Archive size"
-msgstr "Archivgröße"
+#: webapp/backend/countries.py:198
+msgid "Rwanda"
+msgstr ""
-#: templates/downloads.html:3 templates/downloads.html:8
-msgid "Get IPFire"
-msgstr "IPFire herunterladen"
+#: webapp/backend/countries.py:199
+msgid "Saudi Arabia"
+msgstr ""
-#: templates/downloads.html:10
-msgid "IPFire is completely free to download and use"
+#: webapp/backend/countries.py:200
+msgid "Solomon Islands"
+msgstr ""
+
+#: webapp/backend/countries.py:201
+msgid "Seychelles"
+msgstr ""
+
+#: webapp/backend/countries.py:202
+msgid "Sudan"
+msgstr ""
+
+#: webapp/backend/countries.py:203
+msgid "Sweden"
+msgstr ""
+
+#: webapp/backend/countries.py:204
+msgid "Singapore"
+msgstr ""
+
+#: webapp/backend/countries.py:205
+msgid "Saint Helena, Ascension and Tristan Da Cunha"
+msgstr ""
+
+#: webapp/backend/countries.py:206
+msgid "Slovenia"
+msgstr ""
+
+#: webapp/backend/countries.py:207
+msgid "Svalbard and Jan Mayen"
+msgstr ""
+
+#: webapp/backend/countries.py:208
+msgid "Slovakia"
+msgstr ""
+
+#: webapp/backend/countries.py:209
+msgid "Sierra Leone"
+msgstr ""
+
+#: webapp/backend/countries.py:210
+msgid "San Marino"
+msgstr ""
+
+#: webapp/backend/countries.py:211
+msgid "Senegal"
+msgstr ""
+
+#: webapp/backend/countries.py:212
+msgid "Somalia"
+msgstr ""
+
+#: webapp/backend/countries.py:213
+msgid "Suriname"
+msgstr ""
+
+#: webapp/backend/countries.py:214
+msgid "South Sudan"
+msgstr ""
+
+#: webapp/backend/countries.py:215
+msgid "Sao Tome and Principe"
+msgstr ""
+
+#: webapp/backend/countries.py:216
+msgid "El Salvador"
+msgstr ""
+
+#: webapp/backend/countries.py:217
+msgid "Sint Maarten (Dutch Part)"
+msgstr ""
+
+#: webapp/backend/countries.py:218
+msgid "Syrian Arab Republic"
+msgstr ""
+
+#: webapp/backend/countries.py:219
+msgid "Swaziland"
+msgstr ""
+
+#: webapp/backend/countries.py:220
+msgid "Turks and Caicos Islands"
+msgstr ""
+
+#: webapp/backend/countries.py:221
+msgid "Chad"
+msgstr ""
+
+#: webapp/backend/countries.py:222
+msgid "French Southern Territories"
+msgstr ""
+
+#: webapp/backend/countries.py:223
+msgid "Togo"
+msgstr ""
+
+#: webapp/backend/countries.py:224
+msgid "Thailand"
+msgstr ""
+
+#: webapp/backend/countries.py:225
+msgid "Tajikistan"
+msgstr ""
+
+#: webapp/backend/countries.py:226
+msgid "Tokelau"
+msgstr ""
+
+#: webapp/backend/countries.py:227
+msgid "Timor-Leste"
+msgstr ""
+
+#: webapp/backend/countries.py:228
+msgid "Turkmenistan"
+msgstr ""
+
+#: webapp/backend/countries.py:229
+msgid "Tunisia"
+msgstr ""
+
+#: webapp/backend/countries.py:230
+msgid "Tonga"
+msgstr ""
+
+#: webapp/backend/countries.py:231
+msgid "Turkey"
+msgstr ""
+
+#: webapp/backend/countries.py:232
+msgid "Trinidad and Tobago"
+msgstr ""
+
+#: webapp/backend/countries.py:233
+msgid "Tuvalu"
+msgstr ""
+
+#: webapp/backend/countries.py:234
+msgid "Taiwan, Province of China"
+msgstr ""
+
+#: webapp/backend/countries.py:235
+msgid "United Republic of Tanzania"
+msgstr ""
+
+#: webapp/backend/countries.py:236
+msgid "Ukraine"
+msgstr ""
+
+#: webapp/backend/countries.py:237
+msgid "Uganda"
+msgstr ""
+
+#: webapp/backend/countries.py:238
+msgid "Unites States minor outlying islands"
+msgstr ""
+
+#: webapp/backend/countries.py:239
+msgid "Unites States"
+msgstr ""
+
+#: webapp/backend/countries.py:240
+msgid "Uruguay"
+msgstr ""
+
+#: webapp/backend/countries.py:241
+msgid "Uzbekistan"
+msgstr ""
+
+#: webapp/backend/countries.py:242
+msgid "Vatican City State"
+msgstr ""
+
+#: webapp/backend/countries.py:243
+msgid "Saint Vincent and the Grenadines"
+msgstr ""
+
+#: webapp/backend/countries.py:244
+msgid "Bolivarian Republic of Venezuela"
+msgstr ""
+
+#: webapp/backend/countries.py:245
+msgid "Virgin Islands, British"
+msgstr ""
+
+#: webapp/backend/countries.py:246
+msgid "Virgin Islands, U.S."
+msgstr ""
+
+#: webapp/backend/countries.py:247
+msgid "Viet Nam"
+msgstr ""
+
+#: webapp/backend/countries.py:248
+msgid "Vanuatu"
+msgstr ""
+
+#: webapp/backend/countries.py:249
+msgid "Wallis and Futuna"
+msgstr ""
+
+#: webapp/backend/countries.py:250
+msgid "Samoa"
+msgstr ""
+
+#: webapp/backend/countries.py:251
+msgid "Yemen"
+msgstr ""
+
+#: webapp/backend/countries.py:252
+msgid "Mayotte"
+msgstr ""
+
+#: webapp/backend/countries.py:253
+msgid "South Africa"
+msgstr ""
+
+#: webapp/backend/countries.py:254
+msgid "Zambia"
+msgstr ""
+
+#: webapp/backend/countries.py:255
+msgid "Zimbabwe"
+msgstr ""
+
+#: webapp/backend/wishlist.py:207
+msgid "Checkout this crowdfunding wish from #ipfire:"
+msgstr ""
+
+#: webapp/backend/releases.py:89
+msgid "Image for the armv5tel architecture"
+msgstr "Image für die armv5tel-Architektur"
+
+#: webapp/backend/releases.py:90
+msgid "armv5tel image for boards with serial console"
+msgstr "armv5tel-Image für Boards mit serieller Konsole"
+
+#: webapp/backend/releases.py:91
+msgid "Installable CD image"
+msgstr "Bootbares CD-Image"
+
+#: webapp/backend/releases.py:92
+msgid "Torrent file"
+msgstr "Torrentdatei"
+
+#: webapp/backend/releases.py:93
+msgid "Flash image"
+msgstr "Flash-Image"
+
+#: webapp/backend/releases.py:94
+msgid "Alix image"
+msgstr "Alix-Image"
+
+#: webapp/backend/releases.py:95
+msgid "USB FDD Image"
+msgstr "USB-FDD-Image"
+
+#: webapp/backend/releases.py:96
+msgid "USB HDD Image"
+msgstr "USB-HDD-Image"
+
+#: webapp/backend/releases.py:97
+msgid "Pregenerated Xen image"
+msgstr "Vorgefertigtes Xen-Image"
+
+#: webapp/backend/releases.py:103 webapp/backend/releases.py:143
+msgid "Unknown image type"
+msgstr "Unbekanntes Imageformat"
+
+#: webapp/backend/releases.py:129
+msgid "This image runs on many ARM-based boards"
+msgstr "Dieses Image läuft auf vielen ARM-basierten Boards"
+
+#: webapp/backend/releases.py:130
+msgid "This image runs on ARM boards with a serial console"
+msgstr "Dieses Image läuft auf ARM-Boards mit serieller Konsole"
+
+#: webapp/backend/releases.py:131
+msgid "Use this image to burn a CD and install IPFire from it."
+msgstr ""
+"Nutze dieses Image um eine CD zu erstellen und IPFire von dieser zu "
+"installieren."
+
+#: webapp/backend/releases.py:132
+msgid "Download the CD image from the torrent network."
+msgstr "CD-Image mit aus dem Torrentnetzwerk laden"
+
+#: webapp/backend/releases.py:133
+msgid "An image that is meant to run on embedded devices."
+msgstr "Ein Image, das für eingebettete Systeme optimiert ist."
+
+#: webapp/backend/releases.py:134
+msgid "Flash image where a serial console is enabled by default."
+msgstr "Image, bei welchem die serielle Konsole eingeschaltet ist."
+
+#: webapp/backend/releases.py:135
+msgid "Install IPFire from a floppy-formated USB key."
+msgstr "IPFire von einem Floppy-formatiertem USB-Stick installieren."
+
+#: webapp/backend/releases.py:136
+msgid "If the floppy image doesn't work, use this image instead."
+msgstr "Wenn das Floppy-Image nicht funktioniert, dieses verwenden."
+
+#: webapp/backend/releases.py:137
+msgid "A ready-to-run image for Xen."
+msgstr "Ein fertiges Image für Xen."
+
+#: webapp/__init__.py:311
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "January"
+msgstr "Januar"
+
+#: webapp/__init__.py:313
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "February"
+msgstr "Februar"
+
+#: webapp/__init__.py:315
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "March"
+msgstr "März"
+
+#: webapp/__init__.py:317
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "April"
+msgstr "April"
+
+#: webapp/__init__.py:319
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "May"
+msgstr "Mai"
+
+#: webapp/__init__.py:321
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "June"
+msgstr "Juni"
+
+#: webapp/__init__.py:323
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "July"
+msgstr "Juli"
+
+#: webapp/__init__.py:325
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "August"
+msgstr "August"
+
+#: webapp/__init__.py:327
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "September"
+msgstr "September"
+
+#: webapp/__init__.py:329
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "October"
+msgstr "Oktober"
+
+#: webapp/__init__.py:331
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "November"
+msgstr "November"
+
+#: webapp/__init__.py:333
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "December"
+msgstr "Dezember"
+
+#: webapp/ui_modules.py:114 webapp/handlers_news.py:43
+msgid "Unknown author"
+msgstr "Unbekannter Autor"
+
+#: webapp/ui_modules.py:265
+#, python-format
+msgid "%s to %s"
+msgstr "%s nach %s"
+
+#: templates/downloads.html:3 templates/downloads.html:8
+msgid "Get IPFire"
+msgstr "IPFire herunterladen"
+
+#: templates/downloads.html:10
+msgid "IPFire is completely free to download and use"
msgstr "IPFire darf kostenlos heruntergeladen und genutzt werden"
-#: templates/downloads.html:23
-msgid "More download options"
-msgstr "Weitere Downloadoptionen"
+#: templates/downloads.html:23
+msgid "More download options"
+msgstr "Weitere Downloadoptionen"
+
+#: templates/downloads.html:55
+msgid "Get yourself involved"
+msgstr "Selbst mitmachen"
+
+#: templates/news-year.html:3 templates/news.html:3
+msgid "News"
+msgstr "Neuigkeiten"
+
+#: templates/news-year.html:7
+#, python-format
+msgid "News from %(year)s"
+msgstr "Neuigkeiten aus %(year)s"
+
+#: templates/admin-index.html:5
+msgid "Admin Area"
+msgstr "Adminbereich"
+
+#: templates/fireinfo/stats.html:3 templates/modules/menu.html:136
+msgid "Statistics"
+msgstr "Statistiken"
+
+#: templates/fireinfo/stats.html:7
+msgid "fireinfo statistics"
+msgstr "Fireinfo Statistiken"
+
+#: templates/fireinfo/stats.html:17
+msgid "IPFire versions"
+msgstr "IPFire-Versionen"
+
+#: templates/fireinfo/stats.html:38 templates/fireinfo/stats-geo.html:3
+#: templates/fireinfo/stats-geo.html:7
+msgid "Geo locations"
+msgstr "Geographischer Standort"
+
+#: templates/fireinfo/stats.html:59 templates/fireinfo/stats-cpus.html:7
+msgid "Hardware: CPUs"
+msgstr "Hardware: CPUs"
+
+#: templates/fireinfo/stats.html:73
+msgid "CPU features"
+msgstr "CPU-Funktionen"
+
+#: templates/fireinfo/stats.html:85
+msgid "Hardware: Memory"
+msgstr "Hardware: Arbeitsspeicher"
+
+#: templates/fireinfo/stats.html:106 templates/fireinfo/stats-network.html:3
+#: templates/fireinfo/profile-detail.html:95
+msgid "Network"
+msgstr "Netzwerk"
+
+#: templates/fireinfo/stats.html:127 templates/fireinfo/stats-virtual.html:3
+#: templates/base-feature.html:65 templates/static/features.html:1179
+#: templates/static/features.html:1404
+msgid "Virtualization"
+msgstr "Virtualisierung"
+
+#: templates/fireinfo/stats-memory.html:3
+#: templates/fireinfo/stats-memory.html:7
+msgid "Memory"
+msgstr "Arbeitsspeicher"
+
+#: templates/fireinfo/stats-memory.html:13
+#, python-format
+msgid ""
+"The average amount of memory of all systems in the database is: <strong>%.2f "
+"MB</strong>."
+msgstr ""
+"Die durchschnittliche Menge an Arbeitsspeicher aller System ist: <strong>"
+"%.2f MB</strong>."
+
+#: templates/fireinfo/model-detail.html:11
+#, python-format
+msgid "This device is installed on approximately %.2f%% of all systems."
+msgstr "Dieses Gerät ist in etwa %.2f%% aller Systeme installiert."
+
+#: templates/fireinfo/model-detail.html:14
+msgid "Feedback"
+msgstr "Feedback"
+
+#: templates/fireinfo/model-detail.html:28
+msgid "Go to the wiki"
+msgstr "Zum Wiki"
+
+#: templates/fireinfo/stats-admin.html:3
+msgid "Admin"
+msgstr "Administrator"
+
+#: templates/fireinfo/stats-admin.html:11
+msgid "Sending profiles"
+msgstr "Senden Profile"
+
+#: templates/fireinfo/stats-admin.html:19
+msgid "Archive size"
+msgstr "Archivgröße"
+
+#: templates/fireinfo/profile-notfound.html:3
+#: templates/fireinfo/profile-notfound.html:8
+msgid "Profile not found"
+msgstr "Profil nicht gefunden"
+
+#: templates/fireinfo/stats-cpu-flags.html:3
+msgid "CPU flags"
+msgstr "CPU Flags"
+
+#: templates/fireinfo/stats-cpu-flags.html:7
+msgid "Processor flags"
+msgstr "Prozessor-Flags"
+
+#: templates/fireinfo/stats-cpu-flags.html:30
+msgid "CPUs that support 64 bits"
+msgstr "CPUs, die 64 Bit unterstützen"
+
+#: templates/fireinfo/stats-cpu-flags.html:46
+msgid "CPUs with PAE"
+msgstr "CPUs mit PAE"
+
+#: templates/fireinfo/stats-cpu-flags.html:62
+msgid "CPUs that support virtualization"
+msgstr "CPUs, die Virtualisierung unterstützen"
+
+#: templates/fireinfo/stats-virtual.html:7
+msgid "Virtualization support"
+msgstr "Virtualisierungsunterstützung"
+
+#: templates/fireinfo/stats-virtual.html:35
+msgid "Hypervisors"
+msgstr "Hypervisoren"
+
+#: templates/fireinfo/stats-oses.html:3
+#: templates/fireinfo/profile-detail.html:12
+msgid "Operating system"
+msgstr "Betriebssystem"
+
+#: templates/fireinfo/stats-oses.html:7
+msgid "Releases"
+msgstr "Releases"
+
+#: templates/fireinfo/stats-oses.html:18
+msgid "Architectures"
+msgstr "Architekturen"
+
+#: templates/fireinfo/stats-oses.html:25
+msgid "Kernels"
+msgstr "Kernel"
+
+#: templates/fireinfo/stats-cpus.html:3
+msgid "Processors"
+msgstr "Prozessoren"
+
+#: templates/fireinfo/stats-cpus.html:12
+msgid "See statistics about common CPU flags"
+msgstr "Statistiken über CPU-Funktionen"
+
+#: templates/fireinfo/stats-cpus.html:19
+msgid "Vendors"
+msgstr "Hersteller"
+
+#: templates/fireinfo/stats-cpus.html:36
+#: templates/fireinfo/profile-detail.html:154
+msgid "Speed"
+msgstr "Geschwindigkeit"
+
+#: templates/fireinfo/stats-cpus.html:38
+#, python-format
+msgid ""
+"The average speed of all systems in the database is: <strong>%.2f MHz</"
+"strong>."
+msgstr ""
+"Die durchschnittliche Geschwindigkeit aller System ist: <strong>%.2f MHz</"
+"strong>."
+
+#: templates/fireinfo/stats-cpus.html:40
+#, python-format
+msgid "All together, there are <strong>%s bogomips</strong> out there."
+msgstr "Zusammengenomen sind es <strong>%s Bogomips</strong>."
+
+#: templates/fireinfo/stats-cpus.html:48
+msgid "CPU core counter"
+msgstr "CPU-Kerne"
+
+#: templates/fireinfo/stats-cpus.html:50
+msgid ""
+"See a breakdown of the CPU cores that are installed on the IPFire systems."
+msgstr "Eine Übersicht über die CPU Kerne, der IPFire Systeme."
+
+#: templates/fireinfo/stats-network.html:7
+msgid "Network configuration"
+msgstr "Netzwerkkonfiguration"
+
+#: templates/fireinfo/index.html:52
+msgid "Show"
+msgstr "Anzeigen"
+
+#: templates/fireinfo/stats-geo.html:28
+msgid "Language selection"
+msgstr "Sprachauswahl"
+
+#: templates/fireinfo/profile-detail.html:3
+#: templates/fireinfo/profile-detail.html:7
+msgid "Profile"
+msgstr "Profil"
+
+#: templates/fireinfo/profile-detail.html:16
+msgid "Version"
+msgstr "Version"
+
+#: templates/fireinfo/profile-detail.html:24
+msgid "Architecture"
+msgstr "Architektur"
+
+#: templates/fireinfo/profile-detail.html:32
+msgid "Kernel version"
+msgstr "Kernelversion"
+
+#: templates/fireinfo/profile-detail.html:43
+msgid "Hypervisor"
+msgstr "Hypervisor"
+
+#: templates/fireinfo/profile-detail.html:45
+msgid "This machine is running in a virtual environment."
+msgstr "Diese Maschine läuft in einer virtuellen Umgebung."
+
+#: templates/fireinfo/profile-detail.html:51
+#: templates/fireinfo/profile-detail.html:71
+#: templates/fireinfo/profile-detail.html:130
+msgid "Vendor"
+msgstr "Hersteller"
+
+#: templates/fireinfo/profile-detail.html:59
+msgid "Type"
+msgstr "Typ"
+
+#: templates/fireinfo/profile-detail.html:67
+msgid "Hardware vendor"
+msgstr "Hardwarehersteller"
+
+#: templates/fireinfo/profile-detail.html:74
+#: templates/fireinfo/profile-detail.html:82 templates/mirrors-item.html:14
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: templates/fireinfo/profile-detail.html:79
+#: templates/fireinfo/profile-detail.html:138
+msgid "Model"
+msgstr "Modell"
+
+#: templates/fireinfo/profile-detail.html:97
+msgid "Enabled network zones"
+msgstr "Eingeschaltete Netzwerkzonen"
+
+#: templates/fireinfo/profile-detail.html:119 templates/base-feature.html:62
+#: templates/static/features.html:1104 templates/static/features.html:1399
+msgid "Hardware"
+msgstr "Hardware"
+
+#: templates/fireinfo/profile-detail.html:125
+msgid "CPU"
+msgstr "CPU"
+
+#: templates/fireinfo/profile-detail.html:141
+msgid "Not available"
+msgstr "Nicht verfügbar"
+
+#: templates/fireinfo/profile-detail.html:146
+msgid "Cores"
+msgstr "Kerne"
+
+#: templates/fireinfo/profile-detail.html:166
+msgid "Supported features"
+msgstr "Unterstützte Funktionen"
+
+#: templates/fireinfo/profile-detail.html:170
+msgid "64 bit capable"
+msgstr "64-Bit fähig"
+
+#: templates/fireinfo/profile-detail.html:174
+msgid "PAE capable"
+msgstr "PAE fähig"
+
+#: templates/fireinfo/profile-detail.html:178
+msgid "VT-x/AMD-V"
+msgstr "VT-x/AMD-V"
+
+#: templates/fireinfo/profile-detail.html:190
+msgid "Memory size"
+msgstr "Arbeitsspeichergröße"
+
+#: templates/fireinfo/profile-detail.html:198
+msgid "System disk size"
+msgstr "Systemplattengröße"
+
+#: templates/fireinfo/profile-detail.html:211
+msgid "Peripherial devices"
+msgstr "Peripheriegeräte"
+
+#: templates/fireinfo/profile-detail.html:216
+msgid "Signature images"
+msgstr "Signaturbilder"
+
+#: templates/fireinfo/profile-detail.html:231 templates/admin-mirrors.html:15
+#: templates/download-mirror-detail.html:20
+#: templates/downloads-mirrors.html:50
+msgid "Last update"
+msgstr "Letztes Update"
+
+#: templates/fireinfo/base.html:6 templates/modules/menu.html:98
+msgid "Fireinfo"
+msgstr "Fireinfo"
+
+#: templates/fireinfo/base.html:7
+msgid "A hardware data collection tool for IPFire"
+msgstr "Ein Hardwaredatensammeltool für IPFire"
+
+#: templates/sources.html:3
+msgid "Sources"
+msgstr "Quellen"
+
+#: templates/sources.html:6 templates/static/development.html:263
+msgid "Source Code"
+msgstr "Quellcode"
+
+#: templates/sources.html:9
+#, python-format
+msgid "There are %s source files on the server."
+msgstr "Es befinden sich %s Quelldateien auf dem Server."
-#: templates/downloads.html:55
-msgid "Get yourself involved"
-msgstr "Selbst mitmachen"
+#: templates/downloads-all.html:3
+msgid "Ancient Downloads"
+msgstr "Veraltete Downloads"
+
+#: templates/downloads-all.html:7 templates/index.html:18
+msgid "Download IPFire"
+msgstr "IPFire herunterladen"
+
+#: templates/downloads-all.html:9 templates/downloads-older.html:9
+msgid ""
+"These are the ancient downloads of IPFire. They are just saved for "
+"historical reasons and should not be used in a productive environment."
+msgstr ""
+"Dieses sind veraltete Downloads von IPFire. Sie wurden hier archiviert und "
+"sollten nicht in produktiven Umgebungen eingesetzt werden."
+
+#: templates/downloads-all.html:13 templates/downloads-older.html:17
+msgid "Go back to latest stable downloads."
+msgstr "Zurück zu den neuesten stabilen Downloads."
+
+#: templates/admin-accounts-edit.html:5 templates/admin-accounts.html:5
+msgid "Account Administrator"
+msgstr "Accountadministrator"
+
+#: templates/news-author.html:7
+#, python-format
+msgid "%s's announcements"
+msgstr "%ss Ankündigungen"
+
+#: templates/admin-mirrors.html:5
+msgid "Mirror Administrator"
+msgstr "Mirroradministrator"
-#: templates/admin-mirrors-create.html:5 templates/admin-mirrors.html:8
+#: templates/admin-mirrors.html:8 templates/admin-mirrors-create.html:5
msgid "Create new mirror"
msgstr "Neuen Mirror erstellen"
-#: templates/admin-mirrors-create.html:16
-msgid "Path"
-msgstr "Pfad"
-
-#: templates/admin-mirrors-create.html:28
-#: templates/admin-mirrors-details.html:33
-msgid "File mirror"
-msgstr "Dateimirror"
+#: templates/admin-mirrors.html:9
+msgid "Re-check now"
+msgstr "Jetzt neu prüfen"
-#: templates/admin-mirrors-create.html:31
-#: templates/admin-mirrors-create.html:40
-#: templates/admin-mirrors-create.html:49
-#: templates/admin-mirrors-create.html:58
-msgid "yes"
-msgstr "Ja"
+#: templates/admin-mirrors.html:14 templates/download-mirror-detail.html:12
+#: templates/admin-mirrors-create.html:12 templates/downloads-mirrors.html:48
+#: templates/admin-mirrors-details.html:13
+msgid "Hostname"
+msgstr "Hostname"
-#: templates/admin-mirrors-create.html:32
-#: templates/admin-mirrors-create.html:41
-#: templates/admin-mirrors-create.html:50
-#: templates/admin-mirrors-create.html:59
-msgid "no"
-msgstr "Nein"
+#: templates/admin-mirrors.html:23 templates/admin-mirrors-details.html:5
+msgid "Details"
+msgstr "Details"
-#: templates/admin-mirrors-create.html:37
-#: templates/admin-mirrors-details.html:37
-msgid "Pakfire 2 mirror"
-msgstr "Pakfire 2 Mirror"
+#: templates/admin-mirrors.html:24 templates/admin-planet.html:29
+#: templates/admin-accounts.html:20
+msgid "Edit"
+msgstr "Bearbeiten"
-#: templates/admin-mirrors-create.html:46
-#: templates/admin-mirrors-details.html:41
-msgid "Pakfire 3 mirror"
-msgstr "Pakfire 3 Mirror"
+#: templates/admin-mirrors.html:25 templates/admin-accounts.html:21
+msgid "Delete"
+msgstr "Löschen"
-#: templates/admin-mirrors-create.html:55
-#: templates/admin-mirrors-details.html:45
-msgid "Disabled?"
-msgstr "Ausgeschaltet?"
+#: templates/error-500.html:6
+msgid "Detailed information"
+msgstr "Mehr Informationen"
-#: templates/admin-downloads.html:7
-msgid "Download counters"
-msgstr "Downloadzähler"
+#: templates/download-mirror-detail.html:3 templates/downloads-mirrors.html:3
+msgid "Mirror-Server"
+msgstr "Mirrorserver"
-#: templates/admin-downloads.html:10
-msgid "Today"
-msgstr "Heute"
+#: templates/download-mirror-detail.html:8 templates/downloads-mirrors.html:8
+msgid "IPFire Mirrors"
+msgstr "IPFire Mirrors"
-#: templates/admin-downloads.html:14
-msgid "Yesterday"
-msgstr "Gestern"
+#: templates/download-mirror-detail.html:16 templates/mirrors-item.html:23
+#: templates/admin-mirrors-create.html:20 templates/downloads-mirrors.html:47
+#: templates/admin-mirrors-details.html:21
+msgid "Owner"
+msgstr "Eigentümer"
-#: templates/admin-downloads.html:18
-msgid "Total"
-msgstr "Insgesamt"
+#: templates/download-mirror-detail.html:24
+msgid "Number of files"
+msgstr "Anzahl von Dateien"
-#: templates/admin-downloads.html:23
-msgid "Downloads by country"
-msgstr "Downloads pro Land"
+#: templates/download-mirror-detail.html:32
+msgid "View list of all mirror servers."
+msgstr "Liste aller Mirrorserver."
#: templates/news.html:7
msgid "What is new on the IPFire project?"
msgid "Stay up to date"
msgstr "Informiere dich"
-#: templates/news.html:61 templates/planet/year.html:3
-#: templates/planet/user.html:3 templates/planet/search.html:3
-#: templates/planet/base.html:6 templates/planet/index.html:3
-#: templates/planet/posting.html:3 templates/index.html:154
+#: templates/news.html:61 templates/planet/search.html:3
+#: templates/planet/year.html:3 templates/planet/user.html:3
+#: templates/planet/posting.html:3 templates/planet/index.html:3
+#: templates/planet/base.html:6 templates/index.html:154
msgid "IPFire Planet"
msgstr "IPFire Planet"
msgid "Latest news"
msgstr "Aktuelle Neuigkeiten"
-#: templates/base-feature.html:6 templates/modules/menu.html:7
-#: templates/static/features.html:3 templates/static/features.html:8
-#: templates/static/features.html:1349
+#: templates/admin-planet-compose.html:5 templates/admin-planet.html:8
+msgid "Compose new entry"
+msgstr "Neuen Beitrag erstellen"
+
+#: templates/admin-planet-compose.html:16 templates/admin-planet.html:14
+msgid "Title"
+msgstr "Titel"
+
+#: templates/admin-planet-compose.html:33 templates/planet/posting.html:26
+msgid "Tags"
+msgstr "Tags"
+
+#: templates/admin-planet-compose.html:44
+#: templates/admin-mirrors-details.html:17
+msgid "Status"
+msgstr "Status"
+
+#: templates/admin-planet-compose.html:48 templates/admin-planet.html:25
+msgid "Draft"
+msgstr ""
+
+#: templates/admin-planet-compose.html:52
+#, fuzzy
+msgid "Published"
+msgstr "Veröffentlicht am"
+
+#: templates/admin-planet-compose.html:58
+msgid "Save"
+msgstr "Speichern"
+
+#: templates/admin-planet-compose.html:59
+msgid "Preview"
+msgstr "Vorschau"
+
+#: templates/admin-planet-compose.html:60
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: templates/mirrors-item.html:3
+#, python-format
+msgid "Mirror %s"
+msgstr "Mirror %s"
+
+#: templates/mirrors-item.html:8
+msgid "Up"
+msgstr "Verfügbar"
+
+#: templates/mirrors-item.html:10
+msgid "Down"
+msgstr "Nicht verfügbar"
+
+#: templates/mirrors-item.html:12
+msgid "Out of sync"
+msgstr "Nicht synchronisiert"
+
+#: templates/mirrors-item.html:30 templates/admin-mirrors-create.html:24
+#: templates/downloads-mirrors.html:49 templates/admin-mirrors-details.html:25
+msgid "Location"
+msgstr "Standort"
+
+#: templates/mirrors-item.html:36 templates/geoip/index.html:19
+msgid "Country"
+msgstr ""
+
+#: templates/mirrors-item.html:41 templates/geoip/index.html:29
+msgid "City"
+msgstr ""
+
+#: templates/mirrors-item.html:47
+msgid "Preferred for"
+msgstr "Bevorzugt für"
+
+#: templates/mirrors-item.html:54
+msgid "Estimated distance to you"
+msgstr ""
+
+#: templates/mirrors-item.html:61 templates/geoip/index.html:15
+msgid "Autonomous System"
+msgstr ""
+
+#: templates/mirrors-item.html:65
+msgid "IP Addresses"
+msgstr ""
+
+#: templates/mirrors-item.html:75
+#, fuzzy
+msgid "Last updated"
+msgstr "Letztes Update"
+
+#: templates/mirrors-item.html:86
+msgid "Go to mirror"
+msgstr "Zum Mirror"
+
+#: templates/mirrors-item.html:94
+msgid "The location of the mirror server is estimated by the IP address."
+msgstr ""
+"Der Standort dieses Mirrorservers wurde anhand der IP-Adresse geschätzt."
+
+#: templates/mirrors-item.html:98
+#, fuzzy
+msgid "The location of this mirror server could not be estimated."
+msgstr "Der Standort dieses Mirrorservers konnte nicht ermittelt werden."
+
+#: templates/tracker-torrents.html:3
+msgid "Torrent Downloads"
+msgstr "Torrent-Downloads"
+
+#: templates/tracker-torrents.html:7
+msgid "IPFire Torrent Tracker"
+msgstr "IPFire Torrent-Tracker"
+
+#: templates/tracker-torrents.html:32 templates/downloads-older.html:25
+#: templates/downloads-index.html:35
+msgid "Release"
+msgstr "Release"
+
+#: templates/tracker-torrents.html:33
+msgid "Seeders"
+msgstr "Seeders"
+
+#: templates/tracker-torrents.html:34 templates/tracker-torrent-detail.html:23
+msgid "Peers"
+msgstr "Peers"
+
+#: templates/downloads-older.html:3 templates/downloads-older.html:7
+msgid "Ancient downloads"
+msgstr "Veraltete Downloads"
+
+#: templates/downloads-older.html:13
+msgid ""
+"Beware that these releases could lack possible security-fixes\tand so it is "
+"recommended to use the <em>latest</em> version."
+msgstr ""
+"Achtung! Diese Releases könnten potentielle Sicherheitsprobleme aufweisen. "
+"Daher wird empfohlen die <em>neueste</em> Version einzusetzen."
+
+#: templates/downloads-older.html:26
+msgid "Published on"
+msgstr "Veröffentlicht am"
+
+#: templates/admin-downloads-mirrors.html:5 templates/admin-downloads.html:5
+msgid "Download statistics"
+msgstr "Downloadstatistiken"
+
+#: templates/admin-downloads-mirrors.html:7
+msgid "Mirror load from today"
+msgstr "Mirrorauslastung von heute"
+
+#: templates/admin-downloads-mirrors.html:10
+msgid "Mirror load"
+msgstr "Mirrorauslastung"
+
+#: templates/admin-base.html:3
+msgid "IPFire Admin Area"
+msgstr "IPFire Adminbereich"
+
+#: templates/admin-base.html:6 templates/admin-downloads-base.html:8
+msgid "Options"
+msgstr "Optionen"
+
+#: templates/admin-base.html:9
+msgid "Accounts"
+msgstr "Accounts"
+
+#: templates/admin-base.html:10 templates/modules/menu.html:110
+msgid "Mirrors"
+msgstr "Mirrors"
+
+#: templates/admin-base.html:11 templates/modules/menu.html:92
+msgid "Planet"
+msgstr "Planet"
+
+#: templates/admin-base.html:12
+msgid "Downloads"
+msgstr "Downloads"
+
+#: templates/base-feature.html:6 templates/static/features.html:3
+#: templates/static/features.html:8 templates/static/features.html:1349
+#: templates/modules/menu.html:7
msgid "About IPFire"
msgstr "Ãœber IPFire"
msgid "Wireless AP"
msgstr "WLAN-Access-Point"
-#: templates/download-mirror-detail.html:24
-msgid "Number of files"
-msgstr "Anzahl von Dateien"
+#: templates/downloads-development.html:3
+#: templates/downloads-development.html:6
+msgid "Development Downloads"
+msgstr "Development Downloads"
-#: templates/download-mirror-detail.html:32
-msgid "View list of all mirror servers."
-msgstr "Liste aller Mirrorserver."
+#: templates/admin-mirrors-create.html:16
+msgid "Path"
+msgstr "Pfad"
+
+#: templates/admin-mirrors-create.html:28
+#: templates/admin-mirrors-details.html:33
+msgid "File mirror"
+msgstr "Dateimirror"
+
+#: templates/admin-mirrors-create.html:31
+#: templates/admin-mirrors-create.html:40
+#: templates/admin-mirrors-create.html:49
+#: templates/admin-mirrors-create.html:58
+msgid "yes"
+msgstr "Ja"
+
+#: templates/admin-mirrors-create.html:32
+#: templates/admin-mirrors-create.html:41
+#: templates/admin-mirrors-create.html:50
+#: templates/admin-mirrors-create.html:59
+msgid "no"
+msgstr "Nein"
+
+#: templates/admin-mirrors-create.html:37
+#: templates/admin-mirrors-details.html:37
+msgid "Pakfire 2 mirror"
+msgstr "Pakfire 2 Mirror"
+
+#: templates/admin-mirrors-create.html:46
+#: templates/admin-mirrors-details.html:41
+msgid "Pakfire 3 mirror"
+msgstr "Pakfire 3 Mirror"
+
+#: templates/admin-mirrors-create.html:55
+#: templates/admin-mirrors-details.html:45
+msgid "Disabled?"
+msgstr "Ausgeschaltet?"
+
+#: templates/geoip/index.html:3 templates/geoip/index.html:7
+#, python-format
+msgid "GeoIP for %s"
+msgstr ""
+
+#: templates/geoip/index.html:33
+msgid "Postal Code"
+msgstr ""
+
+#: templates/geoip/index.html:46
+#, python-format
+msgid "No GeoIP information could be found for the IP address '%s'."
+msgstr ""
+
+#: templates/downloads-index.html:3
+msgid "Download Center"
+msgstr "Downloadcenter"
+
+#: templates/downloads-index.html:7
+msgid "IPFire Download Center"
+msgstr "IPFire Download-Center"
+
+#: templates/downloads-index.html:30
+msgid "Available releases"
+msgstr "Verfügbare Releases"
+
+#: templates/downloads-index.html:36
+msgid "Release type"
+msgstr "Release-Typ"
+
+#: templates/downloads-index.html:37
+msgid "Release date"
+msgstr "Veröffentlichungsdatum"
+
+#: templates/downloads-index.html:48
+msgid "Stable"
+msgstr "Stabil"
+
+#: templates/downloads-index.html:50 templates/static/getinvolved.html:153
+#: templates/static/development.html:3 templates/static/development.html:8
+#: templates/modules/menu.html:65
+msgid "Development"
+msgstr "Entwicklung"
+
+#: templates/downloads-mirrors.html:63
+msgid "details"
+msgstr "Details"
+
+#: templates/admin-planet.html:5
+msgid "Planet Administrator"
+msgstr "Planet Administrator"
+
+#: templates/admin-planet.html:13
+msgid "Author"
+msgstr "Autor"
+
+#: templates/admin-planet.html:31
+#, fuzzy
+msgid "Publish"
+msgstr "Veröffentlicht am"
+
+#: templates/error.html:3
+msgid "Error"
+msgstr "Error"
+
+#: templates/admin-downloads-base.html:5
+msgid "Back to home"
+msgstr "Zurück zur Startseite"
+
+#: templates/admin-downloads-base.html:11
+msgid "Mirror stats"
+msgstr "Mirrorstatistiken"
+
+#: templates/static/getinvolved.html:3 templates/static/getinvolved.html:8
+msgid "Get involved"
+msgstr "Mitmachen"
+
+#: templates/static/getinvolved.html:10
+msgid "Because making a difference is easy"
+msgstr "Weil es so leicht ist etwas Gutes zu tun"
+
+#: templates/static/getinvolved.html:47
+msgid "First steps"
+msgstr "Erste Schritte"
+
+#: templates/static/getinvolved.html:97
+msgid "Donations"
+msgstr "Spenden"
+
+#: templates/static/getinvolved.html:120 templates/static/donation.html:3
+#: templates/static/donation.html:8 templates/modules/menu.html:47
+#: templates/wishlist/donate.html:3 templates/wishlist/modules/wish.html:26
+#: templates/download-splash.html:37
+msgid "Donate"
+msgstr "Spenden"
+
+#: templates/static/getinvolved.html:126 templates/modules/menu.html:53
+msgid "Wishlist"
+msgstr "Wunschliste"
+
+#: templates/static/getinvolved.html:142
+msgid "Make a wish"
+msgstr "Wünsch dir was"
+
+#: templates/static/getinvolved.html:149
+msgid "Contribute yourself"
+msgstr "Bring dich selbst ein"
+
+#: templates/static/getinvolved.html:175
+msgid "Translation"
+msgstr "Ãœbersetzung"
+
+#: templates/static/getinvolved.html:190
+msgid "Translation team"
+msgstr "Ãœbersetzungsteam"
+
+#: templates/static/getinvolved.html:196
+msgid "Promotion"
+msgstr "Promotion"
+
+#: templates/static/features.html:10
+msgid "Because IPFire is more than just a firewall"
+msgstr "Weil IPFire mehr als nur eine Firewall ist"
+
+#: templates/static/features.html:22
+msgid "IPFire"
+msgstr "IPFire"
+
+#: templates/static/features.html:22
+msgid "An Open Source Firewall Distribution"
+msgstr "An Open Source Firewall Solution"
+
+#: templates/static/features.html:315
+msgid "The IPFire package management system"
+msgstr "Das IPFire Paketmanagementsystem"
+
+#: templates/static/features.html:791
+msgid "Transparent virus scanner"
+msgstr "Transparenter Virenscanner"
+
+#: templates/static/features.html:818
+msgid "Virtual Private Networks"
+msgstr "Virtuelle private Netzwerke"
+
+#: templates/static/features.html:974
+msgid "Intrusion detection system"
+msgstr "Einbruchsdetektierung"
+
+#: templates/static/features.html:1311 templates/static/features.html:1409
+msgid "Wireless Access Point"
+msgstr "WLAN-Access-Point"
+
+#: templates/static/features.html:1379
+msgid "Web Proxy"
+msgstr "Webproxy"
+
+#: templates/static/features.html:1389
+msgid "Intrusion Detection"
+msgstr "Einbruchsdetektierung"
+
+#: templates/static/artwork.html:3 templates/static/artwork.html:8
+#: templates/modules/menu.html:116
+msgid "Artwork"
+msgstr "Artwork"
+
+#: templates/static/artwork.html:36
+msgid "The IPFire Logo"
+msgstr "Das IPFire-Logo"
+
+#: templates/static/artwork.html:50
+msgid "Flyers, Rollups, CDs and more"
+msgstr "Flyer, Rollups, CDs und mehr"
+
+#: templates/static/development.html:37 templates/static/development.html:258
+msgid "Development tools"
+msgstr "Entwicklungstools"
+
+#: templates/static/development.html:55 templates/modules/menu.html:82
+msgid "Bugtracker"
+msgstr "Bugtracker"
+
+#: templates/static/development.html:77
+msgid "Development Mailing List"
+msgstr "Entwicklungsmailingliste"
+
+#: templates/static/development.html:96
+msgid "Source code"
+msgstr "Quellcode"
+
+#: templates/static/development.html:99
+msgid "Git"
+msgstr "Git"
+
+#: templates/static/development.html:118
+msgid "IPFire Git repositories"
+msgstr "IPFire Git-Repositorien"
+
+#: templates/static/development.html:124
+msgid "GitHub"
+msgstr "GitHub"
+
+#: templates/static/development.html:143
+msgid "ipfire on GitHub"
+msgstr "ipfire auf GitHub"
+
+#: templates/static/development.html:150 templates/static/development.html:268
+msgid "How to build IPFire?"
+msgstr "Wie kompiliert man IPFire?"
+
+#: templates/static/development.html:186
+msgid "How to submit patches?"
+msgstr "Wie sendet man Patches?"
+
+#: templates/static/development.html:214
+msgid "How to translate IPFire?"
+msgstr "Wie übersetzt man IPFire?"
+
+#: templates/static/press.html:3 templates/static/press.html:7
+#: templates/base.html:69
+msgid "Press"
+msgstr "Presse"
+
+#: templates/static/press.html:31 templates/static/imprint.html:29
+#: templates/static/imprint.html:41 templates/static/imprint.html:53
+#: templates/static/imprint.html:65 templates/planet/user.html:48
+msgid "Mail"
+msgstr "Mail"
+
+#: templates/static/press.html:35
+msgid "Logo"
+msgstr "Logo"
-#: templates/downloads-all.html:3
-msgid "Ancient Downloads"
-msgstr "Veraltete Downloads"
+#: templates/static/imprint.html:3 templates/static/imprint.html:8
+#: templates/base.html:73
+msgid "Imprint"
+msgstr "Impressum"
-#: templates/downloads-all.html:7 templates/index.html:18
-msgid "Download IPFire"
-msgstr "IPFire herunterladen"
+#: templates/static/chat.html:3 templates/static/chat.html:8
+#: templates/modules/menu.html:39
+msgid "Chat"
+msgstr "Chat"
-#: templates/admin-accounts-edit.html:5 templates/admin-accounts.html:5
-msgid "Account Administrator"
-msgstr "Accountadministrator"
+#: templates/static/chat.html:33
+msgid "Server"
+msgstr "Server"
-#: templates/planet/year.html:6
-#, python-format
-msgid "Year %s"
-msgstr "Jahr %s"
+#: templates/static/chat.html:36
+msgid "Channel"
+msgstr "Channel"
-#: templates/planet/user.html:22 templates/planet/index.html:45
-msgid "Older posts"
-msgstr "Ältere Beiträge"
+#: templates/static/chat.html:41
+msgid "Use the web client"
+msgstr "Web-Client benutzen"
-#: templates/planet/user.html:26 templates/planet/index.html:49
-msgid "Newer posts"
-msgstr "Neuere Beiträge"
+#: templates/static/donation.html:10
+msgid "We need your help!"
+msgstr "Wir brauchen Deine Hilfe!"
-#: templates/planet/user.html:33
-#, python-format
-msgid "%s did not write any posts, yet."
-msgstr "%s hat bisher noch keine Beiträge verfasst."
+#: templates/static/donation.html:68
+msgid "Did you know...?"
+msgstr "Schon gewusst?"
-#: templates/planet/user.html:48 templates/static/press.html:31
-#: templates/static/imprint.html:29 templates/static/imprint.html:41
-#: templates/static/imprint.html:53 templates/static/imprint.html:65
-msgid "Mail"
-msgstr "Mail"
+#: templates/static/donation.html:84
+msgid "How do we use financial support?"
+msgstr "Wofür werden Spenden eingesetzt?"
-#: templates/planet/search.html:6
-#, python-format
-msgid "Search results for '%s'"
-msgstr "Suchergebnisse für '%s'"
+#: templates/static/donation.html:132
+msgid "Research & Development"
+msgstr "Forschung & Entwicklung"
-#: templates/planet/search.html:16
-#, python-format
-msgid "No results found for '%s'"
-msgstr "Keine Resultate gefunden für '%s'"
+#: templates/static/cebit.html:3
+msgid "CeBIT special"
+msgstr "CeBIT-Spezial"
-#: templates/planet/base.html:9
-msgid "The official blog of the IPFire team"
-msgstr "Das offizielle Blog des IPFire-Team"
+#: templates/static/cebit.html:8
+msgid "IPFire at CeBIT 2010"
+msgstr "IPFire auf der CeBIT 2010"
-#: templates/planet/index.html:24
-msgid "All posts from"
-msgstr "Alle Posts aus"
+#: templates/admin-accounts.html:8
+msgid "Create new account"
+msgstr "Neuen Account erstellen"
-#: templates/planet/posting.html:24 templates/modules/planet-entry.html:14
-msgid "Posted by"
-msgstr "Erstellt von"
+#: templates/admin-accounts.html:13
+msgid "Name (Nickname)"
+msgstr "Name (Nickname)"
-#: templates/planet/posting.html:25 templates/modules/planet-entry.html:15
-msgid "on"
-msgstr "am"
+#: templates/modules/sidebar-release.html:4
+#: templates/modules/release-item.html:2 templates/index.html:24
+msgid "Latest release"
+msgstr "Neuestes Release"
-#: templates/base.html:4
-msgid "No title given"
-msgstr "Kein Titel"
+#: templates/modules/sidebar-release.html:9
+msgid "Download now"
+msgstr "Jetzt herunterladen"
-#: templates/base.html:63
-msgid "IPFire is free software"
-msgstr "IPFire ist freie Software"
+#: templates/modules/release-item-short.html:4
+msgid "Here you will find the downloads for the version"
+msgstr "Hier gibt es alle Downloads für diese Version"
-#: templates/base.html:69 templates/static/press.html:3
-#: templates/static/press.html:7
-msgid "Press"
-msgstr "Presse"
+#: templates/modules/release-item-short.html:13
+#: templates/modules/release-item.html:123
+msgid "There are no downloads available for this release."
+msgstr "Es gibt keine Downloads für dieses Release."
-#: templates/base.html:73 templates/static/imprint.html:3
-#: templates/static/imprint.html:8
-msgid "Imprint"
-msgstr "Impressum"
+#: templates/modules/download-button.html:2
+#, python-format
+msgid "Download %s"
+msgstr "%s herunterladen"
-#: templates/admin-mirrors.html:5
-msgid "Mirror Administrator"
-msgstr "Mirroradministrator"
+#: templates/modules/map.html:5
+msgid "View larger map"
+msgstr "Größere Karte ansehen"
-#: templates/admin-mirrors.html:9
-msgid "Re-check now"
-msgstr "Jetzt neu prüfen"
+#: templates/modules/ads/download-splash.html:4
+msgid "Advertisement"
+msgstr "Werbung"
-#: templates/admin-mirrors.html:23 templates/admin-mirrors-details.html:5
-msgid "Details"
-msgstr "Details"
+#: templates/modules/ads/download-splash.html:5
+msgid "This download is sponsored by:"
+msgstr "Dieser Download wurde gesponsort von:"
-#: templates/admin-mirrors.html:25 templates/admin-accounts.html:21
-msgid "Delete"
-msgstr "Löschen"
+#: templates/modules/news-preview.html:6
+msgid "by"
+msgstr "von"
-#: templates/tracker-torrents.html:3
-msgid "Torrent Downloads"
-msgstr "Torrent-Downloads"
+#: templates/modules/mirrors-table.html:37
+#, fuzzy, python-format
+msgid "Last update: %s"
+msgstr "Letztes Update"
-#: templates/tracker-torrents.html:7
-msgid "IPFire Torrent Tracker"
-msgstr "IPFire Torrent-Tracker"
+#: templates/modules/news-year-nav.html:3
+msgid "Jump to"
+msgstr "Springe zu"
-#: templates/tracker-torrents.html:33
-msgid "Seeders"
-msgstr "Seeders"
+#: templates/modules/news-year-nav.html:6
+msgid "Most recent"
+msgstr "Aktuellste"
-#: templates/error.html:3
-msgid "Error"
-msgstr "Error"
+#: templates/modules/stasy-table-devices.html:6
+msgid "Kernel module"
+msgstr "Kernelmodul"
#: templates/modules/donation-box.html:4
msgid "Donate with PayPal or Credit Card"
msgid "Bank code"
msgstr "BLZ"
-#: templates/modules/release-item.html:2
-#: templates/modules/sidebar-release.html:4 templates/index.html:24
-msgid "Latest release"
-msgstr "Neuestes Release"
+#: templates/modules/planet-entry.html:14 templates/planet/posting.html:31
+msgid "Posted by"
+msgstr "Erstellt von"
+
+#: templates/modules/planet-entry.html:15 templates/planet/posting.html:32
+msgid "on"
+msgstr "am"
+
+#: templates/modules/news-item.html:6
+msgid "Announcement"
+msgstr "Ankündigung"
#: templates/modules/release-item.html:10
msgid "Choose an architecture:"
msgid "Legend:"
msgstr "Legende:"
-#: templates/modules/release-item.html:123
-#: templates/modules/release-item-short.html:13
-msgid "There are no downloads available for this release."
-msgstr "Es gibt keine Downloads für dieses Release."
-
-#: templates/modules/sidebar-release.html:9
-msgid "Download now"
-msgstr "Jetzt herunterladen"
-
-#: templates/modules/release-item-short.html:4
-msgid "Here you will find the downloads for the version"
-msgstr "Hier gibt es alle Downloads für diese Version"
-
-#: templates/modules/news-preview.html:6
-msgid "by"
-msgstr "von"
-
-#: templates/modules/download-button.html:2
-#, python-format
-msgid "Download %s"
-msgstr "%s herunterladen"
-
-#: templates/modules/stasy-table-devices.html:6
-msgid "Kernel module"
-msgstr "Kernelmodul"
-
-#: templates/modules/news-year-nav.html:3
-msgid "Jump to"
-msgstr "Springe zu"
-
-#: templates/modules/news-year-nav.html:6
-msgid "Most recent"
-msgstr "Aktuellste"
-
-#: templates/modules/ads/download-splash.html:4
-msgid "Advertisement"
-msgstr "Werbung"
+#: templates/modules/release-item.html:114
+#: templates/tracker-torrent-detail.html:15
+msgid "Magnet link"
+msgstr "Magnet-Link"
-#: templates/modules/ads/download-splash.html:5
-msgid "This download is sponsored by:"
-msgstr "Dieser Download wurde gesponsort von:"
+#: templates/modules/release-item.html:115
+#: templates/tracker-torrent-detail.html:3
+#: templates/tracker-torrent-detail.html:18
+msgid "Torrent download"
+msgstr "Torrent-Download"
#: templates/modules/menu.html:4
msgid "Download"
msgid "Forum"
msgstr "Forum"
-#: templates/modules/menu.html:39 templates/static/chat.html:3
-#: templates/static/chat.html:8
-msgid "Chat"
-msgstr "Chat"
-
-#: templates/modules/menu.html:53 templates/static/getinvolved.html:126
-msgid "Wishlist"
-msgstr "Wunschliste"
-
#: templates/modules/menu.html:61
msgid "More"
msgstr "Mehr"
msgid "Pakfire Build Service"
msgstr "Pakfire Buildsystem"
-#: templates/modules/menu.html:82 templates/static/development.html:55
-msgid "Bugtracker"
-msgstr "Bugtracker"
-
#: templates/modules/menu.html:87
msgid "Miscellaneous"
msgstr "Verschiedenes"
msgid "Mailing lists"
msgstr "Mailinglisten"
-#: templates/modules/menu.html:116 templates/static/artwork.html:3
-#: templates/static/artwork.html:8
-msgid "Artwork"
-msgstr "Artwork"
-
#: templates/modules/menu.html:122
msgid "CeBIT"
msgstr "CeBIT"
msgid "Professional support available!"
msgstr "Professioneller Support verfügbar!"
-#: templates/modules/news-item.html:6
-msgid "Announcement"
-msgstr "Ankündigung"
-
-#: templates/static/press.html:35
-msgid "Logo"
-msgstr "Logo"
-
-#: templates/static/features.html:10
-msgid "Because IPFire is more than just a firewall"
-msgstr "Weil IPFire mehr als nur eine Firewall ist"
-
-#: templates/static/features.html:22
-msgid "IPFire"
-msgstr "IPFire"
+#: templates/admin-login.html:3
+msgid "Please login"
+msgstr "Bitte einloggen"
-#: templates/static/features.html:22
-msgid "An Open Source Firewall Distribution"
-msgstr "An Open Source Firewall Solution"
+#: templates/planet/search.html:6
+#, python-format
+msgid "Search results for '%s'"
+msgstr "Suchergebnisse für '%s'"
-#: templates/static/features.html:315
-msgid "The IPFire package management system"
-msgstr "Das IPFire Paketmanagementsystem"
+#: templates/planet/search.html:16
+#, python-format
+msgid "No results found for '%s'"
+msgstr "Keine Resultate gefunden für '%s'"
-#: templates/static/features.html:791
-msgid "Transparent virus scanner"
-msgstr "Transparenter Virenscanner"
+#: templates/planet/year.html:6
+#, python-format
+msgid "Year %s"
+msgstr "Jahr %s"
-#: templates/static/features.html:818
-msgid "Virtual Private Networks"
-msgstr "Virtuelle private Netzwerke"
+#: templates/planet/user.html:22 templates/planet/index.html:45
+msgid "Older posts"
+msgstr "Ältere Beiträge"
-#: templates/static/features.html:974
-msgid "Intrusion detection system"
-msgstr "Einbruchsdetektierung"
+#: templates/planet/user.html:26 templates/planet/index.html:49
+msgid "Newer posts"
+msgstr "Neuere Beiträge"
-#: templates/static/features.html:1311 templates/static/features.html:1409
-msgid "Wireless Access Point"
-msgstr "WLAN-Access-Point"
+#: templates/planet/user.html:33
+#, python-format
+msgid "%s did not write any posts, yet."
+msgstr "%s hat bisher noch keine Beiträge verfasst."
-#: templates/static/features.html:1379
-msgid "Web Proxy"
-msgstr "Webproxy"
+#: templates/planet/posting.html:17
+msgid "Heads up!"
+msgstr ""
-#: templates/static/features.html:1389
-msgid "Intrusion Detection"
-msgstr "Einbruchsdetektierung"
+#: templates/planet/posting.html:17
+msgid "This post is a draft and has not been published, yet."
+msgstr ""
-#: templates/static/development.html:37 templates/static/development.html:258
-msgid "Development tools"
-msgstr "Entwicklungstools"
+#: templates/planet/index.html:24
+msgid "All posts from"
+msgstr "Alle Posts aus"
-#: templates/static/development.html:77
-msgid "Development Mailing List"
-msgstr "Entwicklungsmailingliste"
+#: templates/planet/base.html:9
+msgid "The official blog of the IPFire team"
+msgstr "Das offizielle Blog des IPFire-Team"
-#: templates/static/development.html:96
-msgid "Source code"
-msgstr "Quellcode"
+#: templates/admin-downloads.html:7
+msgid "Download counters"
+msgstr "Downloadzähler"
-#: templates/static/development.html:99
-msgid "Git"
-msgstr "Git"
+#: templates/admin-downloads.html:10
+msgid "Today"
+msgstr "Heute"
-#: templates/static/development.html:118
-msgid "IPFire Git repositories"
-msgstr "IPFire Git-Repositorien"
+#: templates/admin-downloads.html:14
+msgid "Yesterday"
+msgstr "Gestern"
-#: templates/static/development.html:124
-msgid "GitHub"
-msgstr "GitHub"
+#: templates/admin-downloads.html:18
+msgid "Total"
+msgstr "Insgesamt"
-#: templates/static/development.html:143
-msgid "ipfire on GitHub"
-msgstr "ipfire auf GitHub"
+#: templates/admin-downloads.html:23
+msgid "Downloads by country"
+msgstr "Downloads pro Land"
-#: templates/static/development.html:150 templates/static/development.html:268
-msgid "How to build IPFire?"
-msgstr "Wie kompiliert man IPFire?"
+#: templates/tracker-torrent-detail.html:28
+msgid "Seeds"
+msgstr "Seeds"
-#: templates/static/development.html:186
-msgid "How to submit patches?"
-msgstr "Wie sendet man Patches?"
+#: templates/wishlist/closed.html:3 templates/wishlist/closed.html:13
+msgid "Closed wishes"
+msgstr "Beendete Wünsche"
-#: templates/static/development.html:214
-msgid "How to translate IPFire?"
-msgstr "Wie übersetzt man IPFire?"
+#: templates/wishlist/closed.html:9
+msgid "Wishes open for donation"
+msgstr "Noch laufende Wünsche"
-#: templates/static/chat.html:33
-msgid "Server"
-msgstr "Server"
+#: templates/wishlist/closed.html:36 templates/wishlist/closed.html:40
+msgid "Older"
+msgstr "Älter"
-#: templates/static/chat.html:36
-msgid "Channel"
-msgstr "Channel"
+#: templates/wishlist/closed.html:46 templates/wishlist/closed.html:50
+msgid "Newer"
+msgstr "Neuer"
-#: templates/static/chat.html:41
-msgid "Use the web client"
-msgstr "Web-Client benutzen"
+#: templates/wishlist/donate.html:13 templates/wishlist/donate.html:23
+#: templates/wishlist/terms.html:3 templates/wishlist/terms.html:7
+#: templates/base.html:78
+msgid "Terms & Conditions"
+msgstr "Allgemeine Bedingungen"
-#: templates/static/cebit.html:3
-msgid "CeBIT special"
-msgstr "CeBIT-Spezial"
+#: templates/wishlist/modules/wish.html:6
+msgid "Only a few days left!"
+msgstr "Nur noch wenige Tage!"
-#: templates/static/cebit.html:8
-msgid "IPFire at CeBIT 2010"
-msgstr "IPFire auf der CeBIT 2010"
+#: templates/wishlist/modules/wish.html:36
+msgid "funded"
+msgstr "gesammelt"
-#: templates/static/getinvolved.html:3 templates/static/getinvolved.html:8
-msgid "Get involved"
-msgstr "Mitmachen"
+#: templates/wishlist/modules/wish.html:40
+#: templates/wishlist/modules/wish.html:50
+#, python-format
+msgid "%s €"
+msgstr "%s €"
-#: templates/static/getinvolved.html:10
-msgid "Because making a difference is easy"
-msgstr "Weil es so leicht ist etwas Gutes zu tun"
+#: templates/wishlist/modules/wish.html:41
+msgid "donated"
+msgstr "gespendet"
-#: templates/static/getinvolved.html:47
-msgid "First steps"
-msgstr "Erste Schritte"
+#: templates/wishlist/modules/wish.html:48
+msgid "day to go"
+msgid_plural "days to go"
+msgstr[0] "Tag übrig"
+msgstr[1] "Tage übrig"
-#: templates/static/getinvolved.html:97
-msgid "Donations"
-msgstr "Spenden"
+#: templates/wishlist/modules/wish.html:51
+#, fuzzy
+msgid "to go"
+msgstr "Tag übrig"
-#: templates/static/getinvolved.html:142
-msgid "Make a wish"
-msgstr "Wünsch dir was"
+#: templates/wishlist/modules/wish.html:54
+msgid "In progress"
+msgstr "In Entwicklung"
-#: templates/static/getinvolved.html:149
-msgid "Contribute yourself"
-msgstr "Bring dich selbst ein"
+#: templates/wishlist/modules/wish.html:56
+msgid "Finished"
+msgstr "Beendet"
-#: templates/static/getinvolved.html:175
-msgid "Translation"
-msgstr "Ãœbersetzung"
+#: templates/wishlist/modules/wish.html:58
+msgid "Funding ended"
+msgstr "Sammlung beendet"
-#: templates/static/getinvolved.html:190
-msgid "Translation team"
-msgstr "Ãœbersetzungsteam"
+#: templates/wishlist/modules/wish.html:68
+msgid "Share this wish with your friends and help us promote it!"
+msgstr ""
+"Teile diesen Wunsch mit deinen Freunden und hilf diesen bekannter zu machen!"
-#: templates/static/getinvolved.html:196
-msgid "Promotion"
-msgstr "Promotion"
+#: templates/wishlist/index.html:3 templates/index.html:3
+msgid "Home"
+msgstr "Startseite"
-#: templates/static/artwork.html:36
-msgid "The IPFire Logo"
-msgstr "Das IPFire-Logo"
+#: templates/wishlist/wish.html:3
+msgid "Wish"
+msgstr "Wunsch"
-#: templates/static/artwork.html:50
-msgid "Flyers, Rollups, CDs and more"
-msgstr "Flyer, Rollups, CDs und mehr"
+#: templates/wishlist/wish.html:18
+#, python-format
+msgid "Launched: %s"
+msgstr "Gestarted: %s"
-#: templates/static/donation.html:10
-msgid "We need your help!"
-msgstr "Wir brauchen Deine Hilfe!"
+#: templates/wishlist/wish.html:24
+#, python-format
+msgid "Funding ends: %s"
+msgstr "Sammlung endet: %s"
-#: templates/static/donation.html:68
-msgid "Did you know...?"
-msgstr "Schon gewusst?"
+#: templates/wishlist/wish.html:26
+msgid "This funding runs until the goal is reached."
+msgstr ""
-#: templates/static/donation.html:84
-msgid "How do we use financial support?"
-msgstr "Wofür werden Spenden eingesetzt?"
+#: templates/wishlist/base.html:6 templates/index.html:175
+msgid "IPFire Wishlist"
+msgstr "IPFire Wunschliste"
-#: templates/static/donation.html:132
-msgid "Research & Development"
-msgstr "Forschung & Entwicklung"
+#: templates/wishlist/base.html:8
+msgid "Crowd funding for the IPFire project"
+msgstr "Crowdfunding für das IPFire-Projekt"
#: templates/index.html:92
msgid "Flexibility"
msgid "All mirrors"
msgstr "Alle Mirrors"
-#: templates/admin-mirrors-details.html:17
-msgid "Status"
-msgstr "Status"
-
#: templates/admin-mirrors-details.html:29
msgid "GeoIP Location"
msgstr "GeoIP Standort"
msgid "Filelist"
msgstr "Dateiliste"
-#: templates/admin-accounts.html:8
-msgid "Create new account"
-msgstr "Neuen Account erstellen"
+#: templates/base.html:4
+msgid "No title given"
+msgstr "Kein Titel"
-#: templates/admin-accounts.html:13
-msgid "Name (Nickname)"
-msgstr "Name (Nickname)"
+#: templates/base.html:63
+msgid "IPFire is free software"
+msgstr "IPFire ist freie Software"
+
+#: templates/download-splash.html:3 templates/download-splash.html:7
+msgid "Thanks for downloading IPFire!"
+msgstr "Vielen Dank, für das Herunterladen von IPFire! "
+
+#: templates/download-splash.html:61
+msgid "Next steps"
+msgstr "Nächste Schritte"
+
+#: templates/download-splash.html:66
+msgid "Install IPFire"
+msgstr "IPFire installieren"
-#: templates/mirrors.html:25
-msgid "Mirror servers nearby"
-msgstr "Nahgelegene Mirrorserver"
+#: templates/download-splash.html:82
+msgid "Access documentation"
+msgstr "Dokumentation lesen"
-#: templates/mirrors.html:28 templates/mirrors.html:31
-msgid "Worldwide mirror servers"
-msgstr "Weltweite Mirrorserver"
+#: templates/download-splash.html:100
+msgid "Join the community"
+msgstr "Der Community beitreten"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Monday"
msgstr "Montag"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Tuesday"
msgstr "Dienstag"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Wednesday"
msgstr "Mittwoch"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Thursday"
msgstr "Donnerstag"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:230
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:240
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:240
msgid "Friday"
msgstr "Freitag"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:230
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:240
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:240
msgid "Saturday"
msgstr "Samstag"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:230
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:240
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:240
msgid "Sunday"
msgstr "Sonntag"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:274
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:290
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:290
#, python-format
msgid "1 second ago"
msgid_plural "%(seconds)d seconds ago"
msgstr[0] "vor einer Sekunde"
msgstr[1] "vor %(seconds)d Sekunden"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:279
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:295
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:295
#, python-format
msgid "1 minute ago"
msgid_plural "%(minutes)d minutes ago"
msgstr[0] "vor einer Minute"
msgstr[1] "vor %(minutes)d Minuten"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:283
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:299
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:299
#, python-format
msgid "1 hour ago"
msgid_plural "%(hours)d hours ago"
msgstr[0] "vor einer Stunde"
msgstr[1] "vor %(hours)d Stunden"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:287
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:303
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:303
#, python-format
msgid "%(time)s"
msgstr "%(time)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:290
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:306
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:306
msgid "yesterday"
msgstr "gestern"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:291
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:307
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:307
#, python-format
msgid "yesterday at %(time)s"
msgstr "gestern um %(time)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:293
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:309
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:309
#, python-format
msgid "%(weekday)s"
msgstr "%(weekday)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:294
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:310
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:310
#, python-format
msgid "%(weekday)s at %(time)s"
msgstr "%(weekday)s um %(time)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:296
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:338
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:312
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:354
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:312
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:354
#, python-format
msgid "%(month_name)s %(day)s"
msgstr "%(day)s. %(month_name)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:297
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:313
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:313
#, python-format
msgid "%(month_name)s %(day)s at %(time)s"
msgstr "%(day)s. %(month_name)s um %(time)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:300
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:316
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:316
#, python-format
msgid "%(month_name)s %(day)s, %(year)s"
msgstr "%(day)s %(month_name)s %(year)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:301
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:317
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:317
#, python-format
msgid "%(month_name)s %(day)s, %(year)s at %(time)s"
msgstr "%(day)s. %(month_name)s %(year)s um %(time)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:332
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:348
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:348
#, python-format
msgid "%(weekday)s, %(month_name)s %(day)s"
msgstr "%(weekday)s, %(day)s. %(month_name)s"
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:353
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:369
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:369
#, python-format
msgid "%(commas)s and %(last)s"
msgstr "%(commas)s und %(last)s"
+#~ msgid "Your distance to this mirror"
+#~ msgstr "Deine Entfernung zu diesem Mirror"
+
+#~ msgid "Mirror location"
+#~ msgstr "Mirrorort"
+
+#~ msgid "The mirror <em>%s</em> is located in %s."
+#~ msgstr "Der Mirrorserver <em>%s</em> befindet sich in %s."
+
+#~ msgid "Mirror servers nearby"
+#~ msgstr "Nahgelegene Mirrorserver"
+
+#~ msgid "Worldwide mirror servers"
+#~ msgstr "Weltweite Mirrorserver"
+
#~ msgid "Please donate!"
#~ msgstr "Spenden!"
#~ msgid "Join the IRC channel"
#~ msgstr "Dem IRC-Channel beitreten"
-#~ msgid "About"
-#~ msgstr "Ãœber"
-
#~ msgid "Updates in the last 24 hours"
#~ msgstr "Updates innerhalb der vergangenen 24 Stunden"
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-07-22 11:43+0200\n"
+"POT-Creation-Date: 2013-12-27 11:53+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-#: webapp/handlers_news.py:43 webapp/ui_modules.py:76
-msgid "Unknown author"
+#: webapp/backend/iuse.py:162
+#, python-format
+msgid "Mem: %s"
msgstr ""
-#: webapp/__init__.py:285
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "January"
+#: webapp/backend/iuse.py:165
+#, python-format
+msgid "Disk: %s"
msgstr ""
-#: webapp/__init__.py:287
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "February"
+#: webapp/backend/iuse.py:177
+#, python-format
+msgid "Networks: %s"
msgstr ""
-#: webapp/__init__.py:289
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "March"
+#: webapp/backend/countries.py:7
+msgid "Andorra"
msgstr ""
-#: webapp/__init__.py:291
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:225
-msgid "April"
+#: webapp/backend/countries.py:8
+msgid "United Arab Emirates"
msgstr ""
-#: webapp/__init__.py:293
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "May"
+#: webapp/backend/countries.py:9
+msgid "Afghanistan"
msgstr ""
-#: webapp/__init__.py:295
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "June"
+#: webapp/backend/countries.py:10
+msgid "Antigua and Barbuda"
msgstr ""
-#: webapp/__init__.py:297
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "July"
+#: webapp/backend/countries.py:11
+msgid "Aanguilla"
msgstr ""
-#: webapp/__init__.py:299
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:226
-msgid "August"
+#: webapp/backend/countries.py:12
+msgid "Albania"
msgstr ""
-#: webapp/__init__.py:301
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "September"
+#: webapp/backend/countries.py:13
+msgid "Armenia"
msgstr ""
-#: webapp/__init__.py:303
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "October"
+#: webapp/backend/countries.py:14
+msgid "Angola"
msgstr ""
-#: webapp/__init__.py:305
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "November"
+#: webapp/backend/countries.py:15
+msgid "Antarctica"
msgstr ""
-#: webapp/__init__.py:307
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:227
-msgid "December"
+#: webapp/backend/countries.py:16
+msgid "Argentina"
msgstr ""
-#: webapp/ui_modules.py:239
-#, python-format
-msgid "%s to %s"
+#: webapp/backend/countries.py:17
+msgid "American Samoa"
msgstr ""
-#: webapp/backend/wishlist.py:187
-msgid "Checkout this crowdfunding wish from #ipfire:"
+#: webapp/backend/countries.py:18
+msgid "Austria"
msgstr ""
-#: webapp/backend/releases.py:96
-msgid "Image for the armv5tel architecture"
+#: webapp/backend/countries.py:19
+msgid "Australia"
msgstr ""
-#: webapp/backend/releases.py:97
-msgid "armv5tel image for boards with serial console"
+#: webapp/backend/countries.py:20
+msgid "Aruba"
msgstr ""
-#: webapp/backend/releases.py:98
-msgid "Installable CD image"
+#: webapp/backend/countries.py:21
+msgid "Ã…land Islands"
msgstr ""
-#: webapp/backend/releases.py:99
-msgid "Torrent file"
+#: webapp/backend/countries.py:22
+msgid "Azerbaijan"
msgstr ""
-#: webapp/backend/releases.py:100
-msgid "Flash image"
+#: webapp/backend/countries.py:23
+msgid "Bosnia and Herzegovina"
msgstr ""
-#: webapp/backend/releases.py:101
-msgid "Alix image"
+#: webapp/backend/countries.py:24
+msgid "Barbados"
msgstr ""
-#: webapp/backend/releases.py:102
-msgid "USB FDD Image"
+#: webapp/backend/countries.py:25
+msgid "Bangladesh"
msgstr ""
-#: webapp/backend/releases.py:103
-msgid "USB HDD Image"
+#: webapp/backend/countries.py:26
+msgid "Belgium"
msgstr ""
-#: webapp/backend/releases.py:104
-msgid "Pregenerated Xen image"
+#: webapp/backend/countries.py:27
+msgid "Burkina Faso"
msgstr ""
-#: webapp/backend/releases.py:110 webapp/backend/releases.py:150
-msgid "Unknown image type"
+#: webapp/backend/countries.py:28
+msgid "Bulgaria"
msgstr ""
-#: webapp/backend/releases.py:136
-msgid "This image runs on many ARM-based boards"
+#: webapp/backend/countries.py:29
+msgid "Bahrain"
msgstr ""
-#: webapp/backend/releases.py:137
-msgid "This image runs on ARM boards with a serial console"
+#: webapp/backend/countries.py:30
+msgid "Burundi"
msgstr ""
-#: webapp/backend/releases.py:138
-msgid "Use this image to burn a CD and install IPFire from it."
+#: webapp/backend/countries.py:31
+msgid "Benin"
msgstr ""
-#: webapp/backend/releases.py:139
-msgid "Download the CD image from the torrent network."
+#: webapp/backend/countries.py:32
+msgid "Saint Barthélemy"
msgstr ""
-#: webapp/backend/releases.py:140
-msgid "An image that is meant to run on embedded devices."
+#: webapp/backend/countries.py:33
+msgid "Bermuda"
msgstr ""
-#: webapp/backend/releases.py:141
-msgid "Flash image where a serial console is enabled by default."
+#: webapp/backend/countries.py:34
+msgid "Brunei Darussalam"
msgstr ""
-#: webapp/backend/releases.py:142
-msgid "Install IPFire from a floppy-formated USB key."
+#: webapp/backend/countries.py:35
+msgid "Plurinational State of Bolivia"
msgstr ""
-#: webapp/backend/releases.py:143
-msgid "If the floppy image doesn't work, use this image instead."
+#: webapp/backend/countries.py:36
+msgid "Sint Eustatius and Saba Bonaire"
msgstr ""
-#: webapp/backend/releases.py:144
-msgid "A ready-to-run image for Xen."
+#: webapp/backend/countries.py:37
+msgid "Brazil"
msgstr ""
-#: webapp/backend/iuse.py:165
-#, python-format
-msgid "Mem: %s"
+#: webapp/backend/countries.py:38
+msgid "Bahamas"
msgstr ""
-#: webapp/backend/iuse.py:168
-#, python-format
-msgid "Disk: %s"
+#: webapp/backend/countries.py:39
+msgid "Bhutan"
msgstr ""
-#: webapp/backend/iuse.py:180
-#, python-format
-msgid "Networks: %s"
+#: webapp/backend/countries.py:40
+msgid "Bouvet Island"
msgstr ""
-#: templates/wishlist/wish.html:3
-msgid "Wish"
+#: webapp/backend/countries.py:41
+msgid "Botswana"
msgstr ""
-#: templates/wishlist/wish.html:18
-#, python-format
-msgid "Launched: %s"
+#: webapp/backend/countries.py:42
+msgid "Belarus"
msgstr ""
-#: templates/wishlist/wish.html:23
-#, python-format
-msgid "Funding ends: %s"
+#: webapp/backend/countries.py:43
+msgid "Belize"
msgstr ""
-#: templates/wishlist/closed.html:3 templates/wishlist/closed.html:13
-msgid "Closed wishes"
+#: webapp/backend/countries.py:44
+msgid "Canada"
msgstr ""
-#: templates/wishlist/closed.html:9
-msgid "Wishes open for donation"
+#: webapp/backend/countries.py:45
+msgid "Cocos (Keeling) Islands"
msgstr ""
-#: templates/wishlist/closed.html:36 templates/wishlist/closed.html:40
-msgid "Older"
+#: webapp/backend/countries.py:46
+msgid "The Democratic Republic of the Congo"
msgstr ""
-#: templates/wishlist/closed.html:46 templates/wishlist/closed.html:50
-msgid "Newer"
+#: webapp/backend/countries.py:47
+msgid "Central African Republic"
msgstr ""
-#: templates/wishlist/base.html:6 templates/index.html:175
-msgid "IPFire Wishlist"
+#: webapp/backend/countries.py:48
+msgid "Congo"
msgstr ""
-#: templates/wishlist/base.html:8
-msgid "Crowd funding for the IPFire project"
+#: webapp/backend/countries.py:49
+msgid "Switzerland"
msgstr ""
-#: templates/wishlist/modules/wish.html:6
-msgid "Only a few days left!"
+#: webapp/backend/countries.py:50
+msgid "Côte d'Ivoire"
msgstr ""
-#: templates/wishlist/modules/wish.html:26 templates/wishlist/donate.html:3
-#: templates/download-splash.html:37 templates/modules/menu.html:47
-#: templates/static/getinvolved.html:120 templates/static/donation.html:3
-#: templates/static/donation.html:8
-msgid "Donate"
+#: webapp/backend/countries.py:51
+msgid "Cook Islands"
msgstr ""
-#: templates/wishlist/modules/wish.html:36
-msgid "funded"
+#: webapp/backend/countries.py:52
+msgid "Chile"
msgstr ""
-#: templates/wishlist/modules/wish.html:40
-#, python-format
-msgid "%s €"
+#: webapp/backend/countries.py:53
+msgid "Cameroon"
msgstr ""
-#: templates/wishlist/modules/wish.html:41
-msgid "donated"
+#: webapp/backend/countries.py:54
+msgid "China"
msgstr ""
-#: templates/wishlist/modules/wish.html:47
-msgid "day to go"
-msgid_plural "days to go"
-msgstr[0] ""
-msgstr[1] ""
+#: webapp/backend/countries.py:55
+msgid "Colombia"
+msgstr ""
-#: templates/wishlist/modules/wish.html:49
-msgid "In progress"
+#: webapp/backend/countries.py:56
+msgid "Costa Rica"
msgstr ""
-#: templates/wishlist/modules/wish.html:51
-msgid "Finished"
+#: webapp/backend/countries.py:57
+msgid "Cuba"
msgstr ""
-#: templates/wishlist/modules/wish.html:53
-msgid "Funding ended"
+#: webapp/backend/countries.py:58
+msgid "Cape Verde"
msgstr ""
-#: templates/wishlist/modules/wish.html:63
-msgid "Share this wish with your friends and help us promote it!"
+#: webapp/backend/countries.py:59
+msgid "Curaçao"
msgstr ""
-#: templates/wishlist/index.html:3 templates/index.html:3
-msgid "Home"
+#: webapp/backend/countries.py:60
+msgid "Chrismas Islands"
msgstr ""
-#: templates/wishlist/donate.html:13 templates/wishlist/donate.html:23
-#: templates/wishlist/terms.html:3 templates/wishlist/terms.html:7
-#: templates/base.html:78
-msgid "Terms & Conditions"
+#: webapp/backend/countries.py:61
+msgid "Cyprus"
msgstr ""
-#: templates/downloads-index.html:3
-msgid "Download Center"
+#: webapp/backend/countries.py:62
+msgid "Czech Republic"
msgstr ""
-#: templates/downloads-index.html:7
-msgid "IPFire Download Center"
+#: webapp/backend/countries.py:63
+msgid "Germany"
msgstr ""
-#: templates/downloads-index.html:30
-msgid "Available releases"
+#: webapp/backend/countries.py:64
+msgid "Djibouti"
msgstr ""
-#: templates/downloads-index.html:35 templates/downloads-older.html:25
-#: templates/tracker-torrents.html:32
-msgid "Release"
+#: webapp/backend/countries.py:65
+msgid "Denmark"
msgstr ""
-#: templates/downloads-index.html:36
-msgid "Release type"
+#: webapp/backend/countries.py:66
+msgid "Dominica"
msgstr ""
-#: templates/downloads-index.html:37
-msgid "Release date"
+#: webapp/backend/countries.py:67
+msgid "Dominican Republic"
msgstr ""
-#: templates/downloads-index.html:48
-msgid "Stable"
+#: webapp/backend/countries.py:68
+msgid "Algeria"
msgstr ""
-#: templates/downloads-index.html:50 templates/modules/menu.html:65
-#: templates/static/development.html:3 templates/static/development.html:8
-#: templates/static/getinvolved.html:153
-msgid "Development"
+#: webapp/backend/countries.py:69
+msgid "Ecuador"
msgstr ""
-#: templates/admin-downloads-base.html:5
-msgid "Back to home"
+#: webapp/backend/countries.py:70
+msgid "Estonia"
msgstr ""
-#: templates/admin-downloads-base.html:8 templates/admin-base.html:6
-msgid "Options"
+#: webapp/backend/countries.py:71
+msgid "Egypt"
msgstr ""
-#: templates/admin-downloads-base.html:11
-msgid "Mirror stats"
+#: webapp/backend/countries.py:72
+msgid "Western Sahara"
msgstr ""
-#: templates/downloads-older.html:3 templates/downloads-older.html:7
-msgid "Ancient downloads"
+#: webapp/backend/countries.py:73
+msgid "Eritrea"
msgstr ""
-#: templates/downloads-older.html:9 templates/downloads-all.html:9
-msgid ""
-"These are the ancient downloads of IPFire. They are just saved for "
-"historical reasons and should not be used in a productive environment."
+#: webapp/backend/countries.py:74
+msgid "Spain"
msgstr ""
-#: templates/downloads-older.html:13
-msgid ""
-"Beware that these releases could lack possible security-fixes\tand so it is "
-"recommended to use the <em>latest</em> version."
+#: webapp/backend/countries.py:75
+msgid "Ethiopia"
msgstr ""
-#: templates/downloads-older.html:17 templates/downloads-all.html:13
-msgid "Go back to latest stable downloads."
+#: webapp/backend/countries.py:76
+msgid "Finland"
msgstr ""
-#: templates/downloads-older.html:26
-msgid "Published on"
+#: webapp/backend/countries.py:77
+msgid "Fiji"
msgstr ""
-#: templates/admin-login.html:3
-msgid "Please login"
+#: webapp/backend/countries.py:78
+msgid "Falkland Islands (Malvinas)"
msgstr ""
-#: templates/mirrors-item.html:3
-#, python-format
-msgid "Mirror %s"
+#: webapp/backend/countries.py:79
+msgid "Federated States of Micronesia"
msgstr ""
-#: templates/mirrors-item.html:8
-msgid "Up"
+#: webapp/backend/countries.py:80
+msgid "Faroe Islands"
msgstr ""
-#: templates/mirrors-item.html:10
-msgid "Down"
+#: webapp/backend/countries.py:81
+msgid "France"
msgstr ""
-#: templates/mirrors-item.html:12
-msgid "Out of sync"
+#: webapp/backend/countries.py:82
+msgid "Gabon"
msgstr ""
-#: templates/mirrors-item.html:14 templates/fireinfo/profile-detail.html:74
-#: templates/fireinfo/profile-detail.html:82
-msgid "Unknown"
+#: webapp/backend/countries.py:83
+msgid "United Kingdom"
msgstr ""
-#: templates/mirrors-item.html:22 templates/downloads-mirrors.html:50
-#: templates/fireinfo/profile-detail.html:231
-#: templates/download-mirror-detail.html:20 templates/admin-mirrors.html:15
-msgid "Last update"
+#: webapp/backend/countries.py:84
+msgid "Grenada"
msgstr ""
-#: templates/mirrors-item.html:26 templates/downloads-mirrors.html:47
-#: templates/admin-mirrors-create.html:20
-#: templates/download-mirror-detail.html:16
-#: templates/admin-mirrors-details.html:21
-msgid "Owner"
+#: webapp/backend/countries.py:85
+msgid "Georgia"
msgstr ""
-#: templates/mirrors-item.html:31
-msgid "Preferred for"
+#: webapp/backend/countries.py:86
+msgid "French Guiana"
msgstr ""
-#: templates/mirrors-item.html:37
-msgid "Your distance to this mirror"
+#: webapp/backend/countries.py:87
+msgid "Guersey"
msgstr ""
-#: templates/mirrors-item.html:43
-msgid "Go to mirror"
+#: webapp/backend/countries.py:88
+msgid "Ghana"
msgstr ""
-#: templates/mirrors-item.html:48
-msgid "Mirror location"
+#: webapp/backend/countries.py:89
+msgid "Gibraltar"
msgstr ""
-#: templates/mirrors-item.html:50
-#, python-format
-msgid "The mirror <em>%s</em> is located in %s."
+#: webapp/backend/countries.py:90
+msgid "Greenland"
msgstr ""
-#: templates/mirrors-item.html:58
-msgid "View larger map"
+#: webapp/backend/countries.py:91
+msgid "Gambia"
msgstr ""
-#: templates/mirrors-item.html:63
-msgid "The location of the mirror server is estimated by the IP address."
+#: webapp/backend/countries.py:92
+msgid "Guinea"
msgstr ""
-#: templates/mirrors-item.html:66
-msgid "The location of the mirror server could not be estimated."
+#: webapp/backend/countries.py:93
+msgid "Guadeloupe"
msgstr ""
-#: templates/admin-downloads-mirrors.html:5 templates/admin-downloads.html:5
-msgid "Download statistics"
+#: webapp/backend/countries.py:94
+msgid "Equatorial Guinea"
msgstr ""
-#: templates/admin-downloads-mirrors.html:7
-msgid "Mirror load from today"
+#: webapp/backend/countries.py:95
+msgid "Greece"
msgstr ""
-#: templates/admin-downloads-mirrors.html:10
-msgid "Mirror load"
+#: webapp/backend/countries.py:96
+msgid "South Georgia and the South Sandwich Islands"
msgstr ""
-#: templates/news-year.html:3 templates/news.html:3
-msgid "News"
+#: webapp/backend/countries.py:97
+msgid "Guatemala"
msgstr ""
-#: templates/news-year.html:7
-#, python-format
-msgid "News from %(year)s"
+#: webapp/backend/countries.py:98
+msgid "Guam"
msgstr ""
-#: templates/tracker-torrent-detail.html:3
-#: templates/tracker-torrent-detail.html:18
-#: templates/modules/release-item.html:115
-msgid "Torrent download"
+#: webapp/backend/countries.py:99
+msgid "Guinea-Bissau"
msgstr ""
-#: templates/tracker-torrent-detail.html:15
-#: templates/modules/release-item.html:114
-msgid "Magnet link"
+#: webapp/backend/countries.py:100
+msgid "Guyana"
msgstr ""
-#: templates/tracker-torrent-detail.html:23 templates/tracker-torrents.html:34
-msgid "Peers"
+#: webapp/backend/countries.py:101
+msgid "Hong Kong"
msgstr ""
-#: templates/tracker-torrent-detail.html:28
-msgid "Seeds"
+#: webapp/backend/countries.py:102
+msgid "Heard Island and McDonald Islands"
msgstr ""
-#: templates/sources.html:3
-msgid "Sources"
+#: webapp/backend/countries.py:103
+msgid "Honduras"
msgstr ""
-#: templates/sources.html:6 templates/static/development.html:263
-msgid "Source Code"
+#: webapp/backend/countries.py:104
+msgid "Croatia"
msgstr ""
-#: templates/sources.html:9
-#, python-format
-msgid "There are %s source files on the server."
+#: webapp/backend/countries.py:105
+msgid "Haiti"
msgstr ""
-#: templates/news-author.html:7
-#, python-format
-msgid "%s's announcements"
+#: webapp/backend/countries.py:106
+msgid "Hungary"
msgstr ""
-#: templates/admin-index.html:5
-msgid "Admin Area"
+#: webapp/backend/countries.py:107
+msgid "Indonesia"
msgstr ""
-#: templates/admin-base.html:3
-msgid "IPFire Admin Area"
+#: webapp/backend/countries.py:108
+msgid "Ireland"
msgstr ""
-#: templates/admin-base.html:9
-msgid "Accounts"
+#: webapp/backend/countries.py:109
+msgid "Israel"
msgstr ""
-#: templates/admin-base.html:10 templates/modules/menu.html:110
-msgid "Mirrors"
+#: webapp/backend/countries.py:110
+msgid "Isle of Man"
msgstr ""
-#: templates/admin-base.html:11 templates/modules/menu.html:92
-msgid "Planet"
+#: webapp/backend/countries.py:111
+msgid "India"
msgstr ""
-#: templates/admin-base.html:12
-msgid "Downloads"
+#: webapp/backend/countries.py:112
+msgid "British Indian Ocean Territory"
msgstr ""
-#: templates/admin-planet-compose.html:5 templates/admin-planet.html:8
-msgid "Compose new entry"
+#: webapp/backend/countries.py:113
+msgid "Iraq"
msgstr ""
-#: templates/admin-planet-compose.html:16 templates/admin-planet.html:14
-msgid "Title"
+#: webapp/backend/countries.py:114
+msgid "Islamic Republic of Iran"
msgstr ""
-#: templates/admin-planet-compose.html:33 templates/planet/posting.html:19
-msgid "Tags"
+#: webapp/backend/countries.py:115
+msgid "Iceland"
msgstr ""
-#: templates/admin-planet-compose.html:41
-msgid "Save"
+#: webapp/backend/countries.py:116
+msgid "Italy"
msgstr ""
-#: templates/admin-planet-compose.html:42
-msgid "Preview"
+#: webapp/backend/countries.py:117
+msgid "Jersey"
msgstr ""
-#: templates/admin-planet-compose.html:43
-msgid "Cancel"
+#: webapp/backend/countries.py:118
+msgid "Jamaica"
msgstr ""
-#: templates/download-splash.html:3 templates/download-splash.html:7
-msgid "Thanks for downloading IPFire!"
+#: webapp/backend/countries.py:119
+msgid "Jordan"
msgstr ""
-#: templates/download-splash.html:61
-msgid "Next steps"
+#: webapp/backend/countries.py:120
+msgid "Japan"
msgstr ""
-#: templates/download-splash.html:66
-msgid "Install IPFire"
+#: webapp/backend/countries.py:121
+msgid "Kenya"
msgstr ""
-#: templates/download-splash.html:82
-msgid "Access documentation"
+#: webapp/backend/countries.py:122
+msgid "Kyrgyzstan"
msgstr ""
-#: templates/download-splash.html:100
-msgid "Join the community"
+#: webapp/backend/countries.py:123
+msgid "Cambodia"
msgstr ""
-#: templates/downloads-development.html:3
-#: templates/downloads-development.html:6
-msgid "Development Downloads"
+#: webapp/backend/countries.py:124
+msgid "Kiribati"
msgstr ""
-#: templates/error-500.html:6
-msgid "Detailed information"
+#: webapp/backend/countries.py:125
+msgid "Comoros"
msgstr ""
-#: templates/admin-planet.html:5
-msgid "Planet Administrator"
+#: webapp/backend/countries.py:126
+msgid "Saint Kitts and Nevis"
msgstr ""
-#: templates/admin-planet.html:13
-msgid "Author"
+#: webapp/backend/countries.py:127
+msgid "Democratic People's Republic of Korea"
msgstr ""
-#: templates/admin-planet.html:21 templates/admin-mirrors.html:24
-#: templates/admin-accounts.html:20
-msgid "Edit"
+#: webapp/backend/countries.py:128
+msgid "Republic of Korea"
msgstr ""
-#: templates/downloads-mirrors.html:3 templates/download-mirror-detail.html:3
-msgid "Mirror-Server"
+#: webapp/backend/countries.py:129
+msgid "Kuwait"
msgstr ""
-#: templates/downloads-mirrors.html:8 templates/download-mirror-detail.html:8
-msgid "IPFire Mirrors"
+#: webapp/backend/countries.py:130
+msgid "Cayman Islands"
msgstr ""
-#: templates/downloads-mirrors.html:48 templates/admin-mirrors-create.html:12
-#: templates/download-mirror-detail.html:12 templates/admin-mirrors.html:14
-#: templates/admin-mirrors-details.html:13
-msgid "Hostname"
+#: webapp/backend/countries.py:131
+msgid "Kazakhstan"
msgstr ""
-#: templates/downloads-mirrors.html:49 templates/admin-mirrors-create.html:24
-#: templates/admin-mirrors-details.html:25
-msgid "Location"
+#: webapp/backend/countries.py:132
+msgid "Lao People's Democratic Public"
msgstr ""
-#: templates/downloads-mirrors.html:63
-msgid "details"
+#: webapp/backend/countries.py:133
+msgid "Lebanon"
msgstr ""
-#: templates/fireinfo/stats.html:3 templates/modules/menu.html:136
-msgid "Statistics"
+#: webapp/backend/countries.py:134
+msgid "Saint Lucia"
msgstr ""
-#: templates/fireinfo/stats.html:7
-msgid "fireinfo statistics"
+#: webapp/backend/countries.py:135
+msgid "Liechtenstein"
msgstr ""
-#: templates/fireinfo/stats.html:17
-msgid "IPFire versions"
+#: webapp/backend/countries.py:136
+msgid "Sri Lanka"
msgstr ""
-#: templates/fireinfo/stats.html:38 templates/fireinfo/stats-geo.html:3
-#: templates/fireinfo/stats-geo.html:7
-msgid "Geo locations"
+#: webapp/backend/countries.py:137
+msgid "Liberia"
msgstr ""
-#: templates/fireinfo/stats.html:59 templates/fireinfo/stats-cpus.html:7
-msgid "Hardware: CPUs"
+#: webapp/backend/countries.py:138
+msgid "Lesotho"
msgstr ""
-#: templates/fireinfo/stats.html:73
-msgid "CPU features"
+#: webapp/backend/countries.py:139
+msgid "Lithuania"
msgstr ""
-#: templates/fireinfo/stats.html:85
-msgid "Hardware: Memory"
+#: webapp/backend/countries.py:140
+msgid "Luxembourg"
msgstr ""
-#: templates/fireinfo/stats.html:106 templates/fireinfo/stats-network.html:3
-#: templates/fireinfo/profile-detail.html:95
-msgid "Network"
+#: webapp/backend/countries.py:141
+msgid "Latvia"
msgstr ""
-#: templates/fireinfo/stats.html:127 templates/fireinfo/stats-virtual.html:3
-#: templates/base-feature.html:65 templates/static/features.html:1179
-#: templates/static/features.html:1404
-msgid "Virtualization"
+#: webapp/backend/countries.py:142
+msgid "Libya"
msgstr ""
-#: templates/fireinfo/stats-network.html:7
-msgid "Network configuration"
+#: webapp/backend/countries.py:143
+msgid "Morocco"
msgstr ""
-#: templates/fireinfo/stats-oses.html:3
-#: templates/fireinfo/profile-detail.html:12
-msgid "Operating system"
+#: webapp/backend/countries.py:144
+msgid "Monaco"
msgstr ""
-#: templates/fireinfo/stats-oses.html:7
-msgid "Releases"
+#: webapp/backend/countries.py:145
+msgid "Republic of Moldova"
msgstr ""
-#: templates/fireinfo/stats-oses.html:18
-msgid "Architectures"
+#: webapp/backend/countries.py:146
+msgid "Montenegro"
msgstr ""
-#: templates/fireinfo/stats-oses.html:25
-msgid "Kernels"
+#: webapp/backend/countries.py:147
+msgid "Saint Martin (French Part)"
msgstr ""
-#: templates/fireinfo/profile-notfound.html:3
-#: templates/fireinfo/profile-notfound.html:8
-msgid "Profile not found"
+#: webapp/backend/countries.py:148
+msgid "Madagascar"
msgstr ""
-#: templates/fireinfo/stats-virtual.html:7
-msgid "Virtualization support"
+#: webapp/backend/countries.py:149
+msgid "Marshall Islands"
msgstr ""
-#: templates/fireinfo/stats-virtual.html:35
-msgid "Hypervisors"
+#: webapp/backend/countries.py:150
+msgid "The former Yugoslav Republic of Macedonia"
msgstr ""
-#: templates/fireinfo/profile-detail.html:3
-#: templates/fireinfo/profile-detail.html:7
-msgid "Profile"
+#: webapp/backend/countries.py:151
+msgid "Mali"
msgstr ""
-#: templates/fireinfo/profile-detail.html:16
-msgid "Version"
+#: webapp/backend/countries.py:152
+msgid "Myanmar"
msgstr ""
-#: templates/fireinfo/profile-detail.html:24
-msgid "Architecture"
+#: webapp/backend/countries.py:153
+msgid "Mongolia"
msgstr ""
-#: templates/fireinfo/profile-detail.html:32
-msgid "Kernel version"
+#: webapp/backend/countries.py:154
+msgid "Macao"
msgstr ""
-#: templates/fireinfo/profile-detail.html:43
-msgid "Hypervisor"
+#: webapp/backend/countries.py:155
+msgid "Northern Mariana Islands"
msgstr ""
-#: templates/fireinfo/profile-detail.html:45
-msgid "This machine is running in a virtual environment."
+#: webapp/backend/countries.py:156
+msgid "Martinique"
msgstr ""
-#: templates/fireinfo/profile-detail.html:51
-#: templates/fireinfo/profile-detail.html:71
-#: templates/fireinfo/profile-detail.html:130
-msgid "Vendor"
+#: webapp/backend/countries.py:157
+msgid "Mauritania"
msgstr ""
-#: templates/fireinfo/profile-detail.html:59
-msgid "Type"
+#: webapp/backend/countries.py:158
+msgid "Montserrat"
msgstr ""
-#: templates/fireinfo/profile-detail.html:67
-msgid "Hardware vendor"
+#: webapp/backend/countries.py:159
+msgid "Malta"
msgstr ""
-#: templates/fireinfo/profile-detail.html:79
-#: templates/fireinfo/profile-detail.html:138
-msgid "Model"
+#: webapp/backend/countries.py:160
+msgid "Mauritius"
msgstr ""
-#: templates/fireinfo/profile-detail.html:97
-msgid "Enabled network zones"
+#: webapp/backend/countries.py:161
+msgid "Maldives"
msgstr ""
-#: templates/fireinfo/profile-detail.html:119 templates/base-feature.html:62
-#: templates/static/features.html:1104 templates/static/features.html:1399
-msgid "Hardware"
+#: webapp/backend/countries.py:162
+msgid "Malawi"
msgstr ""
-#: templates/fireinfo/profile-detail.html:125
-msgid "CPU"
+#: webapp/backend/countries.py:163
+msgid "Mexico"
msgstr ""
-#: templates/fireinfo/profile-detail.html:141
-msgid "Not available"
+#: webapp/backend/countries.py:164
+msgid "Malaysia"
msgstr ""
-#: templates/fireinfo/profile-detail.html:146
-msgid "Cores"
+#: webapp/backend/countries.py:165
+msgid "Mozambique"
msgstr ""
-#: templates/fireinfo/profile-detail.html:154
-#: templates/fireinfo/stats-cpus.html:36
-msgid "Speed"
+#: webapp/backend/countries.py:166
+msgid "Namibia"
msgstr ""
-#: templates/fireinfo/profile-detail.html:166
-msgid "Supported features"
+#: webapp/backend/countries.py:167
+msgid "New Caledonia"
msgstr ""
-#: templates/fireinfo/profile-detail.html:170
-msgid "64 bit capable"
+#: webapp/backend/countries.py:168
+msgid "Niger"
msgstr ""
-#: templates/fireinfo/profile-detail.html:174
-msgid "PAE capable"
+#: webapp/backend/countries.py:169
+msgid "Norfolk Island"
msgstr ""
-#: templates/fireinfo/profile-detail.html:178
-msgid "VT-x/AMD-V"
+#: webapp/backend/countries.py:170
+msgid "Nigeria"
msgstr ""
-#: templates/fireinfo/profile-detail.html:190
-msgid "Memory size"
+#: webapp/backend/countries.py:171
+msgid "Nicaragua"
msgstr ""
-#: templates/fireinfo/profile-detail.html:198
-msgid "System disk size"
+#: webapp/backend/countries.py:172
+msgid "Netherlands"
msgstr ""
-#: templates/fireinfo/profile-detail.html:211
-msgid "Peripherial devices"
+#: webapp/backend/countries.py:173
+msgid "Norway"
msgstr ""
-#: templates/fireinfo/profile-detail.html:216
-msgid "Signature images"
+#: webapp/backend/countries.py:174
+msgid "Nepal"
msgstr ""
-#: templates/fireinfo/base.html:6 templates/modules/menu.html:98
-msgid "Fireinfo"
+#: webapp/backend/countries.py:175
+msgid "Nauru"
msgstr ""
-#: templates/fireinfo/base.html:7
-msgid "A hardware data collection tool for IPFire"
+#: webapp/backend/countries.py:176
+msgid "Niue"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:3
-msgid "Processors"
+#: webapp/backend/countries.py:177
+msgid "New Zealand"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:12
-msgid "See statistics about common CPU flags"
+#: webapp/backend/countries.py:178
+msgid "Oman"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:19
-msgid "Vendors"
+#: webapp/backend/countries.py:179
+msgid "Panama"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:38
-#, python-format
-msgid ""
-"The average speed of all systems in the database is: <strong>%.2f MHz</"
-"strong>."
+#: webapp/backend/countries.py:180
+msgid "Peru"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:40
-#, python-format
-msgid "All together, there are <strong>%s bogomips</strong> out there."
+#: webapp/backend/countries.py:181
+msgid "French Polynesia"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:48
-msgid "CPU core counter"
+#: webapp/backend/countries.py:182
+msgid "Papua New Guinea"
msgstr ""
-#: templates/fireinfo/stats-cpus.html:50
-msgid ""
-"See a breakdown of the CPU cores that are installed on the IPFire systems."
+#: webapp/backend/countries.py:183
+msgid "Philipplines"
msgstr ""
-#: templates/fireinfo/index.html:52
-msgid "Show"
+#: webapp/backend/countries.py:184
+msgid "Pakistan"
msgstr ""
-#: templates/fireinfo/model-detail.html:11
-#, python-format
-msgid "This device is installed on approximately %.2f%% of all systems."
+#: webapp/backend/countries.py:185
+msgid "Poland"
msgstr ""
-#: templates/fireinfo/model-detail.html:14
-msgid "Feedback"
+#: webapp/backend/countries.py:186
+msgid "Saint Pierre and Miquelon"
msgstr ""
-#: templates/fireinfo/model-detail.html:28
-msgid "Go to the wiki"
+#: webapp/backend/countries.py:187
+msgid "Pitcairn"
msgstr ""
-#: templates/fireinfo/stats-memory.html:3
-#: templates/fireinfo/stats-memory.html:7
-msgid "Memory"
+#: webapp/backend/countries.py:188
+msgid "Puerto Rico"
msgstr ""
-#: templates/fireinfo/stats-memory.html:13
-#, python-format
-msgid ""
-"The average amount of memory of all systems in the database is: <strong>%.2f "
-"MB</strong>."
+#: webapp/backend/countries.py:189
+msgid "Palestinian Territory, occupied"
msgstr ""
-#: templates/fireinfo/stats-geo.html:28
-msgid "Language selection"
+#: webapp/backend/countries.py:190
+msgid "Portugal"
msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:3
-msgid "CPU flags"
+#: webapp/backend/countries.py:191
+msgid "Palau"
msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:7
-msgid "Processor flags"
+#: webapp/backend/countries.py:192
+msgid "Paraguay"
msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:30
-msgid "CPUs that support 64 bits"
+#: webapp/backend/countries.py:193
+msgid "Qatar"
msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:46
-msgid "CPUs with PAE"
+#: webapp/backend/countries.py:194
+msgid "Réunion"
msgstr ""
-#: templates/fireinfo/stats-cpu-flags.html:62
-msgid "CPUs that support virtualization"
+#: webapp/backend/countries.py:195
+msgid "Romania"
msgstr ""
-#: templates/fireinfo/stats-admin.html:3
-msgid "Admin"
+#: webapp/backend/countries.py:196
+msgid "Serbia"
msgstr ""
-#: templates/fireinfo/stats-admin.html:11
-msgid "Sending profiles"
+#: webapp/backend/countries.py:197
+msgid "Russian Federation"
msgstr ""
-#: templates/fireinfo/stats-admin.html:19
-msgid "Archive size"
+#: webapp/backend/countries.py:198
+msgid "Rwanda"
msgstr ""
-#: templates/downloads.html:3 templates/downloads.html:8
-msgid "Get IPFire"
+#: webapp/backend/countries.py:199
+msgid "Saudi Arabia"
msgstr ""
-#: templates/downloads.html:10
-msgid "IPFire is completely free to download and use"
+#: webapp/backend/countries.py:200
+msgid "Solomon Islands"
msgstr ""
-#: templates/downloads.html:23
-msgid "More download options"
+#: webapp/backend/countries.py:201
+msgid "Seychelles"
msgstr ""
-#: templates/downloads.html:55
-msgid "Get yourself involved"
+#: webapp/backend/countries.py:202
+msgid "Sudan"
msgstr ""
-#: templates/admin-mirrors-create.html:5 templates/admin-mirrors.html:8
-msgid "Create new mirror"
+#: webapp/backend/countries.py:203
+msgid "Sweden"
msgstr ""
-#: templates/admin-mirrors-create.html:16
-msgid "Path"
+#: webapp/backend/countries.py:204
+msgid "Singapore"
msgstr ""
-#: templates/admin-mirrors-create.html:28
-#: templates/admin-mirrors-details.html:33
-msgid "File mirror"
+#: webapp/backend/countries.py:205
+msgid "Saint Helena, Ascension and Tristan Da Cunha"
msgstr ""
-#: templates/admin-mirrors-create.html:31
-#: templates/admin-mirrors-create.html:40
-#: templates/admin-mirrors-create.html:49
-#: templates/admin-mirrors-create.html:58
-msgid "yes"
+#: webapp/backend/countries.py:206
+msgid "Slovenia"
msgstr ""
-#: templates/admin-mirrors-create.html:32
-#: templates/admin-mirrors-create.html:41
-#: templates/admin-mirrors-create.html:50
-#: templates/admin-mirrors-create.html:59
-msgid "no"
+#: webapp/backend/countries.py:207
+msgid "Svalbard and Jan Mayen"
msgstr ""
-#: templates/admin-mirrors-create.html:37
-#: templates/admin-mirrors-details.html:37
-msgid "Pakfire 2 mirror"
+#: webapp/backend/countries.py:208
+msgid "Slovakia"
msgstr ""
-#: templates/admin-mirrors-create.html:46
-#: templates/admin-mirrors-details.html:41
-msgid "Pakfire 3 mirror"
+#: webapp/backend/countries.py:209
+msgid "Sierra Leone"
msgstr ""
-#: templates/admin-mirrors-create.html:55
-#: templates/admin-mirrors-details.html:45
-msgid "Disabled?"
+#: webapp/backend/countries.py:210
+msgid "San Marino"
msgstr ""
-#: templates/admin-downloads.html:7
-msgid "Download counters"
+#: webapp/backend/countries.py:211
+msgid "Senegal"
msgstr ""
-#: templates/admin-downloads.html:10
-msgid "Today"
+#: webapp/backend/countries.py:212
+msgid "Somalia"
msgstr ""
-#: templates/admin-downloads.html:14
-msgid "Yesterday"
+#: webapp/backend/countries.py:213
+msgid "Suriname"
msgstr ""
-#: templates/admin-downloads.html:18
-msgid "Total"
+#: webapp/backend/countries.py:214
+msgid "South Sudan"
msgstr ""
-#: templates/admin-downloads.html:23
-msgid "Downloads by country"
+#: webapp/backend/countries.py:215
+msgid "Sao Tome and Principe"
msgstr ""
-#: templates/news.html:7
-msgid "What is new on the IPFire project?"
+#: webapp/backend/countries.py:216
+msgid "El Salvador"
msgstr ""
-#: templates/news.html:34
-msgid "Stay up to date"
+#: webapp/backend/countries.py:217
+msgid "Sint Maarten (Dutch Part)"
msgstr ""
-#: templates/news.html:61 templates/planet/year.html:3
-#: templates/planet/user.html:3 templates/planet/search.html:3
-#: templates/planet/base.html:6 templates/planet/index.html:3
-#: templates/planet/posting.html:3 templates/index.html:154
-msgid "IPFire Planet"
+#: webapp/backend/countries.py:218
+msgid "Syrian Arab Republic"
msgstr ""
-#: templates/news.html:85
-msgid "Latest news"
+#: webapp/backend/countries.py:219
+msgid "Swaziland"
msgstr ""
-#: templates/base-feature.html:6 templates/modules/menu.html:7
-#: templates/static/features.html:3 templates/static/features.html:8
-#: templates/static/features.html:1349
-msgid "About IPFire"
+#: webapp/backend/countries.py:220
+msgid "Turks and Caicos Islands"
msgstr ""
-#: templates/base-feature.html:9 templates/static/features.html:88
-#: templates/static/features.html:1354 templates/index.html:75
-msgid "Security"
+#: webapp/backend/countries.py:221
+msgid "Chad"
msgstr ""
-#: templates/base-feature.html:12 templates/static/features.html:139
-#: templates/static/features.html:1359
-msgid "Firewall"
+#: webapp/backend/countries.py:222
+msgid "French Southern Territories"
msgstr ""
-#: templates/base-feature.html:15 templates/static/features.html:1364
-msgid "Pakfire"
+#: webapp/backend/countries.py:223
+msgid "Togo"
msgstr ""
-#: templates/base-feature.html:18 templates/static/features.html:432
-#: templates/static/features.html:1369
-msgid "Updates"
+#: webapp/backend/countries.py:224
+msgid "Thailand"
msgstr ""
-#: templates/base-feature.html:21
-msgid "It's free"
+#: webapp/backend/countries.py:225
+msgid "Tajikistan"
msgstr ""
-#: templates/base-feature.html:25
-msgid "Features"
+#: webapp/backend/countries.py:226
+msgid "Tokelau"
msgstr ""
-#: templates/base-feature.html:28 templates/static/features.html:502
-#: templates/static/features.html:1374
-msgid "Dialup"
+#: webapp/backend/countries.py:227
+msgid "Timor-Leste"
msgstr ""
-#: templates/base-feature.html:31 templates/static/features.html:616
-msgid "Web proxy"
+#: webapp/backend/countries.py:228
+msgid "Turkmenistan"
msgstr ""
-#: templates/base-feature.html:35 templates/static/features.html:705
-msgid "Content filter"
+#: webapp/backend/countries.py:229
+msgid "Tunisia"
msgstr ""
-#: templates/base-feature.html:38 templates/static/features.html:766
-msgid "Update accelerator"
+#: webapp/backend/countries.py:230
+msgid "Tonga"
msgstr ""
-#: templates/base-feature.html:41
-msgid "Virus scan"
+#: webapp/backend/countries.py:231
+msgid "Turkey"
msgstr ""
-#: templates/base-feature.html:45 templates/static/features.html:818
-#: templates/static/features.html:1384
-msgid "VPN"
+#: webapp/backend/countries.py:232
+msgid "Trinidad and Tobago"
msgstr ""
-#: templates/base-feature.html:49 templates/static/features.html:854
-msgid "IPsec"
+#: webapp/backend/countries.py:233
+msgid "Tuvalu"
msgstr ""
-#: templates/base-feature.html:52 templates/static/features.html:915
-msgid "OpenVPN"
+#: webapp/backend/countries.py:234
+msgid "Taiwan, Province of China"
msgstr ""
-#: templates/base-feature.html:56
-msgid "Intrusion detection"
+#: webapp/backend/countries.py:235
+msgid "United Republic of Tanzania"
msgstr ""
-#: templates/base-feature.html:59 templates/static/features.html:1031
-#: templates/static/features.html:1394
-msgid "Quality of Service"
+#: webapp/backend/countries.py:236
+msgid "Ukraine"
msgstr ""
-#: templates/base-feature.html:68
-msgid "Wireless AP"
+#: webapp/backend/countries.py:237
+msgid "Uganda"
msgstr ""
-#: templates/download-mirror-detail.html:24
-msgid "Number of files"
+#: webapp/backend/countries.py:238
+msgid "Unites States minor outlying islands"
msgstr ""
-#: templates/download-mirror-detail.html:32
-msgid "View list of all mirror servers."
+#: webapp/backend/countries.py:239
+msgid "Unites States"
msgstr ""
-#: templates/downloads-all.html:3
-msgid "Ancient Downloads"
+#: webapp/backend/countries.py:240
+msgid "Uruguay"
msgstr ""
-#: templates/downloads-all.html:7 templates/index.html:18
-msgid "Download IPFire"
+#: webapp/backend/countries.py:241
+msgid "Uzbekistan"
msgstr ""
-#: templates/admin-accounts-edit.html:5 templates/admin-accounts.html:5
-msgid "Account Administrator"
+#: webapp/backend/countries.py:242
+msgid "Vatican City State"
msgstr ""
-#: templates/planet/year.html:6
-#, python-format
-msgid "Year %s"
+#: webapp/backend/countries.py:243
+msgid "Saint Vincent and the Grenadines"
msgstr ""
-#: templates/planet/user.html:22 templates/planet/index.html:45
-msgid "Older posts"
+#: webapp/backend/countries.py:244
+msgid "Bolivarian Republic of Venezuela"
msgstr ""
-#: templates/planet/user.html:26 templates/planet/index.html:49
-msgid "Newer posts"
+#: webapp/backend/countries.py:245
+msgid "Virgin Islands, British"
msgstr ""
-#: templates/planet/user.html:33
-#, python-format
-msgid "%s did not write any posts, yet."
+#: webapp/backend/countries.py:246
+msgid "Virgin Islands, U.S."
msgstr ""
-#: templates/planet/user.html:48 templates/static/press.html:31
-#: templates/static/imprint.html:29 templates/static/imprint.html:41
-#: templates/static/imprint.html:53 templates/static/imprint.html:65
-msgid "Mail"
+#: webapp/backend/countries.py:247
+msgid "Viet Nam"
msgstr ""
-#: templates/planet/search.html:6
-#, python-format
-msgid "Search results for '%s'"
+#: webapp/backend/countries.py:248
+msgid "Vanuatu"
msgstr ""
-#: templates/planet/search.html:16
-#, python-format
-msgid "No results found for '%s'"
+#: webapp/backend/countries.py:249
+msgid "Wallis and Futuna"
msgstr ""
-#: templates/planet/base.html:9
-msgid "The official blog of the IPFire team"
+#: webapp/backend/countries.py:250
+msgid "Samoa"
msgstr ""
-#: templates/planet/index.html:24
-msgid "All posts from"
+#: webapp/backend/countries.py:251
+msgid "Yemen"
msgstr ""
-#: templates/planet/posting.html:24 templates/modules/planet-entry.html:14
-msgid "Posted by"
+#: webapp/backend/countries.py:252
+msgid "Mayotte"
msgstr ""
-#: templates/planet/posting.html:25 templates/modules/planet-entry.html:15
-msgid "on"
+#: webapp/backend/countries.py:253
+msgid "South Africa"
msgstr ""
-#: templates/base.html:4
-msgid "No title given"
+#: webapp/backend/countries.py:254
+msgid "Zambia"
msgstr ""
-#: templates/base.html:63
-msgid "IPFire is free software"
+#: webapp/backend/countries.py:255
+msgid "Zimbabwe"
msgstr ""
-#: templates/base.html:69 templates/static/press.html:3
-#: templates/static/press.html:7
-msgid "Press"
+#: webapp/backend/wishlist.py:207
+msgid "Checkout this crowdfunding wish from #ipfire:"
msgstr ""
-#: templates/base.html:73 templates/static/imprint.html:3
-#: templates/static/imprint.html:8
+#: webapp/backend/releases.py:89
+msgid "Image for the armv5tel architecture"
+msgstr ""
+
+#: webapp/backend/releases.py:90
+msgid "armv5tel image for boards with serial console"
+msgstr ""
+
+#: webapp/backend/releases.py:91
+msgid "Installable CD image"
+msgstr ""
+
+#: webapp/backend/releases.py:92
+msgid "Torrent file"
+msgstr ""
+
+#: webapp/backend/releases.py:93
+msgid "Flash image"
+msgstr ""
+
+#: webapp/backend/releases.py:94
+msgid "Alix image"
+msgstr ""
+
+#: webapp/backend/releases.py:95
+msgid "USB FDD Image"
+msgstr ""
+
+#: webapp/backend/releases.py:96
+msgid "USB HDD Image"
+msgstr ""
+
+#: webapp/backend/releases.py:97
+msgid "Pregenerated Xen image"
+msgstr ""
+
+#: webapp/backend/releases.py:103 webapp/backend/releases.py:143
+msgid "Unknown image type"
+msgstr ""
+
+#: webapp/backend/releases.py:129
+msgid "This image runs on many ARM-based boards"
+msgstr ""
+
+#: webapp/backend/releases.py:130
+msgid "This image runs on ARM boards with a serial console"
+msgstr ""
+
+#: webapp/backend/releases.py:131
+msgid "Use this image to burn a CD and install IPFire from it."
+msgstr ""
+
+#: webapp/backend/releases.py:132
+msgid "Download the CD image from the torrent network."
+msgstr ""
+
+#: webapp/backend/releases.py:133
+msgid "An image that is meant to run on embedded devices."
+msgstr ""
+
+#: webapp/backend/releases.py:134
+msgid "Flash image where a serial console is enabled by default."
+msgstr ""
+
+#: webapp/backend/releases.py:135
+msgid "Install IPFire from a floppy-formated USB key."
+msgstr ""
+
+#: webapp/backend/releases.py:136
+msgid "If the floppy image doesn't work, use this image instead."
+msgstr ""
+
+#: webapp/backend/releases.py:137
+msgid "A ready-to-run image for Xen."
+msgstr ""
+
+#: webapp/__init__.py:311
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "January"
+msgstr ""
+
+#: webapp/__init__.py:313
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "February"
+msgstr ""
+
+#: webapp/__init__.py:315
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "March"
+msgstr ""
+
+#: webapp/__init__.py:317
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:235
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:235
+msgid "April"
+msgstr ""
+
+#: webapp/__init__.py:319
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "May"
+msgstr ""
+
+#: webapp/__init__.py:321
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "June"
+msgstr ""
+
+#: webapp/__init__.py:323
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "July"
+msgstr ""
+
+#: webapp/__init__.py:325
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:236
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:236
+msgid "August"
+msgstr ""
+
+#: webapp/__init__.py:327
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "September"
+msgstr ""
+
+#: webapp/__init__.py:329
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "October"
+msgstr ""
+
+#: webapp/__init__.py:331
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "November"
+msgstr ""
+
+#: webapp/__init__.py:333
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:237
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:237
+msgid "December"
+msgstr ""
+
+#: webapp/ui_modules.py:114 webapp/handlers_news.py:43
+msgid "Unknown author"
+msgstr ""
+
+#: webapp/ui_modules.py:265
+#, python-format
+msgid "%s to %s"
+msgstr ""
+
+#: templates/downloads.html:3 templates/downloads.html:8
+msgid "Get IPFire"
+msgstr ""
+
+#: templates/downloads.html:10
+msgid "IPFire is completely free to download and use"
+msgstr ""
+
+#: templates/downloads.html:23
+msgid "More download options"
+msgstr ""
+
+#: templates/downloads.html:55
+msgid "Get yourself involved"
+msgstr ""
+
+#: templates/news-year.html:3 templates/news.html:3
+msgid "News"
+msgstr ""
+
+#: templates/news-year.html:7
+#, python-format
+msgid "News from %(year)s"
+msgstr ""
+
+#: templates/admin-index.html:5
+msgid "Admin Area"
+msgstr ""
+
+#: templates/fireinfo/stats.html:3 templates/modules/menu.html:136
+msgid "Statistics"
+msgstr ""
+
+#: templates/fireinfo/stats.html:7
+msgid "fireinfo statistics"
+msgstr ""
+
+#: templates/fireinfo/stats.html:17
+msgid "IPFire versions"
+msgstr ""
+
+#: templates/fireinfo/stats.html:38 templates/fireinfo/stats-geo.html:3
+#: templates/fireinfo/stats-geo.html:7
+msgid "Geo locations"
+msgstr ""
+
+#: templates/fireinfo/stats.html:59 templates/fireinfo/stats-cpus.html:7
+msgid "Hardware: CPUs"
+msgstr ""
+
+#: templates/fireinfo/stats.html:73
+msgid "CPU features"
+msgstr ""
+
+#: templates/fireinfo/stats.html:85
+msgid "Hardware: Memory"
+msgstr ""
+
+#: templates/fireinfo/stats.html:106 templates/fireinfo/stats-network.html:3
+#: templates/fireinfo/profile-detail.html:95
+msgid "Network"
+msgstr ""
+
+#: templates/fireinfo/stats.html:127 templates/fireinfo/stats-virtual.html:3
+#: templates/base-feature.html:65 templates/static/features.html:1179
+#: templates/static/features.html:1404
+msgid "Virtualization"
+msgstr ""
+
+#: templates/fireinfo/stats-memory.html:3
+#: templates/fireinfo/stats-memory.html:7
+msgid "Memory"
+msgstr ""
+
+#: templates/fireinfo/stats-memory.html:13
+#, python-format
+msgid ""
+"The average amount of memory of all systems in the database is: <strong>%.2f "
+"MB</strong>."
+msgstr ""
+
+#: templates/fireinfo/model-detail.html:11
+#, python-format
+msgid "This device is installed on approximately %.2f%% of all systems."
+msgstr ""
+
+#: templates/fireinfo/model-detail.html:14
+msgid "Feedback"
+msgstr ""
+
+#: templates/fireinfo/model-detail.html:28
+msgid "Go to the wiki"
+msgstr ""
+
+#: templates/fireinfo/stats-admin.html:3
+msgid "Admin"
+msgstr ""
+
+#: templates/fireinfo/stats-admin.html:11
+msgid "Sending profiles"
+msgstr ""
+
+#: templates/fireinfo/stats-admin.html:19
+msgid "Archive size"
+msgstr ""
+
+#: templates/fireinfo/profile-notfound.html:3
+#: templates/fireinfo/profile-notfound.html:8
+msgid "Profile not found"
+msgstr ""
+
+#: templates/fireinfo/stats-cpu-flags.html:3
+msgid "CPU flags"
+msgstr ""
+
+#: templates/fireinfo/stats-cpu-flags.html:7
+msgid "Processor flags"
+msgstr ""
+
+#: templates/fireinfo/stats-cpu-flags.html:30
+msgid "CPUs that support 64 bits"
+msgstr ""
+
+#: templates/fireinfo/stats-cpu-flags.html:46
+msgid "CPUs with PAE"
+msgstr ""
+
+#: templates/fireinfo/stats-cpu-flags.html:62
+msgid "CPUs that support virtualization"
+msgstr ""
+
+#: templates/fireinfo/stats-virtual.html:7
+msgid "Virtualization support"
+msgstr ""
+
+#: templates/fireinfo/stats-virtual.html:35
+msgid "Hypervisors"
+msgstr ""
+
+#: templates/fireinfo/stats-oses.html:3
+#: templates/fireinfo/profile-detail.html:12
+msgid "Operating system"
+msgstr ""
+
+#: templates/fireinfo/stats-oses.html:7
+msgid "Releases"
+msgstr ""
+
+#: templates/fireinfo/stats-oses.html:18
+msgid "Architectures"
+msgstr ""
+
+#: templates/fireinfo/stats-oses.html:25
+msgid "Kernels"
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:3
+msgid "Processors"
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:12
+msgid "See statistics about common CPU flags"
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:19
+msgid "Vendors"
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:36
+#: templates/fireinfo/profile-detail.html:154
+msgid "Speed"
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:38
+#, python-format
+msgid ""
+"The average speed of all systems in the database is: <strong>%.2f MHz</"
+"strong>."
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:40
+#, python-format
+msgid "All together, there are <strong>%s bogomips</strong> out there."
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:48
+msgid "CPU core counter"
+msgstr ""
+
+#: templates/fireinfo/stats-cpus.html:50
+msgid ""
+"See a breakdown of the CPU cores that are installed on the IPFire systems."
+msgstr ""
+
+#: templates/fireinfo/stats-network.html:7
+msgid "Network configuration"
+msgstr ""
+
+#: templates/fireinfo/index.html:52
+msgid "Show"
+msgstr ""
+
+#: templates/fireinfo/stats-geo.html:28
+msgid "Language selection"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:3
+#: templates/fireinfo/profile-detail.html:7
+msgid "Profile"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:16
+msgid "Version"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:24
+msgid "Architecture"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:32
+msgid "Kernel version"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:43
+msgid "Hypervisor"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:45
+msgid "This machine is running in a virtual environment."
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:51
+#: templates/fireinfo/profile-detail.html:71
+#: templates/fireinfo/profile-detail.html:130
+msgid "Vendor"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:59
+msgid "Type"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:67
+msgid "Hardware vendor"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:74
+#: templates/fireinfo/profile-detail.html:82 templates/mirrors-item.html:14
+msgid "Unknown"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:79
+#: templates/fireinfo/profile-detail.html:138
+msgid "Model"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:97
+msgid "Enabled network zones"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:119 templates/base-feature.html:62
+#: templates/static/features.html:1104 templates/static/features.html:1399
+msgid "Hardware"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:125
+msgid "CPU"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:141
+msgid "Not available"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:146
+msgid "Cores"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:166
+msgid "Supported features"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:170
+msgid "64 bit capable"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:174
+msgid "PAE capable"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:178
+msgid "VT-x/AMD-V"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:190
+msgid "Memory size"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:198
+msgid "System disk size"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:211
+msgid "Peripherial devices"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:216
+msgid "Signature images"
+msgstr ""
+
+#: templates/fireinfo/profile-detail.html:231 templates/admin-mirrors.html:15
+#: templates/download-mirror-detail.html:20
+#: templates/downloads-mirrors.html:50
+msgid "Last update"
+msgstr ""
+
+#: templates/fireinfo/base.html:6 templates/modules/menu.html:98
+msgid "Fireinfo"
+msgstr ""
+
+#: templates/fireinfo/base.html:7
+msgid "A hardware data collection tool for IPFire"
+msgstr ""
+
+#: templates/sources.html:3
+msgid "Sources"
+msgstr ""
+
+#: templates/sources.html:6 templates/static/development.html:263
+msgid "Source Code"
+msgstr ""
+
+#: templates/sources.html:9
+#, python-format
+msgid "There are %s source files on the server."
+msgstr ""
+
+#: templates/downloads-all.html:3
+msgid "Ancient Downloads"
+msgstr ""
+
+#: templates/downloads-all.html:7 templates/index.html:18
+msgid "Download IPFire"
+msgstr ""
+
+#: templates/downloads-all.html:9 templates/downloads-older.html:9
+msgid ""
+"These are the ancient downloads of IPFire. They are just saved for "
+"historical reasons and should not be used in a productive environment."
+msgstr ""
+
+#: templates/downloads-all.html:13 templates/downloads-older.html:17
+msgid "Go back to latest stable downloads."
+msgstr ""
+
+#: templates/admin-accounts-edit.html:5 templates/admin-accounts.html:5
+msgid "Account Administrator"
+msgstr ""
+
+#: templates/news-author.html:7
+#, python-format
+msgid "%s's announcements"
+msgstr ""
+
+#: templates/admin-mirrors.html:5
+msgid "Mirror Administrator"
+msgstr ""
+
+#: templates/admin-mirrors.html:8 templates/admin-mirrors-create.html:5
+msgid "Create new mirror"
+msgstr ""
+
+#: templates/admin-mirrors.html:9
+msgid "Re-check now"
+msgstr ""
+
+#: templates/admin-mirrors.html:14 templates/download-mirror-detail.html:12
+#: templates/admin-mirrors-create.html:12 templates/downloads-mirrors.html:48
+#: templates/admin-mirrors-details.html:13
+msgid "Hostname"
+msgstr ""
+
+#: templates/admin-mirrors.html:23 templates/admin-mirrors-details.html:5
+msgid "Details"
+msgstr ""
+
+#: templates/admin-mirrors.html:24 templates/admin-planet.html:29
+#: templates/admin-accounts.html:20
+msgid "Edit"
+msgstr ""
+
+#: templates/admin-mirrors.html:25 templates/admin-accounts.html:21
+msgid "Delete"
+msgstr ""
+
+#: templates/error-500.html:6
+msgid "Detailed information"
+msgstr ""
+
+#: templates/download-mirror-detail.html:3 templates/downloads-mirrors.html:3
+msgid "Mirror-Server"
+msgstr ""
+
+#: templates/download-mirror-detail.html:8 templates/downloads-mirrors.html:8
+msgid "IPFire Mirrors"
+msgstr ""
+
+#: templates/download-mirror-detail.html:16 templates/mirrors-item.html:23
+#: templates/admin-mirrors-create.html:20 templates/downloads-mirrors.html:47
+#: templates/admin-mirrors-details.html:21
+msgid "Owner"
+msgstr ""
+
+#: templates/download-mirror-detail.html:24
+msgid "Number of files"
+msgstr ""
+
+#: templates/download-mirror-detail.html:32
+msgid "View list of all mirror servers."
+msgstr ""
+
+#: templates/news.html:7
+msgid "What is new on the IPFire project?"
+msgstr ""
+
+#: templates/news.html:34
+msgid "Stay up to date"
+msgstr ""
+
+#: templates/news.html:61 templates/planet/search.html:3
+#: templates/planet/year.html:3 templates/planet/user.html:3
+#: templates/planet/posting.html:3 templates/planet/index.html:3
+#: templates/planet/base.html:6 templates/index.html:154
+msgid "IPFire Planet"
+msgstr ""
+
+#: templates/news.html:85
+msgid "Latest news"
+msgstr ""
+
+#: templates/admin-planet-compose.html:5 templates/admin-planet.html:8
+msgid "Compose new entry"
+msgstr ""
+
+#: templates/admin-planet-compose.html:16 templates/admin-planet.html:14
+msgid "Title"
+msgstr ""
+
+#: templates/admin-planet-compose.html:33 templates/planet/posting.html:26
+msgid "Tags"
+msgstr ""
+
+#: templates/admin-planet-compose.html:44
+#: templates/admin-mirrors-details.html:17
+msgid "Status"
+msgstr ""
+
+#: templates/admin-planet-compose.html:48 templates/admin-planet.html:25
+msgid "Draft"
+msgstr ""
+
+#: templates/admin-planet-compose.html:52
+msgid "Published"
+msgstr ""
+
+#: templates/admin-planet-compose.html:58
+msgid "Save"
+msgstr ""
+
+#: templates/admin-planet-compose.html:59
+msgid "Preview"
+msgstr ""
+
+#: templates/admin-planet-compose.html:60
+msgid "Cancel"
+msgstr ""
+
+#: templates/mirrors-item.html:3
+#, python-format
+msgid "Mirror %s"
+msgstr ""
+
+#: templates/mirrors-item.html:8
+msgid "Up"
+msgstr ""
+
+#: templates/mirrors-item.html:10
+msgid "Down"
+msgstr ""
+
+#: templates/mirrors-item.html:12
+msgid "Out of sync"
+msgstr ""
+
+#: templates/mirrors-item.html:30 templates/admin-mirrors-create.html:24
+#: templates/downloads-mirrors.html:49 templates/admin-mirrors-details.html:25
+msgid "Location"
+msgstr ""
+
+#: templates/mirrors-item.html:36 templates/geoip/index.html:19
+msgid "Country"
+msgstr ""
+
+#: templates/mirrors-item.html:41 templates/geoip/index.html:29
+msgid "City"
+msgstr ""
+
+#: templates/mirrors-item.html:47
+msgid "Preferred for"
+msgstr ""
+
+#: templates/mirrors-item.html:54
+msgid "Estimated distance to you"
+msgstr ""
+
+#: templates/mirrors-item.html:61 templates/geoip/index.html:15
+msgid "Autonomous System"
+msgstr ""
+
+#: templates/mirrors-item.html:65
+msgid "IP Addresses"
+msgstr ""
+
+#: templates/mirrors-item.html:75
+msgid "Last updated"
+msgstr ""
+
+#: templates/mirrors-item.html:86
+msgid "Go to mirror"
+msgstr ""
+
+#: templates/mirrors-item.html:94
+msgid "The location of the mirror server is estimated by the IP address."
+msgstr ""
+
+#: templates/mirrors-item.html:98
+msgid "The location of this mirror server could not be estimated."
+msgstr ""
+
+#: templates/tracker-torrents.html:3
+msgid "Torrent Downloads"
+msgstr ""
+
+#: templates/tracker-torrents.html:7
+msgid "IPFire Torrent Tracker"
+msgstr ""
+
+#: templates/tracker-torrents.html:32 templates/downloads-older.html:25
+#: templates/downloads-index.html:35
+msgid "Release"
+msgstr ""
+
+#: templates/tracker-torrents.html:33
+msgid "Seeders"
+msgstr ""
+
+#: templates/tracker-torrents.html:34 templates/tracker-torrent-detail.html:23
+msgid "Peers"
+msgstr ""
+
+#: templates/downloads-older.html:3 templates/downloads-older.html:7
+msgid "Ancient downloads"
+msgstr ""
+
+#: templates/downloads-older.html:13
+msgid ""
+"Beware that these releases could lack possible security-fixes\tand so it is "
+"recommended to use the <em>latest</em> version."
+msgstr ""
+
+#: templates/downloads-older.html:26
+msgid "Published on"
+msgstr ""
+
+#: templates/admin-downloads-mirrors.html:5 templates/admin-downloads.html:5
+msgid "Download statistics"
+msgstr ""
+
+#: templates/admin-downloads-mirrors.html:7
+msgid "Mirror load from today"
+msgstr ""
+
+#: templates/admin-downloads-mirrors.html:10
+msgid "Mirror load"
+msgstr ""
+
+#: templates/admin-base.html:3
+msgid "IPFire Admin Area"
+msgstr ""
+
+#: templates/admin-base.html:6 templates/admin-downloads-base.html:8
+msgid "Options"
+msgstr ""
+
+#: templates/admin-base.html:9
+msgid "Accounts"
+msgstr ""
+
+#: templates/admin-base.html:10 templates/modules/menu.html:110
+msgid "Mirrors"
+msgstr ""
+
+#: templates/admin-base.html:11 templates/modules/menu.html:92
+msgid "Planet"
+msgstr ""
+
+#: templates/admin-base.html:12
+msgid "Downloads"
+msgstr ""
+
+#: templates/base-feature.html:6 templates/static/features.html:3
+#: templates/static/features.html:8 templates/static/features.html:1349
+#: templates/modules/menu.html:7
+msgid "About IPFire"
+msgstr ""
+
+#: templates/base-feature.html:9 templates/static/features.html:88
+#: templates/static/features.html:1354 templates/index.html:75
+msgid "Security"
+msgstr ""
+
+#: templates/base-feature.html:12 templates/static/features.html:139
+#: templates/static/features.html:1359
+msgid "Firewall"
+msgstr ""
+
+#: templates/base-feature.html:15 templates/static/features.html:1364
+msgid "Pakfire"
+msgstr ""
+
+#: templates/base-feature.html:18 templates/static/features.html:432
+#: templates/static/features.html:1369
+msgid "Updates"
+msgstr ""
+
+#: templates/base-feature.html:21
+msgid "It's free"
+msgstr ""
+
+#: templates/base-feature.html:25
+msgid "Features"
+msgstr ""
+
+#: templates/base-feature.html:28 templates/static/features.html:502
+#: templates/static/features.html:1374
+msgid "Dialup"
+msgstr ""
+
+#: templates/base-feature.html:31 templates/static/features.html:616
+msgid "Web proxy"
+msgstr ""
+
+#: templates/base-feature.html:35 templates/static/features.html:705
+msgid "Content filter"
+msgstr ""
+
+#: templates/base-feature.html:38 templates/static/features.html:766
+msgid "Update accelerator"
+msgstr ""
+
+#: templates/base-feature.html:41
+msgid "Virus scan"
+msgstr ""
+
+#: templates/base-feature.html:45 templates/static/features.html:818
+#: templates/static/features.html:1384
+msgid "VPN"
+msgstr ""
+
+#: templates/base-feature.html:49 templates/static/features.html:854
+msgid "IPsec"
+msgstr ""
+
+#: templates/base-feature.html:52 templates/static/features.html:915
+msgid "OpenVPN"
+msgstr ""
+
+#: templates/base-feature.html:56
+msgid "Intrusion detection"
+msgstr ""
+
+#: templates/base-feature.html:59 templates/static/features.html:1031
+#: templates/static/features.html:1394
+msgid "Quality of Service"
+msgstr ""
+
+#: templates/base-feature.html:68
+msgid "Wireless AP"
+msgstr ""
+
+#: templates/downloads-development.html:3
+#: templates/downloads-development.html:6
+msgid "Development Downloads"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:16
+msgid "Path"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:28
+#: templates/admin-mirrors-details.html:33
+msgid "File mirror"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:31
+#: templates/admin-mirrors-create.html:40
+#: templates/admin-mirrors-create.html:49
+#: templates/admin-mirrors-create.html:58
+msgid "yes"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:32
+#: templates/admin-mirrors-create.html:41
+#: templates/admin-mirrors-create.html:50
+#: templates/admin-mirrors-create.html:59
+msgid "no"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:37
+#: templates/admin-mirrors-details.html:37
+msgid "Pakfire 2 mirror"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:46
+#: templates/admin-mirrors-details.html:41
+msgid "Pakfire 3 mirror"
+msgstr ""
+
+#: templates/admin-mirrors-create.html:55
+#: templates/admin-mirrors-details.html:45
+msgid "Disabled?"
+msgstr ""
+
+#: templates/geoip/index.html:3 templates/geoip/index.html:7
+#, python-format
+msgid "GeoIP for %s"
+msgstr ""
+
+#: templates/geoip/index.html:33
+msgid "Postal Code"
+msgstr ""
+
+#: templates/geoip/index.html:46
+#, python-format
+msgid "No GeoIP information could be found for the IP address '%s'."
+msgstr ""
+
+#: templates/downloads-index.html:3
+msgid "Download Center"
+msgstr ""
+
+#: templates/downloads-index.html:7
+msgid "IPFire Download Center"
+msgstr ""
+
+#: templates/downloads-index.html:30
+msgid "Available releases"
+msgstr ""
+
+#: templates/downloads-index.html:36
+msgid "Release type"
+msgstr ""
+
+#: templates/downloads-index.html:37
+msgid "Release date"
+msgstr ""
+
+#: templates/downloads-index.html:48
+msgid "Stable"
+msgstr ""
+
+#: templates/downloads-index.html:50 templates/static/getinvolved.html:153
+#: templates/static/development.html:3 templates/static/development.html:8
+#: templates/modules/menu.html:65
+msgid "Development"
+msgstr ""
+
+#: templates/downloads-mirrors.html:63
+msgid "details"
+msgstr ""
+
+#: templates/admin-planet.html:5
+msgid "Planet Administrator"
+msgstr ""
+
+#: templates/admin-planet.html:13
+msgid "Author"
+msgstr ""
+
+#: templates/admin-planet.html:31
+msgid "Publish"
+msgstr ""
+
+#: templates/error.html:3
+msgid "Error"
+msgstr ""
+
+#: templates/admin-downloads-base.html:5
+msgid "Back to home"
+msgstr ""
+
+#: templates/admin-downloads-base.html:11
+msgid "Mirror stats"
+msgstr ""
+
+#: templates/static/getinvolved.html:3 templates/static/getinvolved.html:8
+msgid "Get involved"
+msgstr ""
+
+#: templates/static/getinvolved.html:10
+msgid "Because making a difference is easy"
+msgstr ""
+
+#: templates/static/getinvolved.html:47
+msgid "First steps"
+msgstr ""
+
+#: templates/static/getinvolved.html:97
+msgid "Donations"
+msgstr ""
+
+#: templates/static/getinvolved.html:120 templates/static/donation.html:3
+#: templates/static/donation.html:8 templates/modules/menu.html:47
+#: templates/wishlist/donate.html:3 templates/wishlist/modules/wish.html:26
+#: templates/download-splash.html:37
+msgid "Donate"
+msgstr ""
+
+#: templates/static/getinvolved.html:126 templates/modules/menu.html:53
+msgid "Wishlist"
+msgstr ""
+
+#: templates/static/getinvolved.html:142
+msgid "Make a wish"
+msgstr ""
+
+#: templates/static/getinvolved.html:149
+msgid "Contribute yourself"
+msgstr ""
+
+#: templates/static/getinvolved.html:175
+msgid "Translation"
+msgstr ""
+
+#: templates/static/getinvolved.html:190
+msgid "Translation team"
+msgstr ""
+
+#: templates/static/getinvolved.html:196
+msgid "Promotion"
+msgstr ""
+
+#: templates/static/features.html:10
+msgid "Because IPFire is more than just a firewall"
+msgstr ""
+
+#: templates/static/features.html:22
+msgid "IPFire"
+msgstr ""
+
+#: templates/static/features.html:22
+msgid "An Open Source Firewall Distribution"
+msgstr ""
+
+#: templates/static/features.html:315
+msgid "The IPFire package management system"
+msgstr ""
+
+#: templates/static/features.html:791
+msgid "Transparent virus scanner"
+msgstr ""
+
+#: templates/static/features.html:818
+msgid "Virtual Private Networks"
+msgstr ""
+
+#: templates/static/features.html:974
+msgid "Intrusion detection system"
+msgstr ""
+
+#: templates/static/features.html:1311 templates/static/features.html:1409
+msgid "Wireless Access Point"
+msgstr ""
+
+#: templates/static/features.html:1379
+msgid "Web Proxy"
+msgstr ""
+
+#: templates/static/features.html:1389
+msgid "Intrusion Detection"
+msgstr ""
+
+#: templates/static/artwork.html:3 templates/static/artwork.html:8
+#: templates/modules/menu.html:116
+msgid "Artwork"
+msgstr ""
+
+#: templates/static/artwork.html:36
+msgid "The IPFire Logo"
+msgstr ""
+
+#: templates/static/artwork.html:50
+msgid "Flyers, Rollups, CDs and more"
+msgstr ""
+
+#: templates/static/development.html:37 templates/static/development.html:258
+msgid "Development tools"
+msgstr ""
+
+#: templates/static/development.html:55 templates/modules/menu.html:82
+msgid "Bugtracker"
+msgstr ""
+
+#: templates/static/development.html:77
+msgid "Development Mailing List"
+msgstr ""
+
+#: templates/static/development.html:96
+msgid "Source code"
+msgstr ""
+
+#: templates/static/development.html:99
+msgid "Git"
+msgstr ""
+
+#: templates/static/development.html:118
+msgid "IPFire Git repositories"
+msgstr ""
+
+#: templates/static/development.html:124
+msgid "GitHub"
+msgstr ""
+
+#: templates/static/development.html:143
+msgid "ipfire on GitHub"
+msgstr ""
+
+#: templates/static/development.html:150 templates/static/development.html:268
+msgid "How to build IPFire?"
+msgstr ""
+
+#: templates/static/development.html:186
+msgid "How to submit patches?"
+msgstr ""
+
+#: templates/static/development.html:214
+msgid "How to translate IPFire?"
+msgstr ""
+
+#: templates/static/press.html:3 templates/static/press.html:7
+#: templates/base.html:69
+msgid "Press"
+msgstr ""
+
+#: templates/static/press.html:31 templates/static/imprint.html:29
+#: templates/static/imprint.html:41 templates/static/imprint.html:53
+#: templates/static/imprint.html:65 templates/planet/user.html:48
+msgid "Mail"
+msgstr ""
+
+#: templates/static/press.html:35
+msgid "Logo"
+msgstr ""
+
+#: templates/static/imprint.html:3 templates/static/imprint.html:8
+#: templates/base.html:73
msgid "Imprint"
msgstr ""
-#: templates/admin-mirrors.html:5
-msgid "Mirror Administrator"
+#: templates/static/chat.html:3 templates/static/chat.html:8
+#: templates/modules/menu.html:39
+msgid "Chat"
msgstr ""
-#: templates/admin-mirrors.html:9
-msgid "Re-check now"
+#: templates/static/chat.html:33
+msgid "Server"
msgstr ""
-#: templates/admin-mirrors.html:23 templates/admin-mirrors-details.html:5
-msgid "Details"
+#: templates/static/chat.html:36
+msgid "Channel"
msgstr ""
-#: templates/admin-mirrors.html:25 templates/admin-accounts.html:21
-msgid "Delete"
+#: templates/static/chat.html:41
+msgid "Use the web client"
msgstr ""
-#: templates/tracker-torrents.html:3
-msgid "Torrent Downloads"
+#: templates/static/donation.html:10
+msgid "We need your help!"
msgstr ""
-#: templates/tracker-torrents.html:7
-msgid "IPFire Torrent Tracker"
+#: templates/static/donation.html:68
+msgid "Did you know...?"
msgstr ""
-#: templates/tracker-torrents.html:33
-msgid "Seeders"
+#: templates/static/donation.html:84
+msgid "How do we use financial support?"
msgstr ""
-#: templates/error.html:3
-msgid "Error"
+#: templates/static/donation.html:132
+msgid "Research & Development"
+msgstr ""
+
+#: templates/static/cebit.html:3
+msgid "CeBIT special"
+msgstr ""
+
+#: templates/static/cebit.html:8
+msgid "IPFire at CeBIT 2010"
+msgstr ""
+
+#: templates/admin-accounts.html:8
+msgid "Create new account"
+msgstr ""
+
+#: templates/admin-accounts.html:13
+msgid "Name (Nickname)"
+msgstr ""
+
+#: templates/modules/sidebar-release.html:4
+#: templates/modules/release-item.html:2 templates/index.html:24
+msgid "Latest release"
+msgstr ""
+
+#: templates/modules/sidebar-release.html:9
+msgid "Download now"
+msgstr ""
+
+#: templates/modules/release-item-short.html:4
+msgid "Here you will find the downloads for the version"
+msgstr ""
+
+#: templates/modules/release-item-short.html:13
+#: templates/modules/release-item.html:123
+msgid "There are no downloads available for this release."
+msgstr ""
+
+#: templates/modules/download-button.html:2
+#, python-format
+msgid "Download %s"
+msgstr ""
+
+#: templates/modules/map.html:5
+msgid "View larger map"
+msgstr ""
+
+#: templates/modules/ads/download-splash.html:4
+msgid "Advertisement"
+msgstr ""
+
+#: templates/modules/ads/download-splash.html:5
+msgid "This download is sponsored by:"
+msgstr ""
+
+#: templates/modules/news-preview.html:6
+msgid "by"
+msgstr ""
+
+#: templates/modules/mirrors-table.html:37
+#, python-format
+msgid "Last update: %s"
+msgstr ""
+
+#: templates/modules/news-year-nav.html:3
+msgid "Jump to"
+msgstr ""
+
+#: templates/modules/news-year-nav.html:6
+msgid "Most recent"
+msgstr ""
+
+#: templates/modules/stasy-table-devices.html:6
+msgid "Kernel module"
msgstr ""
#: templates/modules/donation-box.html:4
msgid "Bank code"
msgstr ""
-#: templates/modules/release-item.html:2
-#: templates/modules/sidebar-release.html:4 templates/index.html:24
-msgid "Latest release"
+#: templates/modules/planet-entry.html:14 templates/planet/posting.html:31
+msgid "Posted by"
+msgstr ""
+
+#: templates/modules/planet-entry.html:15 templates/planet/posting.html:32
+msgid "on"
+msgstr ""
+
+#: templates/modules/news-item.html:6
+msgid "Announcement"
msgstr ""
#: templates/modules/release-item.html:10
msgid "Legend:"
msgstr ""
-#: templates/modules/release-item.html:123
-#: templates/modules/release-item-short.html:13
-msgid "There are no downloads available for this release."
-msgstr ""
-
-#: templates/modules/sidebar-release.html:9
-msgid "Download now"
-msgstr ""
-
-#: templates/modules/release-item-short.html:4
-msgid "Here you will find the downloads for the version"
-msgstr ""
-
-#: templates/modules/news-preview.html:6
-msgid "by"
-msgstr ""
-
-#: templates/modules/download-button.html:2
-#, python-format
-msgid "Download %s"
-msgstr ""
-
-#: templates/modules/stasy-table-devices.html:6
-msgid "Kernel module"
-msgstr ""
-
-#: templates/modules/news-year-nav.html:3
-msgid "Jump to"
-msgstr ""
-
-#: templates/modules/news-year-nav.html:6
-msgid "Most recent"
-msgstr ""
-
-#: templates/modules/ads/download-splash.html:4
-msgid "Advertisement"
+#: templates/modules/release-item.html:114
+#: templates/tracker-torrent-detail.html:15
+msgid "Magnet link"
msgstr ""
-#: templates/modules/ads/download-splash.html:5
-msgid "This download is sponsored by:"
+#: templates/modules/release-item.html:115
+#: templates/tracker-torrent-detail.html:3
+#: templates/tracker-torrent-detail.html:18
+msgid "Torrent download"
msgstr ""
#: templates/modules/menu.html:4
msgid "Forum"
msgstr ""
-#: templates/modules/menu.html:39 templates/static/chat.html:3
-#: templates/static/chat.html:8
-msgid "Chat"
-msgstr ""
-
-#: templates/modules/menu.html:53 templates/static/getinvolved.html:126
-msgid "Wishlist"
-msgstr ""
-
#: templates/modules/menu.html:61
msgid "More"
msgstr ""
msgid "Pakfire Build Service"
msgstr ""
-#: templates/modules/menu.html:82 templates/static/development.html:55
-msgid "Bugtracker"
-msgstr ""
-
#: templates/modules/menu.html:87
msgid "Miscellaneous"
msgstr ""
msgid "Mailing lists"
msgstr ""
-#: templates/modules/menu.html:116 templates/static/artwork.html:3
-#: templates/static/artwork.html:8
-msgid "Artwork"
-msgstr ""
-
#: templates/modules/menu.html:122
msgid "CeBIT"
msgstr ""
msgid "Professional support available!"
msgstr ""
-#: templates/modules/news-item.html:6
-msgid "Announcement"
-msgstr ""
-
-#: templates/static/press.html:35
-msgid "Logo"
-msgstr ""
-
-#: templates/static/features.html:10
-msgid "Because IPFire is more than just a firewall"
-msgstr ""
-
-#: templates/static/features.html:22
-msgid "IPFire"
+#: templates/admin-login.html:3
+msgid "Please login"
msgstr ""
-#: templates/static/features.html:22
-msgid "An Open Source Firewall Distribution"
+#: templates/planet/search.html:6
+#, python-format
+msgid "Search results for '%s'"
msgstr ""
-#: templates/static/features.html:315
-msgid "The IPFire package management system"
+#: templates/planet/search.html:16
+#, python-format
+msgid "No results found for '%s'"
msgstr ""
-#: templates/static/features.html:791
-msgid "Transparent virus scanner"
+#: templates/planet/year.html:6
+#, python-format
+msgid "Year %s"
msgstr ""
-#: templates/static/features.html:818
-msgid "Virtual Private Networks"
+#: templates/planet/user.html:22 templates/planet/index.html:45
+msgid "Older posts"
msgstr ""
-#: templates/static/features.html:974
-msgid "Intrusion detection system"
+#: templates/planet/user.html:26 templates/planet/index.html:49
+msgid "Newer posts"
msgstr ""
-#: templates/static/features.html:1311 templates/static/features.html:1409
-msgid "Wireless Access Point"
+#: templates/planet/user.html:33
+#, python-format
+msgid "%s did not write any posts, yet."
msgstr ""
-#: templates/static/features.html:1379
-msgid "Web Proxy"
+#: templates/planet/posting.html:17
+msgid "Heads up!"
msgstr ""
-#: templates/static/features.html:1389
-msgid "Intrusion Detection"
+#: templates/planet/posting.html:17
+msgid "This post is a draft and has not been published, yet."
msgstr ""
-#: templates/static/development.html:37 templates/static/development.html:258
-msgid "Development tools"
+#: templates/planet/index.html:24
+msgid "All posts from"
msgstr ""
-#: templates/static/development.html:77
-msgid "Development Mailing List"
+#: templates/planet/base.html:9
+msgid "The official blog of the IPFire team"
msgstr ""
-#: templates/static/development.html:96
-msgid "Source code"
+#: templates/admin-downloads.html:7
+msgid "Download counters"
msgstr ""
-#: templates/static/development.html:99
-msgid "Git"
+#: templates/admin-downloads.html:10
+msgid "Today"
msgstr ""
-#: templates/static/development.html:118
-msgid "IPFire Git repositories"
+#: templates/admin-downloads.html:14
+msgid "Yesterday"
msgstr ""
-#: templates/static/development.html:124
-msgid "GitHub"
+#: templates/admin-downloads.html:18
+msgid "Total"
msgstr ""
-#: templates/static/development.html:143
-msgid "ipfire on GitHub"
+#: templates/admin-downloads.html:23
+msgid "Downloads by country"
msgstr ""
-#: templates/static/development.html:150 templates/static/development.html:268
-msgid "How to build IPFire?"
+#: templates/tracker-torrent-detail.html:28
+msgid "Seeds"
msgstr ""
-#: templates/static/development.html:186
-msgid "How to submit patches?"
+#: templates/wishlist/closed.html:3 templates/wishlist/closed.html:13
+msgid "Closed wishes"
msgstr ""
-#: templates/static/development.html:214
-msgid "How to translate IPFire?"
+#: templates/wishlist/closed.html:9
+msgid "Wishes open for donation"
msgstr ""
-#: templates/static/chat.html:33
-msgid "Server"
+#: templates/wishlist/closed.html:36 templates/wishlist/closed.html:40
+msgid "Older"
msgstr ""
-#: templates/static/chat.html:36
-msgid "Channel"
+#: templates/wishlist/closed.html:46 templates/wishlist/closed.html:50
+msgid "Newer"
msgstr ""
-#: templates/static/chat.html:41
-msgid "Use the web client"
+#: templates/wishlist/donate.html:13 templates/wishlist/donate.html:23
+#: templates/wishlist/terms.html:3 templates/wishlist/terms.html:7
+#: templates/base.html:78
+msgid "Terms & Conditions"
msgstr ""
-#: templates/static/cebit.html:3
-msgid "CeBIT special"
+#: templates/wishlist/modules/wish.html:6
+msgid "Only a few days left!"
msgstr ""
-#: templates/static/cebit.html:8
-msgid "IPFire at CeBIT 2010"
+#: templates/wishlist/modules/wish.html:36
+msgid "funded"
msgstr ""
-#: templates/static/getinvolved.html:3 templates/static/getinvolved.html:8
-msgid "Get involved"
+#: templates/wishlist/modules/wish.html:40
+#: templates/wishlist/modules/wish.html:50
+#, python-format
+msgid "%s €"
msgstr ""
-#: templates/static/getinvolved.html:10
-msgid "Because making a difference is easy"
+#: templates/wishlist/modules/wish.html:41
+msgid "donated"
msgstr ""
-#: templates/static/getinvolved.html:47
-msgid "First steps"
-msgstr ""
+#: templates/wishlist/modules/wish.html:48
+msgid "day to go"
+msgid_plural "days to go"
+msgstr[0] ""
+msgstr[1] ""
-#: templates/static/getinvolved.html:97
-msgid "Donations"
+#: templates/wishlist/modules/wish.html:51
+msgid "to go"
msgstr ""
-#: templates/static/getinvolved.html:142
-msgid "Make a wish"
+#: templates/wishlist/modules/wish.html:54
+msgid "In progress"
msgstr ""
-#: templates/static/getinvolved.html:149
-msgid "Contribute yourself"
+#: templates/wishlist/modules/wish.html:56
+msgid "Finished"
msgstr ""
-#: templates/static/getinvolved.html:175
-msgid "Translation"
+#: templates/wishlist/modules/wish.html:58
+msgid "Funding ended"
msgstr ""
-#: templates/static/getinvolved.html:190
-msgid "Translation team"
+#: templates/wishlist/modules/wish.html:68
+msgid "Share this wish with your friends and help us promote it!"
msgstr ""
-#: templates/static/getinvolved.html:196
-msgid "Promotion"
+#: templates/wishlist/index.html:3 templates/index.html:3
+msgid "Home"
msgstr ""
-#: templates/static/artwork.html:36
-msgid "The IPFire Logo"
+#: templates/wishlist/wish.html:3
+msgid "Wish"
msgstr ""
-#: templates/static/artwork.html:50
-msgid "Flyers, Rollups, CDs and more"
+#: templates/wishlist/wish.html:18
+#, python-format
+msgid "Launched: %s"
msgstr ""
-#: templates/static/donation.html:10
-msgid "We need your help!"
+#: templates/wishlist/wish.html:24
+#, python-format
+msgid "Funding ends: %s"
msgstr ""
-#: templates/static/donation.html:68
-msgid "Did you know...?"
+#: templates/wishlist/wish.html:26
+msgid "This funding runs until the goal is reached."
msgstr ""
-#: templates/static/donation.html:84
-msgid "How do we use financial support?"
+#: templates/wishlist/base.html:6 templates/index.html:175
+msgid "IPFire Wishlist"
msgstr ""
-#: templates/static/donation.html:132
-msgid "Research & Development"
+#: templates/wishlist/base.html:8
+msgid "Crowd funding for the IPFire project"
msgstr ""
#: templates/index.html:92
msgid "All mirrors"
msgstr ""
-#: templates/admin-mirrors-details.html:17
-msgid "Status"
-msgstr ""
-
#: templates/admin-mirrors-details.html:29
msgid "GeoIP Location"
msgstr ""
msgid "Filelist"
msgstr ""
-#: templates/admin-accounts.html:8
-msgid "Create new account"
+#: templates/base.html:4
+msgid "No title given"
msgstr ""
-#: templates/admin-accounts.html:13
-msgid "Name (Nickname)"
+#: templates/base.html:63
+msgid "IPFire is free software"
+msgstr ""
+
+#: templates/download-splash.html:3 templates/download-splash.html:7
+msgid "Thanks for downloading IPFire!"
+msgstr ""
+
+#: templates/download-splash.html:61
+msgid "Next steps"
+msgstr ""
+
+#: templates/download-splash.html:66
+msgid "Install IPFire"
msgstr ""
-#: templates/mirrors.html:25
-msgid "Mirror servers nearby"
+#: templates/download-splash.html:82
+msgid "Access documentation"
msgstr ""
-#: templates/mirrors.html:28 templates/mirrors.html:31
-msgid "Worldwide mirror servers"
+#: templates/download-splash.html:100
+msgid "Join the community"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Monday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Tuesday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Wednesday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:229
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:239
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:239
msgid "Thursday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:230
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:240
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:240
msgid "Friday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:230
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:240
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:240
msgid "Saturday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:230
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:240
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:240
msgid "Sunday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:274
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:290
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:290
#, python-format
msgid "1 second ago"
msgid_plural "%(seconds)d seconds ago"
msgstr[0] ""
msgstr[1] ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:279
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:295
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:295
#, python-format
msgid "1 minute ago"
msgid_plural "%(minutes)d minutes ago"
msgstr[0] ""
msgstr[1] ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:283
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:299
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:299
#, python-format
msgid "1 hour ago"
msgid_plural "%(hours)d hours ago"
msgstr[0] ""
msgstr[1] ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:287
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:303
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:303
#, python-format
msgid "%(time)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:290
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:306
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:306
msgid "yesterday"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:291
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:307
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:307
#, python-format
msgid "yesterday at %(time)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:293
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:309
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:309
#, python-format
msgid "%(weekday)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:294
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:310
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:310
#, python-format
msgid "%(weekday)s at %(time)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:296
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:338
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:312
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:354
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:312
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:354
#, python-format
msgid "%(month_name)s %(day)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:297
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:313
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:313
#, python-format
msgid "%(month_name)s %(day)s at %(time)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:300
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:316
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:316
#, python-format
msgid "%(month_name)s %(day)s, %(year)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:301
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:317
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:317
#, python-format
msgid "%(month_name)s %(day)s, %(year)s at %(time)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:332
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:348
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:348
#, python-format
msgid "%(weekday)s, %(month_name)s %(day)s"
msgstr ""
-#: /usr/lib/python2.7/site-packages/tornado/locale.py:353
+#: /usr/lib/python2.7/site-packages/tornado/locale.py:369
+#: /usr/lib/python3.3/site-packages/tornado/locale.py:369
#, python-format
msgid "%(commas)s and %(last)s"
msgstr ""
--- /dev/null
+[global]
+
+[database]
+server = pgsql-master.ipfire.org
+database = webapp
+username = webapp
+password = ...
from webapp import Application
if __name__ == "__main__":
- app = Application()
+ app = Application(configfile="webapp.conf")
context = daemon.DaemonContext(
working_directory=os.getcwd(),
tornado.locale.load_gettext_translations(os.path.join(BASEDIR, "translations"), "webapp")
class Application(tornado.web.Application):
- def __init__(self):
+ def __init__(self, **kwargs):
self.__backend = None
settings = dict(
"format_month_name" : self.format_month_name,
},
ui_modules = {
- "Advertisement" : AdvertisementModule,
- "DonationBox" : DonationBoxModule,
- "DownloadButton" : DownloadButtonModule,
- "Menu" : MenuModule,
- "MirrorItem" : MirrorItemModule,
- "MirrorsTable" : MirrorsTableModule,
- "NewsItem" : NewsItemModule,
- "NewsLine" : NewsLineModule,
- "NewsTable" : NewsTableModule,
- "NewsYearNavigation": NewsYearNavigationModule,
- "PlanetEntry" : PlanetEntryModule,
- "ReleaseItem" : ReleaseItemModule,
- "SidebarBanner" : SidebarBannerModule,
- "SidebarRelease" : SidebarReleaseModule,
- "StasyTable" : StasyTableModule,
- "StasyCPUCoreTable" : StasyCPUCoreTableModule,
- "StasyDeviceTable" : StasyDeviceTableModule,
- "StasyGeoTable" : StasyGeoTableModule,
- "TrackerPeerList": TrackerPeerListModule,
- "Wish" : WishModule,
- "Wishlist" : WishlistModule,
+ "Advertisement" : AdvertisementModule,
+ "DonationBox" : DonationBoxModule,
+ "DownloadButton" : DownloadButtonModule,
+ "Map" : MapModule,
+ "Menu" : MenuModule,
+ "MirrorItem" : MirrorItemModule,
+ "MirrorsTable" : MirrorsTableModule,
+ "NetBootMenuConfig" : NetBootMenuConfigModule,
+ "NetBootMenuHeader" : NetBootMenuHeaderModule,
+ "NetBootMenuSeparator" : NetBootMenuSeparatorModule,
+ "NewsItem" : NewsItemModule,
+ "NewsLine" : NewsLineModule,
+ "NewsTable" : NewsTableModule,
+ "NewsYearNavigation" : NewsYearNavigationModule,
+ "PlanetEntry" : PlanetEntryModule,
+ "ReleaseItem" : ReleaseItemModule,
+ "SidebarBanner" : SidebarBannerModule,
+ "SidebarRelease" : SidebarReleaseModule,
+ "StasyTable" : StasyTableModule,
+ "StasyCPUCoreTable" : StasyCPUCoreTableModule,
+ "StasyDeviceTable" : StasyDeviceTableModule,
+ "StasyGeoTable" : StasyGeoTableModule,
+ "TrackerPeerList" : TrackerPeerListModule,
+ "Wish" : WishModule,
+ "Wishlist" : WishlistModule,
},
xsrf_cookies = True,
)
+ settings.update(kwargs)
tornado.web.Application.__init__(self, **settings)
self.add_handlers(r"downloads?\.ipfire\.org", [
(r"/", DownloadsIndexHandler),
(r"/latest", DownloadsLatestHandler),
- (r"/release/([0-9]+)", DownloadsReleaseHandler),
+ (r"/release/(\d)", DownloadsReleaseHandler),
+ (r"/release/([\w\.\-]*)", DownloadsReleaseHandler),
(r"/older", DownloadsOlderHandler),
(r"/development", DownloadsDevelopmentHandler),
(r"/mirrors", tornado.web.RedirectHandler, { "url" : "http://mirrors.ipfire.org/" }),
# mirrors.ipfire.org
self.add_handlers(r"mirrors\.ipfire\.org", [
(r"/", MirrorIndexHandler),
- (r"/mirror/([0-9]+)", MirrorItemHandler),
+ (r"/mirror/(.*)", MirrorItemHandler),
(r"/lists/pakfire2", MirrorListPakfire2Handler),
] + static_handlers)
(r"/terms", WishlistTermsHandler),
] + static_handlers)
+ # geoip.ipfire.org
+ self.add_handlers(r"geoip\.ipfire\.org", [
+ (r"/", GeoIPHandler),
+ ] + static_handlers)
+
# admin.ipfire.org
self.add_handlers(r"admin\.ipfire\.org", [
(r"/", AdminIndexHandler),
@property
def backend(self):
if self.__backend is None:
- self.__backend = backend.Backend()
+ configfile = self.settings.get("configfile", None)
+ if not configfile:
+ raise RuntimeException("Could not find configuration file")
+
+ self.__backend = backend.Backend(configfile=configfile)
return self.__backend
parse_command_line()
from base import Backend
-
-from ads import Advertisements
-from accounts import Accounts
-from banners import Banners
-from geoip import GeoIP
-from iuse import IUse
-from memcached import Memcached
-from mirrors import Downloads, Mirrors
-from netboot import NetBoot
-from news import News
-from planet import Planet, PlanetEntry
-from releases import Releases
-from settings import Settings as Config
-from stasy import Stasy
-from tracker import Tracker
-from wishlist import Wishlist
import urllib
from misc import Object
-from settings import Settings
class Accounts(Object):
- @property
- def settings(self):
- return Settings()
-
def __init__(self, backend):
Object.__init__(self, backend)
self.__db = None
@property
def search_base(self):
- return Settings().get("ldap_search_base")
+ return self.settings.get("ldap_search_base")
@property
def db(self):
bind_dn = self.settings.get("ldap_bind_dn")
if bind_dn:
- bind_pw = self.settings.get("ldap_bind_pw")
+ bind_pw = self.settings.get("ldap_bind_pw", "")
self.__db.simple_bind(bind_dn, bind_pw)
import datetime
import textile
-from databases import Databases
-from misc import Singleton
-
-class Advertisements(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
+from misc import Object
+class Advertisements(Object):
def get(self, where=None):
- args = []
query = "SELECT * FROM advertisements \
- WHERE DATE(NOW()) >= date_start AND DATE(NOW()) <= date_end AND published = 'Y'"
+ WHERE NOW() BETWEEN date_start AND date_end AND published = %s"
+ args = [True]
if where:
- query += " AND `where` = %s"
+ query += " AND location = %s"
args.append(where)
- query += " ORDER BY RAND() LIMIT 1"
+ query += " ORDER BY RANDOM() LIMIT 1"
ad = self.db.get(query, *args)
if ad:
- return Advert(self, ad.id, ad)
+ return Advert(self.backend, ad.id, ad)
-class Advert(object):
- def __init__(self, advertisements, id, data=None):
- self.advertisements = advertisements
- self.id = id
+class Advert(Object):
+ def __init__(self, backend, id, data=None):
+ Object.__init__(self, backend)
+ self.id = id
self.__data = data
- @property
- def db(self):
- return self.advertisements.db
-
@property
def data(self):
if self.__data is None:
+++ /dev/null
-#!/usr/bin/python
-
-from databases import Databases
-from misc import Singleton
-
-class Banners(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
-
- def list(self):
- return self.db.query("SELECT * FROM banners")
-
- def get_random(self):
- return self.db.get("SELECT * FROM banners ORDER BY RAND() LIMIT 1")
-
-
-if __name__ == "__main__":
- b = Banners()
-
- print b.list()
-
- print "--- RANDOM ---"
-
- for i in range(5):
- print i, b.get_random()
#!/usr/bin/python
-import tornado.database
+import ConfigParser as configparser
import accounts
+import ads
+import database
+import geoip
+import iuse
+import memcached
+import mirrors
+import netboot
+import news
import planet
-
-MYSQL_SERVER = "mysql-master.ipfire.org"
-MYSQL_DB = "webapp"
-MYSQL_USER = "webapp"
+import releases
+import settings
+import stasy
+import tracker
+import wishlist
class Backend(object):
- def __init__(self):
- self.db = tornado.database.Connection(MYSQL_SERVER, MYSQL_DB, user=MYSQL_USER)
+ def __init__(self, configfile):
+ # Read configuration file.
+ self.config = self.read_config(configfile)
+
+ # Setup database.
+ self.setup_database()
+ # Initialize settings first.
+ self.settings = settings.Settings(self)
+ self.memcache = memcached.Memcached(self)
+
+ # Initialize backend modules.
self.accounts = accounts.Accounts(self)
+ self.advertisements = ads.Advertisements(self)
+ self.downloads = mirrors.Downloads(self)
+ self.geoip = geoip.GeoIP(self)
+ self.iuse = iuse.IUse(self)
+ self.mirrors = mirrors.Mirrors(self)
+ self.netboot = netboot.NetBoot(self)
+ self.news = news.News(self)
self.planet = planet.Planet(self)
+ self.releases = releases.Releases(self)
+ self.stasy = stasy.Stasy(self)
+ self.tracker = tracker.Tracker(self)
+ self.wishlist = wishlist.Wishlist(self)
+
+ def read_config(self, configfile):
+ cp = configparser.ConfigParser()
+ cp.read(configfile)
+
+ return cp
+
+ def setup_database(self):
+ """
+ Sets up the database connection.
+ """
+ credentials = {
+ "host" : self.config.get("database", "server"),
+ "database" : self.config.get("database", "database"),
+ "user" : self.config.get("database", "username"),
+ "password" : self.config.get("database", "password"),
+ }
+
+ self.db = database.Connection(**credentials)
--- /dev/null
+#!/usr/bin/python
+# encoding: utf-8
+
+_ = lambda x: x
+
+country_list = {
+ "AD" : _("Andorra"),
+ "AE" : _("United Arab Emirates"),
+ "AF" : _("Afghanistan"),
+ "AG" : _("Antigua and Barbuda"),
+ "AI" : _("Aanguilla"),
+ "AL" : _("Albania"),
+ "AM" : _("Armenia"),
+ "AO" : _("Angola"),
+ "AQ" : _("Antarctica"),
+ "AR" : _("Argentina"),
+ "AS" : _("American Samoa"),
+ "AT" : _("Austria"),
+ "AU" : _("Australia"),
+ "AW" : _("Aruba"),
+ "AX" : _("Ã…land Islands"),
+ "AZ" : _("Azerbaijan"),
+ "BA" : _("Bosnia and Herzegovina"),
+ "BB" : _("Barbados"),
+ "BD" : _("Bangladesh"),
+ "BE" : _("Belgium"),
+ "BF" : _("Burkina Faso"),
+ "BG" : _("Bulgaria"),
+ "BH" : _("Bahrain"),
+ "BI" : _("Burundi"),
+ "BJ" : _("Benin"),
+ "BL" : _("Saint Barthélemy"),
+ "BM" : _("Bermuda"),
+ "BN" : _("Brunei Darussalam"),
+ "BO" : _("Plurinational State of Bolivia"),
+ "BQ" : _("Sint Eustatius and Saba Bonaire"),
+ "BR" : _("Brazil"),
+ "BS" : _("Bahamas"),
+ "BT" : _("Bhutan"),
+ "BV" : _("Bouvet Island"),
+ "BW" : _("Botswana"),
+ "BY" : _("Belarus"),
+ "BZ" : _("Belize"),
+ "CA" : _("Canada"),
+ "CC" : _("Cocos (Keeling) Islands"),
+ "CD" : _("The Democratic Republic of the Congo"),
+ "CF" : _("Central African Republic"),
+ "CG" : _("Congo"),
+ "CH" : _("Switzerland"),
+ "CI" : _("Côte d'Ivoire"),
+ "CK" : _("Cook Islands"),
+ "CL" : _("Chile"),
+ "CM" : _("Cameroon"),
+ "CN" : _("China"),
+ "CO" : _("Colombia"),
+ "CR" : _("Costa Rica"),
+ "CU" : _("Cuba"),
+ "CV" : _("Cape Verde"),
+ "CW" : _("Curaçao"),
+ "CX" : _("Chrismas Islands"),
+ "CY" : _("Cyprus"),
+ "CZ" : _("Czech Republic"),
+ "DE" : _("Germany"),
+ "DJ" : _("Djibouti"),
+ "DK" : _("Denmark"),
+ "DM" : _("Dominica"),
+ "DO" : _("Dominican Republic"),
+ "DZ" : _("Algeria"),
+ "EC" : _("Ecuador"),
+ "EE" : _("Estonia"),
+ "EG" : _("Egypt"),
+ "EH" : _("Western Sahara"),
+ "ER" : _("Eritrea"),
+ "ES" : _("Spain"),
+ "ET" : _("Ethiopia"),
+ "FI" : _("Finland"),
+ "FJ" : _("Fiji"),
+ "FK" : _("Falkland Islands (Malvinas)"),
+ "FM" : _("Federated States of Micronesia"),
+ "FO" : _("Faroe Islands"),
+ "FR" : _("France"),
+ "GA" : _("Gabon"),
+ "GB" : _("United Kingdom"),
+ "GD" : _("Grenada"),
+ "GE" : _("Georgia"),
+ "GF" : _("French Guiana"),
+ "GG" : _("Guersey"),
+ "GH" : _("Ghana"),
+ "GI" : _("Gibraltar"),
+ "GL" : _("Greenland"),
+ "GM" : _("Gambia"),
+ "GN" : _("Guinea"),
+ "GP" : _("Guadeloupe"),
+ "GQ" : _("Equatorial Guinea"),
+ "GR" : _("Greece"),
+ "GS" : _("South Georgia and the South Sandwich Islands"),
+ "GT" : _("Guatemala"),
+ "GU" : _("Guam"),
+ "GW" : _("Guinea-Bissau"),
+ "GY" : _("Guyana"),
+ "HK" : _("Hong Kong"),
+ "HM" : _("Heard Island and McDonald Islands"),
+ "HN" : _("Honduras"),
+ "HR" : _("Croatia"),
+ "HT" : _("Haiti"),
+ "HU" : _("Hungary"),
+ "ID" : _("Indonesia"),
+ "IE" : _("Ireland"),
+ "IL" : _("Israel"),
+ "IM" : _("Isle of Man"),
+ "IN" : _("India"),
+ "IO" : _("British Indian Ocean Territory"),
+ "IQ" : _("Iraq"),
+ "IR" : _("Islamic Republic of Iran"),
+ "IS" : _("Iceland"),
+ "IT" : _("Italy"),
+ "JE" : _("Jersey"),
+ "JM" : _("Jamaica"),
+ "JO" : _("Jordan"),
+ "JP" : _("Japan"),
+ "KE" : _("Kenya"),
+ "KG" : _("Kyrgyzstan"),
+ "KH" : _("Cambodia"),
+ "KI" : _("Kiribati"),
+ "KM" : _("Comoros"),
+ "KN" : _("Saint Kitts and Nevis"),
+ "KP" : _("Democratic People's Republic of Korea"),
+ "KR" : _("Republic of Korea"),
+ "KW" : _("Kuwait"),
+ "KY" : _("Cayman Islands"),
+ "KZ" : _("Kazakhstan"),
+ "LA" : _("Lao People's Democratic Public"),
+ "LB" : _("Lebanon"),
+ "LC" : _("Saint Lucia"),
+ "LI" : _("Liechtenstein"),
+ "LK" : _("Sri Lanka"),
+ "LR" : _("Liberia"),
+ "LS" : _("Lesotho"),
+ "LT" : _("Lithuania"),
+ "LU" : _("Luxembourg"),
+ "LV" : _("Latvia"),
+ "LY" : _("Libya"),
+ "MA" : _("Morocco"),
+ "MC" : _("Monaco"),
+ "MD" : _("Republic of Moldova"),
+ "ME" : _("Montenegro"),
+ "MF" : _("Saint Martin (French Part)"),
+ "MG" : _("Madagascar"),
+ "MH" : _("Marshall Islands"),
+ "MK" : _("The former Yugoslav Republic of Macedonia"),
+ "ML" : _("Mali"),
+ "MM" : _("Myanmar"),
+ "MN" : _("Mongolia"),
+ "MO" : _("Macao"),
+ "MP" : _("Northern Mariana Islands"),
+ "MQ" : _("Martinique"),
+ "MR" : _("Mauritania"),
+ "MS" : _("Montserrat"),
+ "MT" : _("Malta"),
+ "MU" : _("Mauritius"),
+ "MV" : _("Maldives"),
+ "MW" : _("Malawi"),
+ "MX" : _("Mexico"),
+ "MY" : _("Malaysia"),
+ "MZ" : _("Mozambique"),
+ "NA" : _("Namibia"),
+ "NC" : _("New Caledonia"),
+ "NE" : _("Niger"),
+ "NF" : _("Norfolk Island"),
+ "NG" : _("Nigeria"),
+ "NI" : _("Nicaragua"),
+ "NL" : _("Netherlands"),
+ "NO" : _("Norway"),
+ "NP" : _("Nepal"),
+ "NR" : _("Nauru"),
+ "NU" : _("Niue"),
+ "NZ" : _("New Zealand"),
+ "OM" : _("Oman"),
+ "PA" : _("Panama"),
+ "PE" : _("Peru"),
+ "PF" : _("French Polynesia"),
+ "PG" : _("Papua New Guinea"),
+ "PH" : _("Philipplines"),
+ "PK" : _("Pakistan"),
+ "PL" : _("Poland"),
+ "PM" : _("Saint Pierre and Miquelon"),
+ "PN" : _("Pitcairn"),
+ "PR" : _("Puerto Rico"),
+ "PS" : _("Palestinian Territory, occupied"),
+ "PT" : _("Portugal"),
+ "PW" : _("Palau"),
+ "PY" : _("Paraguay"),
+ "QA" : _("Qatar"),
+ "RE" : _("Réunion"),
+ "RO" : _("Romania"),
+ "RS" : _("Serbia"),
+ "RU" : _("Russian Federation"),
+ "RW" : _("Rwanda"),
+ "SA" : _("Saudi Arabia"),
+ "SB" : _("Solomon Islands"),
+ "SC" : _("Seychelles"),
+ "SD" : _("Sudan"),
+ "SE" : _("Sweden"),
+ "SG" : _("Singapore"),
+ "SH" : _("Saint Helena, Ascension and Tristan Da Cunha"),
+ "SI" : _("Slovenia"),
+ "SJ" : _("Svalbard and Jan Mayen"),
+ "SK" : _("Slovakia"),
+ "SL" : _("Sierra Leone"),
+ "SM" : _("San Marino"),
+ "SN" : _("Senegal"),
+ "SO" : _("Somalia"),
+ "SR" : _("Suriname"),
+ "SS" : _("South Sudan"),
+ "ST" : _("Sao Tome and Principe"),
+ "SV" : _("El Salvador"),
+ "SX" : _("Sint Maarten (Dutch Part)"),
+ "SY" : _("Syrian Arab Republic"),
+ "SZ" : _("Swaziland"),
+ "TC" : _("Turks and Caicos Islands"),
+ "TD" : _("Chad"),
+ "TF" : _("French Southern Territories"),
+ "TG" : _("Togo"),
+ "TH" : _("Thailand"),
+ "TJ" : _("Tajikistan"),
+ "TK" : _("Tokelau"),
+ "TL" : _("Timor-Leste"),
+ "TM" : _("Turkmenistan"),
+ "TN" : _("Tunisia"),
+ "TO" : _("Tonga"),
+ "TR" : _("Turkey"),
+ "TT" : _("Trinidad and Tobago"),
+ "TV" : _("Tuvalu"),
+ "TW" : _("Taiwan, Province of China"),
+ "TZ" : _("United Republic of Tanzania"),
+ "UA" : _("Ukraine"),
+ "UG" : _("Uganda"),
+ "UM" : _("Unites States minor outlying islands"),
+ "US" : _("Unites States"),
+ "UY" : _("Uruguay"),
+ "UZ" : _("Uzbekistan"),
+ "VA" : _("Vatican City State"),
+ "VC" : _("Saint Vincent and the Grenadines"),
+ "VE" : _("Bolivarian Republic of Venezuela"),
+ "VG" : _("Virgin Islands, British"),
+ "VI" : _("Virgin Islands, U.S."),
+ "VN" : _("Viet Nam"),
+ "VU" : _("Vanuatu"),
+ "WF" : _("Wallis and Futuna"),
+ "WS" : _("Samoa"),
+ "YE" : _("Yemen"),
+ "YT" : _("Mayotte"),
+ "ZA" : _("South Africa"),
+ "ZM" : _("Zambia"),
+ "ZW" : _("Zimbabwe"),
+}
+
+def get_by_code(code):
+ return country_list.get(code, None)
+
+def get_all(locale=None):
+ if locale is None:
+ l = country_list.keys()
+ else:
+ l = []
+
+ for c in country_list.keys():
+ c = locale.translate(c)
+ l.append(c)
+
+ # Sort list in place.
+ l.sort()
+
+ return l
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ A lightweight wrapper around psycopg2.
+
+ Originally part of the Tornado framework. The tornado.database module
+ is slated for removal in Tornado 3.0, and it is now available separately
+ as torndb.
+"""
+
+from __future__ import absolute_import, division, with_statement
+
+import copy
+import itertools
+import logging
+import os
+import psycopg2
+import time
+
+class Connection(object):
+ """
+ A lightweight wrapper around MySQLdb DB-API connections.
+
+ The main value we provide is wrapping rows in a dict/object so that
+ columns can be accessed by name. Typical usage::
+
+ db = torndb.Connection("localhost", "mydatabase")
+ for article in db.query("SELECT * FROM articles"):
+ print article.title
+
+ Cursors are hidden by the implementation, but other than that, the methods
+ are very similar to the DB-API.
+
+ We explicitly set the timezone to UTC and the character encoding to
+ UTF-8 on all connections to avoid time zone and encoding errors.
+ """
+ def __init__(self, host, database, user=None, password=None):
+ self.host = host
+ self.database = database
+
+ self._db = None
+ self._db_args = {
+ "host" : host,
+ "database" : database,
+ "user" : user,
+ "password" : password,
+ }
+
+ try:
+ self.reconnect()
+ except Exception:
+ logging.error("Cannot connect to database on %s", self.host, exc_info=True)
+
+ def __del__(self):
+ self.close()
+
+ def close(self):
+ """
+ Closes this database connection.
+ """
+ if getattr(self, "_db", None) is not None:
+ self._db.close()
+ self._db = None
+
+ def reconnect(self):
+ """
+ Closes the existing database connection and re-opens it.
+ """
+ self.close()
+
+ self._db = psycopg2.connect(**self._db_args)
+ self._db.autocommit = True
+
+ def query(self, query, *parameters, **kwparameters):
+ """
+ Returns a row list for the given query and parameters.
+ """
+ cursor = self._cursor()
+ try:
+ self._execute(cursor, query, parameters, kwparameters)
+ column_names = [d[0] for d in cursor.description]
+ return [Row(itertools.izip(column_names, row)) for row in cursor]
+ finally:
+ cursor.close()
+
+ def get(self, query, *parameters, **kwparameters):
+ """
+ Returns the first row returned for the given query.
+ """
+ rows = self.query(query, *parameters, **kwparameters)
+ if not rows:
+ return None
+ elif len(rows) > 1:
+ raise Exception("Multiple rows returned for Database.get() query")
+ else:
+ return rows[0]
+
+ def execute(self, query, *parameters, **kwparameters):
+ """
+ Executes the given query, returning the lastrowid from the query.
+ """
+ return self.execute_lastrowid(query, *parameters, **kwparameters)
+
+ def execute_lastrowid(self, query, *parameters, **kwparameters):
+ """
+ Executes the given query, returning the lastrowid from the query.
+ """
+ cursor = self._cursor()
+ try:
+ self._execute(cursor, query, parameters, kwparameters)
+ return cursor.lastrowid
+ finally:
+ cursor.close()
+
+ def execute_rowcount(self, query, *parameters, **kwparameters):
+ """
+ Executes the given query, returning the rowcount from the query.
+ """
+ cursor = self._cursor()
+ try:
+ self._execute(cursor, query, parameters, kwparameters)
+ return cursor.rowcount
+ finally:
+ cursor.close()
+
+ def executemany(self, query, parameters):
+ """
+ Executes the given query against all the given param sequences.
+
+ We return the lastrowid from the query.
+ """
+ return self.executemany_lastrowid(query, parameters)
+
+ def executemany_lastrowid(self, query, parameters):
+ """
+ Executes the given query against all the given param sequences.
+
+ We return the lastrowid from the query.
+ """
+ cursor = self._cursor()
+ try:
+ cursor.executemany(query, parameters)
+ return cursor.lastrowid
+ finally:
+ cursor.close()
+
+ def executemany_rowcount(self, query, parameters):
+ """
+ Executes the given query against all the given param sequences.
+
+ We return the rowcount from the query.
+ """
+ cursor = self._cursor()
+
+ try:
+ cursor.executemany(query, parameters)
+ return cursor.rowcount
+ finally:
+ cursor.close()
+
+ def _ensure_connected(self):
+ if self._db is None:
+ self.reconnect()
+
+ def _cursor(self):
+ self._ensure_connected()
+ return self._db.cursor()
+
+ def _execute(self, cursor, query, parameters, kwparameters):
+ try:
+ return cursor.execute(query, kwparameters or parameters)
+ except OperationalError:
+ logging.error("Error connecting to database on %s", self.host)
+ self.close()
+ raise
+
+
+class Row(dict):
+ """A dict that allows for object-like property access syntax."""
+ def __getattr__(self, name):
+ try:
+ return self[name]
+ except KeyError:
+ raise AttributeError(name)
+
+
+# Alias some common exceptions
+IntegrityError = psycopg2.IntegrityError
+OperationalError = psycopg2.OperationalError
+++ /dev/null
-#!/usr/bin/python
-
-import logging
-import tornado.database
-
-from misc import Singleton
-
-class Row(tornado.database.Row):
- pass
-
-MYSQL_SERVER = "mysql-master.ipfire.org"
-
-class Databases(object):
- __metaclass__ = Singleton
-
- def __init__(self):
- self._connections = {}
-
- @property
- def webapp(self):
- if not self._connections.has_key("webapp"):
- self._connections["webapp"] = \
- Connection(MYSQL_SERVER, "webapp", user="webapp")
-
- return self._connections["webapp"]
-
- @property
- def geoip(self):
- if not self._connections.has_key("geoip"):
- self._connections["geoip"] = \
- Connection(MYSQL_SERVER, "geoip", user="webapp")
-
- return self._connections["geoip"]
-
-
-class Connection(tornado.database.Connection):
- def __init__(self, *args, **kwargs):
- logging.debug("Creating new database connection: %s" % args[1])
-
- tornado.database.Connection.__init__(self, *args, **kwargs)
-
- def update(self, table, item_id, **items):
- query = "UPDATE %s SET " % table
-
- keys = []
- for k, v in items.items():
- # Never update id
- if k == "id":
- continue
-
- keys.append("%s='%s'" % (k, v))
-
- query += ", ".join(keys)
- query += " WHERE id=%s" % item_id
-
- return self.execute(query)
-
- def insert(self, table, **items):
- query = "INSERT INTO %s" % table
-
- keys = []
- vals = []
-
- for k, v in items.items():
- # Never insert id
- if k == "id":
- continue
-
- keys.append(k)
- vals.append("'%s'" % v)
-
- query += "(%s)"% ", ".join(keys)
- query += " VALUES(%s)" % ", ".join(vals)
-
- return self.execute(query)
-
- def _execute(self, cursor, query, parameters):
- logging.debug("Executing query: %s" % (query % parameters))
-
- return tornado.database.Connection._execute(self, cursor, query, parameters)
#!/usr/bin/python
+import IPy
import re
-from databases import Databases
-from memcached import Memcached
-from misc import Singleton
+import countries
-class GeoIP(object):
- __metaclass__ = Singleton
+from misc import Object
- @property
- def db(self):
- return Databases().geoip
+class GeoIP(Object):
+ def guess_address_family(self, addr):
+ if ":" in addr:
+ return 6
- def _encode_ip(self, addr):
- # We get a tuple if there were proxy headers.
- addr = addr.split(", ")
- if addr:
- addr = addr[-1]
+ return 4
- # ip is calculated as described in http://dev.maxmind.com/geoip/csv
- a1, a2, a3, a4 = addr.split(".")
+ def get_country(self, addr):
+ ret = self.get_all(addr)
- try:
- a1 = int(a1)
- a2 = int(a2)
- a3 = int(a3)
- a4 = int(a4)
- except ValueError:
- return 0
+ if ret:
+ return ret.country
- return (16777216 * a1) + (65536 * a2) + (256 * a3) + a4
+ def get_location(self, addr):
+ family = self.guess_address_family(addr)
- def get_country(self, addr):
- addr = self._encode_ip(addr)
+ if family == 6:
+ query = "SELECT *, NULL AS city, NULL AS postal_code FROM geoip_ipv6 WHERE %s \
+ BETWEEN start_ip AND end_ip LIMIT 1"
+ elif family == 4:
+ query = "SELECT * FROM geoip_ipv4 WHERE inet_to_bigint(%s) \
+ BETWEEN start_ip AND end_ip LIMIT 1"
- ret = self.db.get("SELECT locations.country_code AS country_code FROM addresses \
- JOIN locations ON locations.id = addresses.location \
- WHERE %s BETWEEN start_ip_num AND end_ip_num LIMIT 1", addr)
+ return self.db.get(query, addr)
- if ret:
- return ret.country_code
+ def get_asn(self, addr):
+ family = self.guess_address_family(addr)
- def get_all(self, addr):
- addr = self._encode_ip(addr)
- if not addr:
- return
+ if family == 6:
+ query = "SELECT asn FROM geoip_asnv6 WHERE %s \
+ BETWEEN start_ip AND end_ip LIMIT 1"
+ elif family == 4:
+ query = "SELECT asn FROM geoip_asnv4 WHERE inet_to_bigint(%s) \
+ BETWEEN start_ip AND end_ip LIMIT 1"
- ret = self.db.get("SELECT locations.* FROM addresses \
- JOIN locations ON locations.id = addresses.location \
- WHERE %s BETWEEN start_ip_num AND end_ip_num LIMIT 1", addr)
+ ret = self.db.get(query, addr)
- if not ret:
- return
+ if ret:
+ return ret.asn
- # If location was not determinable
- if ret.latitude == 0 and ret.longitude == 0:
- return None
+ def get_all(self, addr):
+ location = self.get_location(addr)
- return ret
+ if location:
+ location["asn"] = self.get_asn(addr)
- def get_country_name(self, code):
- name = "Unkown"
+ return location
- codes = {
- "A1" : "Anonymous Proxy",
- "A2" : "Satellite Provider",
- "EU" : "Europe",
- "AP" : "Asia/Pacific Region",
- }
+ _countries = {
+ "A1" : "Anonymous Proxy",
+ "A2" : "Satellite Provider",
+ "AP" : "Asia/Pacific Region",
+ "EU" : "Europe",
+ }
+ def get_country_name(self, code):
# Return description of some exceptional codes.
try:
- return codes[code]
+ return self._countries[code]
except KeyError:
pass
- ret = self.db.get("SELECT name FROM iso3166_countries WHERE code = %s LIMIT 1", code)
- if ret:
- name = ret.name
-
- # Fix some weird strings
- name = re.sub(r"(.*) (.* Republic of)", r"\2 \1", name)
-
- return name
-
-
-if __name__ == "__main__":
- g = GeoIP()
+ country = countries.get_by_code(code)
+ if not country:
+ return code
- print g.get_country("123.123.123.123")
- print g.get_all("123.123.123.123")
+ return country
from PIL import Image, ImageDraw, ImageFont, PngImagePlugin
-from misc import Singleton
+from misc import Object
-class IUse(object):
- __metaclass__ = Singleton
-
- images = []
-
- def add_imagetype(self, type):
- self.images.append(type)
+image_types = []
+class IUse(Object):
def get_imagetype(self, id):
id = int(id)
- for image in self.images:
- if image.id == id:
- return image
+ for image_type in image_types:
+ if image_type.id == id:
+ return image_type
-class ImageObject(object):
+class ImageObject(Object):
default_mode = "RGBA"
default_size = 100, 100
_font = "DejaVuSans.ttf"
_font_size = 10
- def __init__(self, request, profile):
+ def __init__(self, backend, request, profile):
+ Object.__init__(self, backend)
+
self.request = request
self.profile = profile
self.draw_text((225, 32), "%s" % " - ".join(line3))
-IUse().add_imagetype(Image1)
-
-
-if __name__ == "__main__":
- image = Image1("123")
- image.save("picture.png")
-
+image_types.append(Image1)
#!/usr/bin/python
+import logging
import memcache
-from misc import Singleton
-from settings import Settings
+from misc import Object
-class Memcached(object):
- __metaclass__ = Singleton
+class Memcached(Object):
+ def init(self):
+ self._connection = None
- def __init__(self):
- # Fetch hosts from database
- hosts = Settings().get("memcached_servers").split(",")
+ servers = self.get_servers()
- self._connection = memcache.Client(hosts, debug=0)
+ # Nothing to do, if no servers have been configured.
+ if not servers:
+ logging.warning("No memcache servers defined")
+ return
+
+ logging.info("Using memcache servers: %s" % ", ".join(servers))
+ self._connection = memcache.Client(servers, debug=0)
+
+ def get_servers(self):
+ servers = self.settings.get("memcached_servers")
+
+ if servers:
+ return servers.split(" ")
def get(self, key, *args, **kwargs):
+ if not self._connection:
+ return
+
key = str(key)
return self._connection.get(key, *args, **kwargs)
def set(self, key, *args, **kwargs):
+ if not self._connection:
+ return
+
key = str(key)
return self._connection.set(key, *args, **kwargs)
def delete(self, key, *args, **kwargs):
+ if not self._connection:
+ return
+
key = str(key)
return self._connection.delete(key, *args, **kwargs)
#!/usr/bin/python
+from __future__ import division
+
+import datetime
import logging
import math
import os.path
import socket
import time
import tornado.httpclient
+import tornado.netutil
+import urlparse
-from databases import Databases
-from geoip import GeoIP
-from memcached import Memcached
-from misc import Singleton
-
-class Downloads(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
-
- @property
- def mirrors(self):
- return Mirrors()
+from misc import Object
+class Downloads(Object):
@property
def total(self):
ret = self.db.get("SELECT COUNT(*) AS total FROM log_download")
@property
def today(self):
- ret = self.db.get("SELECT COUNT(*) AS today FROM log_download WHERE date >= NOW() - 1000000")
+ ret = self.db.get("SELECT COUNT(*) AS today FROM log_download WHERE date::date = NOW()::date")
return ret.today
@property
def yesterday(self):
- ret = self.db.get("SELECT COUNT(*) AS yesterday FROM log_download WHERE DATE(date) = DATE(NOW())-1")
+ ret = self.db.get("SELECT COUNT(*) AS yesterday FROM log_download WHERE date::date = (NOW() - INTERVAL '1 day')::date")
return ret.yesterday
@property
def daily_map(self):
- ret = self.db.query("SELECT DATE(date) AS date, COUNT(*) AS downloads FROM log_download"
- " WHERE DATE(date) BETWEEN DATE(NOW()) - 31 AND DATE(NOW()) GROUP BY DATE(date)")
+ ret = self.db.query("SELECT date::date AS date, COUNT(*) AS downloads FROM log_download"
+ " WHERE date::date BETWEEN (NOW() - INTERVAL '30 days')::date AND NOW()::date GROUP BY date::date")
return ret
query = "SELECT country_code, count(country_code) AS count FROM log_download"
if duration == "today":
- query += " WHERE date >= NOW() - 1000000"
+ query += " WHERE date::date = NOW()::date"
query += " GROUP BY country_code ORDER BY count DESC"
ret = {}
count = sum([o.count for o in results])
- for res in results:
- ret[res.country_code] = float(res.count) / count
+ if count:
+ for res in results:
+ ret[res.country_code] = res.count / count
return ret
query = "SELECT mirror, COUNT(mirror) AS count FROM log_download"
if duration == "today":
- query += " WHERE date >= NOW() - 1000000"
+ query += " WHERE date::date = NOW()::date"
query += " GROUP BY mirror ORDER BY count DESC"
ret = {}
count = sum([o.count for o in results])
- for res in results:
- mirror = self.mirrors.get(res.mirror)
- ret[mirror.hostname] = float(res.count) / count
+ if count:
+ for res in results:
+ mirror = self.mirrors.get(res.mirror)
+ ret[mirror.hostname] = res.count / count
return ret
-class Mirrors(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
-
- @property
- def memcached(self):
- return Memcached()
-
- def list(self):
- return [Mirror(m.id) for m in self.db.query("SELECT id FROM mirrors WHERE disabled = 'N' ORDER BY state,hostname")]
-
+class Mirrors(Object):
def check_all(self):
- for mirror in self.list():
+ for mirror in self.get_all():
mirror.check()
def get(self, id):
- return Mirror(id)
+ return Mirror(self.backend, id)
def get_all(self):
- return MirrorSet(self.list())
+ res = self.db.query("SELECT * FROM mirrors WHERE enabled = %s", True)
+
+ mirrors = []
+ for row in res:
+ mirror = Mirror(self.backend, row.id, row)
+ mirrors.append(mirror)
+
+ return MirrorSet(self.backend, sorted(mirrors))
def get_all_up(self):
- res = self.db.query("SELECT * FROM mirrors WHERE disabled = %s AND state = %s ORDER BY hostname", "N", "UP")
+ res = self.db.query("SELECT * FROM mirrors WHERE enabled = %s AND state = %s \
+ ORDER BY hostname", True, "UP")
mirrors = []
for row in res:
- m = Mirror(row.id, row)
+ m = Mirror(self.backend, row.id, row)
mirrors.append(m)
- return MirrorSet(mirrors)
+ return MirrorSet(self.backend, mirrors)
def get_by_hostname(self, hostname):
mirror = self.db.get("SELECT id FROM mirrors WHERE hostname=%s", hostname)
- return Mirror(mirror.id)
+ return Mirror(self.backend, mirror.id)
def get_with_file(self, filename, country=None):
# XXX quick and dirty solution - needs a performance boost
continue
mirrors.append(mirror)
- logging.debug("%s" % mirrors)
-
return mirrors
def get_for_country(self, country):
for mirror in mirrors:
yield self.get(mirror.id)
- def get_for_location(self, addr):
- distance = 10
-
- mirrors = []
- all_mirrors = self.list()
-
- location = GeoIP().get_all(addr)
+ def get_for_location(self, location):
if not location:
return None
- while all_mirrors and len(mirrors) <= 2 and distance <= 270:
+ distance = 2500
+
+ mirrors = []
+ all_mirrors = self.get_all()
+
+ while all_mirrors and len(mirrors) <= 3 and distance <= 8000:
for mirror in all_mirrors:
- if mirror.distance_to(location) <= distance:
+ mirror_distance = mirror.distance_to(location)
+ if mirror_distance is None:
+ continue
+
+ if mirror_distance<= distance:
mirrors.append(mirror)
all_mirrors.remove(mirror)
def get_all_files(self):
files = []
- for mirror in self.list():
+ for mirror in self.get_all():
if not mirror.state == "UP":
continue
return files
-class MirrorSet(object):
- def __init__(self, mirrors):
+class MirrorSet(Object):
+ def __init__(self, backend, mirrors):
+ Object.__init__(self, backend)
+
self._mirrors = mirrors
def __add__(self, other):
mirrors.append(mirror)
- return MirrorSet(mirrors)
+ return MirrorSet(self.backend, mirrors)
def __sub__(self, other):
mirrors = self._mirrors[:]
if mirror in mirrors:
mirrors.remove(mirror)
- return MirrorSet(mirrors)
+ return MirrorSet(self.backend, mirrors)
def __iter__(self):
return iter(self._mirrors)
def __str__(self):
return "<MirrorSet %s>" % ", ".join([m.hostname for m in self._mirrors])
- @property
- def db(self):
- return Mirrors().db
-
def get_with_file(self, filename):
with_file = [m.mirror for m in self.db.query("SELECT mirror FROM mirror_files WHERE filename=%s", filename)]
if mirror.id in with_file:
mirrors.append(mirror)
- return MirrorSet(mirrors)
+ return MirrorSet(self.backend, mirrors)
def get_random(self):
mirrors = []
if country in mirror.prefer_for_countries:
mirrors.append(mirror)
- return MirrorSet(mirrors)
-
- def get_for_location(self, addr):
- distance = 10
+ return MirrorSet(self.backend, mirrors)
+ def get_for_location(self, location):
+ distance = 2500
mirrors = []
- location = GeoIP().get_all(addr)
if location:
- while len(mirrors) <= 2 and distance <= 270:
+ while len(mirrors) <= 3 and distance <= 8000:
for mirror in self._mirrors:
if mirror in mirrors:
continue
- if mirror.distance_to(location) <= distance:
+ mirror_distance = mirror.distance_to(location)
+ if mirror_distance is None:
+ continue
+
+ if mirror_distance <= distance:
mirrors.append(mirror)
distance *= 1.2
- return MirrorSet(mirrors)
+ return MirrorSet(self.backend, mirrors)
def get_with_state(self, state):
mirrors = []
if mirror.state == state:
mirrors.append(mirror)
- return MirrorSet(mirrors)
+ return MirrorSet(self.backend, mirrors)
+
+class Mirror(Object):
+ def __init__(self, backend, id, data=None):
+ Object.__init__(self, backend)
-class Mirror(object):
- def __init__(self, id, data=None):
self.id = id
if data:
return "<%s %s>" % (self.__class__.__name__, self.url)
def __cmp__(self, other):
- return cmp(self.id, other.id)
+ ret = cmp(self.country_code, other.country_code)
- @property
- def db(self):
- return Databases().webapp
+ if not ret:
+ ret = cmp(self.hostname, other.hostname)
+
+ return ret
def generate_url(self):
url = "http://%s" % self.hostname
url += "/"
return url
- def __getattr__(self, key):
- try:
- return self._info[key]
- except KeyError:
- raise AttributeError(key)
+ @property
+ def hostname(self):
+ return self._info.hostname
+
+ @property
+ def path(self):
+ return self._info.path
@property
def address(self):
return socket.gethostbyname(self.hostname)
+ @property
+ def owner(self):
+ return self._info.owner
+
@property
def location(self):
if self.__location is None:
- self.__location = GeoIP().get_all(self.address)
+ self.__location = self.geoip.get_location(self.address)
return self.__location
@property
def latitude(self):
- return self.location.latitude
+ if self.location:
+ return self.location.latitude
@property
def longitude(self):
- return self.location.longitude
+ if self.location:
+ return self.location.longitude
@property
def coordinates(self):
@property
def country_code(self):
- return self.location.country_code.lower() or "unknown"
+ if self.location:
+ return self.location.country
@property
def country_name(self):
if self.__country_name is None:
- self.__country_name = GeoIP().get_country_name(self.country_code)
+ self.__country_name = self.geoip.get_country_name(self.country_code)
return self.__country_name
@property
- def city(self):
- if self._info["city"]:
- return self._info["city"]
+ def location_str(self):
+ location = []
+
+ if self._info.location:
+ location.append(self._info.location)
- return self.location.city
+ elif self.location:
+ location.append(self.location.city)
+ location.append(self.country_name)
+
+ return ", ".join([s for s in location if s])
@property
- def location_str(self):
- s = self.country_name
- if self.city:
- s = "%s, %s" % (self.city, s)
+ def asn(self):
+ if not hasattr(self, "__asn"):
+ self.__asn = self.geoip.get_asn(self.address)
- return s
+ return self.__asn
@property
def filelist(self):
@property
def prefix(self):
- if self.type.startswith("pakfire"):
- return self.type
-
return ""
+ @property
+ def url(self):
+ return self._info.url
+
+ def build_url(self, filename):
+ return urlparse.urljoin(self.url, filename)
+
+ @property
+ def last_update(self):
+ return self._info.last_update
+
+ @property
+ def state(self):
+ return self._info.state
+
def set_state(self, state):
logging.info("Setting state of %s to %s" % (self.hostname, state))
if self.state == state:
return
- self.db.execute("UPDATE mirrors SET state=%s WHERE id=%s",
- state, self.id)
+ self.db.execute("UPDATE mirrors SET state = %s WHERE id = %s", state, self.id)
# Reload changed settings
if hasattr(self, "_info"):
self._info["state"] = state
+ @property
+ def enabled(self):
+ return self._info.enabled
+
+ @property
+ def disabled(self):
+ return not self.enabled
+
def check(self):
logging.info("Running check for mirror %s" % self.hostname)
def check_state(self):
logging.debug("Checking state of mirror %s" % self.id)
- if self.disabled == "Y":
+ if not self.enabled:
self.set_state("DOWN")
+ return
+
+ now = datetime.datetime.utcnow()
+
+ time_delta = now - self.last_update
+ time_diff = time_delta.total_seconds()
- time_diff = time.time() - self.last_update
- if time_diff > 3*24*60*60: # XXX get this into Settings
+ time_down = self.settings.get_int("mirrors_time_down", 3*24*60*60)
+ if time_diff >= time_down:
self.set_state("DOWN")
- elif time_diff > 6*60*60:
- self.set_state("OUTOFSYNC")
- else:
- self.set_state("UP")
+ return
- def check_timestamp(self):
- if not self.type == "full":
+ time_outofsync = self.settings.get_int("mirrors_time_outofsync", 6*60*60)
+ if time_diff >= time_outofsync:
+ self.set_state("OUTOFSYNC")
return
+ self.set_state("UP")
+
+ def check_timestamp(self):
http = tornado.httpclient.AsyncHTTPClient()
http.fetch(self.url + ".timestamp",
except ValueError:
timestamp = 0
- self.db.execute("UPDATE mirrors SET last_update=%s WHERE id=%s",
+ timestamp = datetime.datetime.fromtimestamp(timestamp)
+
+ self.db.execute("UPDATE mirrors SET last_update = %s WHERE id = %s",
timestamp, self.id)
# Reload changed settings
def check_filelist(self):
# XXX need to remove data from disabled mirrors
- if self.disabled == "Y" or self.type != "full":
+ if not self.enabled:
return
http = tornado.httpclient.AsyncHTTPClient()
@property
def prefer_for_countries_names(self):
- return sorted([GeoIP().get_country_name(c) for c in self.prefer_for_countries])
+ countries = [self.geoip.get_country_name(c.upper()) for c in self.prefer_for_countries]
+
+ return sorted(countries)
def distance_to(self, location, ignore_preference=False):
if not location:
- return 0
+ return None
- if not ignore_preference and location.country_code.lower() in self.prefer_for_countries:
+ country_code = None
+ if location.country:
+ country_code = location.country.lower()
+
+ if not ignore_preference and country_code in self.prefer_for_countries:
return 0
- distance_vector = (
- self.latitude - location.latitude,
- self.longitude - location.longitude
- )
+ # http://www.movable-type.co.uk/scripts/latlong.html
+
+ if self.latitude is None:
+ return None
+
+ if self.longitude is None:
+ return None
+
+ earth = 6371 # km
+ delta_lat = math.radians(self.latitude - location.latitude)
+ delta_lon = math.radians(self.longitude - location.longitude)
+
+ lat1 = math.radians(self.latitude)
+ lat2 = math.radians(location.latitude)
+
+ a = math.sin(delta_lat / 2) ** 2
+ a += math.cos(lat1) * math.cos(lat2) * (math.sin(delta_lon / 2) ** 2)
- distance = 0
- for i in distance_vector:
- distance += i**2
+ b1 = math.sqrt(a)
+ b2 = math.sqrt(1 - a)
- return math.sqrt(distance)
+ c = 2 * math.atan2(b1, b2)
+
+ return c * earth
def traffic(self, since):
# XXX needs to be done better
def priority(self):
return self._info.get("priority", 10)
- def is_pakfire2(self):
- return self.type in ("full", "pakfire2")
-
@property
def development(self):
- return self._info.get("development", "N") == "Y"
+ return self._info.get("development", False)
@property
def mirrorlist(self):
- return self._info.get("mirrorlist", "N") == "Y"
+ return self._info.get("mirrorlist", False)
+
+ @property
+ def addresses(self):
+ if not hasattr(self, "__addresses"):
+ addrinfo = socket.getaddrinfo(self.hostname, 0, socket.AF_UNSPEC, socket.SOCK_STREAM)
+
+ ret = []
+ for family, socktype, proto, canonname, address in addrinfo:
+ if family == socket.AF_INET:
+ address, port = address
+ elif family == socket.AF_INET6:
+ address, port, flowid, scopeid = address
+ ret.append((family, address))
+
+ self.__addresses = ret
+
+ return self.__addresses
+
+ @property
+ def addresses6(self):
+ return [address for family, address in self.addresses if family == socket.AF_INET6]
+
+ @property
+ def addresses4(self):
+ return [address for family, address in self.addresses if family == socket.AF_INET]
def __init__(self, backend):
self.backend = backend
+ self.init()
+
+ def init(self):
+ """
+ Function for custom initialization.
+ """
+ pass
+
@property
def db(self):
return self.backend.db
def accounts(self):
return self.backend.accounts
+ @property
+ def downloads(self):
+ return self.backend.downloads
+
+ @property
+ def geoip(self):
+ return self.backend.geoip
+
+ @property
+ def iuse(self):
+ return self.backend.iuse
+
+ @property
+ def memcache(self):
+ return self.backend.memcache
+
@property
def planet(self):
return self.backend.planet
-
-class Singleton(type):
- """
- A class for using the singleton pattern
- """
-
- def __init__(cls, name, bases, dict):
- super(Singleton, cls).__init__(name, bases, dict)
- cls.instance = None
-
- def __call__(cls, *args, **kw):
- if cls.instance is None:
- cls.instance = super(Singleton, cls).__call__(*args, **kw)
-
- return cls.instance
+ @property
+ def settings(self):
+ return self.backend.settings
#!/usr/bin/python
-from databases import Databases
-from misc import Singleton
-
+from misc import Object
class MenuEntry(object):
def __init__(self, _data):
return int(self._data.get("item"))
-class NetBoot(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
-
+class NetBoot(Object):
def get_menu(self, level=0):
menu = []
#!/usr/bin/python
-from databases import Databases
-from misc import Singleton
-
-class News(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
-
- def list(self):
- return [i.uuid for i in self.db.query("SELECT DISTINCT uuid FROM news ORDER BY date")]
+from misc import Object
+class News(Object):
def get(self, uuid, lang="en"):
- return self.db.get("SELECT * FROM news WHERE uuid=%s AND lang=%s",
- uuid, lang)
+ return self.db.get("SELECT * FROM news WHERE uuid = %s AND lang = %s \
+ AND published IS NOT NULL AND published <= NOW()", uuid, lang)
def get_by_slug(self, slug):
- return self.db.get("SELECT * FROM news WHERE slug=%s", slug)
+ return self.db.get("SELECT * FROM news WHERE slug = %s \
+ AND published IS NOT NULL AND published <= NOW()", slug)
def get_latest(self, author=None, locale=None, limit=1, offset=0):
- query = "SELECT * FROM news WHERE published='Y'"
+ query = "SELECT * FROM news WHERE published IS NOT NULL AND published <= NOW()"
+ args = []
if author:
- query += " AND author_id='%s'" % author
+ query += " AND author_id = %s"
+ args.append(author)
if locale:
- query += " AND lang='%s'" % locale.code[:2]
+ query += " AND lang = %s"
+ args.append(locale.code[:2])
- query += " ORDER BY date DESC"
+ query += " ORDER BY published DESC"
if limit:
- if offset:
- query += " LIMIT %d,%d" % (offset, limit)
- else:
- query += " LIMIT %d" % limit
+ query += " LIMIT %s"
+ args.append(limit)
- news = self.db.query(query)
+ if offset:
+ query += " OFFSET %s"
+ args.append(offset)
- return news
+ return self.db.query(query, *args)
def get_by_year(self, year, locale=None):
- query = "SELECT * FROM news WHERE published = 'Y' AND YEAR(date) = %s"
+ query = "SELECT * FROM news WHERE published IS NOT NULL AND published <= NOW() \
+ AND EXTRACT(YEAR FROM published) = %s"
args = [year,]
if locale:
query += " AND lang = %s"
args.append(locale.code[:2])
- query += " ORDER BY date DESC"
+ query += " ORDER BY published DESC"
return self.db.query(query, *args)
@property
def years(self):
- years = []
-
- for row in self.db.query("SELECT DISTINCT YEAR(date) AS year FROM news \
- WHERE published = 'Y' ORDER BY year DESC"):
- years.append(row.year)
-
- return years
-
-
-if __name__ == "__main__":
- n = News()
+ query = self.db.query("SELECT DISTINCT EXTRACT(YEAR FROM published)::integer AS year FROM news \
+ WHERE published IS NOT NULL AND published <= NOW() ORDER BY year DESC")
- print n.list()
- print n.get_latest()
+ return [r.year for r in query]
import datetime
import re
import textile
-import tornado.database
import unicodedata
-from accounts import Accounts
-from databases import Databases
-
from misc import Object
class PlanetEntry(Object):
class Planet(Object):
def get_authors(self):
+ query = self.db.query("SELECT DISTINCT author_id FROM planet WHERE status = %s \
+ AND published IS NOT NULL AND published <= NOW()", "published")
+
authors = []
- for author in self.db.query("SELECT DISTINCT author_id FROM planet WHERE status = %s", "published"):
+ for author in query:
author = self.accounts.search(author.author_id)
if author:
authors.append(author)
return sorted(authors)
def get_years(self):
- res = self.db.query("SELECT DISTINCT YEAR(published) AS year \
+ res = self.db.query("SELECT DISTINCT EXTRACT(YEAR FROM published)::integer AS year \
FROM planet WHERE status = %s ORDER BY year DESC", "published")
return [row.year for row in res]
def get_entry_by_slug(self, slug):
entry = self.db.get("SELECT * FROM planet WHERE slug = %s", slug)
+
if entry:
return PlanetEntry(self.backend, entry)
def get_entry_by_id(self, id):
entry = self.db.get("SELECT * FROM planet WHERE id = %s", id)
+
if entry:
return PlanetEntry(self.backend, entry)
- def _limit_and_offset_query(self, limit=None, offset=None):
- query = " "
-
- if limit:
- if offset:
- query += "LIMIT %d,%d" % (offset, limit)
- else:
- query += "LIMIT %d" % limit
-
- return query
-
def get_entries(self, limit=3, offset=None, status="published", author_id=None):
query = "SELECT * FROM planet"
args, clauses = [], []
# Respect limit and offset
if limit:
+ query += " LIMIT %s"
+ args.append(limit)
+
if offset:
- query += " LIMIT %s,%s"
- args += [offset, limit,]
- else:
- query += " LIMIT %s"
- args.append(limit)
+ query += " OFFSET %s"
+ args.append(offset)
entries = []
for entry in self.db.query(query, *args):
def get_entries_by_year(self, year):
entries = self.db.query("SELECT * FROM planet \
- WHERE status = %s AND YEAR(published) = %s ORDER BY published DESC",
- "published", year)
+ WHERE status = %s AND EXTRACT(YEAR FROM published) = %s \
+ ORDER BY published DESC", "published", year)
return [PlanetEntry(self.backend, e) for e in entries]
def save_entry(self, entry):
slug = self._generate_slug(entry.title)
- id = self.db.execute("INSERT INTO planet(author_id, title, slug, markdown, published) "
- "VALUES(%s, %s, %s, %s, UTC_TIMESTAMP())", entry.author.uid, entry.title,
- slug, entry.markdown)
+ id = self.db.execute("INSERT INTO planet(author_id, title, slug, markdown, published) \
+ VALUES(%s, %s, %s, %s, NOW())", entry.author.uid, entry.title, slug, entry.markdown)
return id
import urllib
import urlparse
+import database
import tracker
+from misc import Object
-from databases import Databases
-from misc import Singleton
-from settings import Settings
+class File(Object):
+ def __init__(self, backend, release, id, data=None):
+ Object.__init__(self, backend)
-class File(object):
- def __init__(self, release, id):
self.id = id
self._release = release
# get all data from database
- self.__data = None
+ self.__data = data
- @property
- def db(self):
- return Databases().webapp
-
- @property
- def tracker(self):
- return self.release.tracker
+ def __cmp__(self, other):
+ return cmp(self.prio, other.prio)
@property
def data(self):
@property
def url(self):
- baseurl = Settings().get("download_url")
+ baseurl = self.settings.get("download_url", "http://downloads.ipfire.org")
return urlparse.urljoin(baseurl, self.filename)
return self.tracker.get_peers(self.torrent_hash)
- @property
- def completed(self):
- if not self.torrent_hash:
- return
-
- return self.tracker.complete(self.torrent_hash)
-
-class Release(object):
- @property
- def db(self):
- return Releases().db
-
- @property
- def tracker(self):
- return tracker.Tracker()
-
- def __init__(self, id):
+class Release(Object):
+ def __init__(self, backend, id, data=None):
+ Object.__init__(self, backend)
self.id = id
# get all data from database
- self.__data = \
- self.db.get("SELECT * FROM releases WHERE id = %s", self.id)
+ self.__data = data or self.db.get("SELECT * FROM releases WHERE id = %s", self.id)
assert self.__data
self.__files = []
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.name)
+ def __cmp__(self, other):
+ return cmp(self.id, other.id)
+
@property
def files(self):
if not self.__files:
- files = self.db.query("SELECT id, filename FROM files WHERE releases = %s \
- AND loadable = 'Y' AND NOT filename LIKE '%%.torrent'", self.id)
+ files = self.db.query("SELECT * FROM files WHERE releases = %s \
+ AND NOT filename LIKE '%%.torrent'", self.id)
- self.__files = [File(self, f.id) for f in files]
- self.__files.sort(lambda a, b: cmp(a.prio, b.prio))
+ self.__files = [File(self.backend, self, f.id, f) for f in files]
+ self.__files.sort()
return self.__files
@property
def name(self):
- return self.__data.get("name")
+ return self.__data.name
+
+ @property
+ def sname(self):
+ return self.__data.sname
@property
def stable(self):
- return self.__data.get("stable") == "Y"
+ return self.__data.stable
@property
def published(self):
- return self.__data.get("published") == "Y"
+ return self.__data.published
- @property
- def date(self):
- return self.__data.get("date")
+ date = published
@property
def path(self):
- return self.__data.get("path")
+ return self.__data.path
def get_file(self, type):
for file in self.files:
if filename.endswith(".md5"):
continue
+ logging.info("Hashing %s..." % filename)
filehash = self.__file_hash(filename)
filesize = os.path.getsize(filename)
if f:
f.close()
+ def is_netboot_capable(self):
+ return self.path and "ipfire-2.x" in self.path
+
+ @property
+ def netboot_kernel(self):
+ return "http://downloads.ipfire.org/%s/images/vmlinuz" % self.path
-class Releases(object):
- __metaclass__ = Singleton
+ @property
+ def netboot_initrd(self):
+ return "http://downloads.ipfire.org/%s/images/instroot" % self.path
@property
- def db(self):
- return Databases().webapp
+ def netboot_append(self):
+ return "ro"
- def list(self):
- return [Release(r.id) for r in self.db.query("SELECT id FROM releases ORDER BY date DESC")]
+class Releases(Object):
def get_by_id(self, id):
- id = int(id)
- if id in [r.id for r in self.db.query("SELECT id FROM releases")]:
- return Release(id)
-
- def get_latest(self, stable=1):
- query = "SELECT id FROM releases WHERE published='Y' AND"
- if stable:
- query += " stable='Y'"
- else:
- query += " stable='N'"
+ ret = self.db.get("SELECT * FROM releases WHERE id = %s", id)
+
+ if ret:
+ return Release(self.backend, ret.id, data=ret)
+
+ def get_by_sname(self, sname):
+ ret = self.db.get("SELECT * FROM releases WHERE sname = %s", sname)
+
+ if ret:
+ return Release(self.backend, ret.id, data=ret)
- query += " ORDER BY date DESC LIMIT 1"
+ def get_latest(self, stable=True):
+ ret = self.db.get("SELECT * FROM releases WHERE published IS NOT NULL AND published <= NOW() \
+ AND stable = %s ORDER BY published DESC LIMIT 1", stable)
- release = self.db.get(query)
- if release:
- return Release(release.id)
+ if ret:
+ return Release(self.backend, ret.id, data=ret)
def get_stable(self):
- releases = self.db.query("""SELECT id FROM releases
- WHERE published='Y' AND stable='Y'
- ORDER BY date DESC""")
+ query = self.db.query("SELECT * FROM releases \
+ WHERE published IS NOT NULL AND published <= NOW() AND stable = TRUE \
+ ORDER BY published DESC")
- return [Release(r.id) for r in releases]
+ releases = []
+ for row in query:
+ release = Release(self.backend, row.id, data=row)
+ releases.append(release)
+
+ return releases
def get_unstable(self):
- releases = self.db.query("""SELECT id FROM releases
- WHERE published='Y' AND stable='N'
- ORDER BY date DESC""")
+ query = self.db.query("SELECT * FROM releases \
+ WHERE published IS NOT NULL AND published <= NOW() AND stable = FALSE \
+ ORDER BY published DESC")
+
+ releases = []
+ for row in query:
+ release = Release(self.backend, row.id, data=row)
+ releases.append(release)
- return [Release(r.id) for r in releases]
+ return releases
def get_all(self):
- releases = self.db.query("""SELECT id FROM releases
- WHERE published='Y' ORDER BY date DESC""")
+ query = self.db.query("SELECT * FROM releases \
+ WHERE published IS NOT NULL AND published <= NOW() \
+ ORDER BY published DESC")
- return [Release(r.id) for r in releases]
+ releases = []
+ for row in query:
+ release = Release(self.backend, row.id, data=row)
+ releases.append(release)
+
+ return releases
def get_file_for_torrent_hash(self, torrent_hash):
file = self.db.get("SELECT id, releases FROM files WHERE torrent_hash = %s LIMIT 1",
file = File(release, file.id)
return file
-
-
-if __name__ == "__main__":
- r = Releases()
-
- for release in r.get_all():
- print release.name
-
- print r.get_latest()
#!/usr/bin/python
-from databases import Databases
-from misc import Singleton
+from misc import Object
-class Settings(object):
- __metaclass__ = Singleton
+class Settings(Object):
+ def init(self):
+ """
+ Initialize the settings dictionary by fetching the
+ entire table from the database.
+ """
+ self.__settings = {}
- @property
- def db(self):
- return Databases().webapp
+ query = self.db.query("SELECT k, v FROM settings")
+
+ for row in query:
+ self.__settings[row.k] = row.v
def query(self, key):
return self.db.get("SELECT * FROM settings WHERE k=%s", key)
- def get(self, key):
- return "%s" % self.query(key)["v"]
-
- def get_id(self, key):
- return self.query(key)["id"]
+ def get(self, key, default=None):
+ return self.__settings.get(key, default)
- def get_int(self, key):
+ def get_int(self, key, default=None):
value = self.get(key)
if value is None:
- return None
+ return default
- return int(value)
+ try:
+ return int(value)
+ except (TypeError, ValueError):
+ return default
def get_float(self, key):
value = self.get(key)
if value is None:
- return None
+ return default
- return float(value)
+ try:
+ return float(value)
+ except (TypeError, ValueError):
+ return default
def set(self, key, value):
- id = self.get(key)
+ oldvalue = self.get(key)
- if not id:
- self.db.execute("INSERT INTO settings(k, v) VALUES(%s, %s)", key, value)
+ if value == oldvalue:
+ return
+
+ if oldvalue:
+ self.db.execute("UPDATE settings SET v = %s WHERE k = %s", value, key)
else:
- self.db.execute("UPDATE settings SET v=%s WHERE id=%s" % (value, id))
+ self.db.execute("INSERT INTO settings(k, v) VALUES(%s, %s)", key, value)
def get_all(self):
- attrs = {}
-
- for s in self.db.query("SELECT * FROM settings"):
- attrs[s.k] = s.v
-
- return attrs
-
-
-if __name__ == "__main__":
- s = Settings()
-
- print s.get_all()
+ return self.__settings.copy()
import pymongo
import re
-from misc import Singleton
+from misc import Object
DATABASE_HOST = ["wilhelmina.ipfire.org", "miranda.ipfire.org", "falco.ipfire.org",]
DATABASE_NAME = "stasy"
"Geode by NSC" : "NSC",
"NexGenDriven" : "NexGen",
"RiseRiseRise" : "Rise",
+ "SiS SiS SiS" : "SiS",
"SiS SiS SiS " : "SiS",
"UMC UMC UMC " : "UMC",
"VIA VIA VIA " : "VIA",
+ "Vortex86 SoC" : "Vortex86",
}
CPU_STRINGS = (
return ProfileNetwork(network)
-class Stasy(object):
- __metaclass__ = Singleton
-
- def __init__(self):
+class Stasy(Object):
+ def init(self):
# Initialize database connection
self._conn = pymongo.Connection(DATABASE_HOST)
self._db = self._conn[DATABASE_NAME]
{ "profile.system.release" : release }).count()
return updates
-
-
-if __name__ == "__main__":
- s = Stasy()
-
#!/usr/bin/python
-import os
-import random
-import time
+from __future__ import division
-import releases
+import random
-from databases import Databases, Row
-from misc import Singleton
+from misc import Object
def decode_hex(s):
ret = []
return "".join(ret)
-class Tracker(object):
- id = "TheIPFireTorrentTracker"
-
- # Intervals # XXX needs to be in Settings
- _interval = 60*60
- _min_interval = 30*60
+class Tracker(Object):
+ @property
+ def tracker_id(self):
+ return self.settings.get("tracker_id", "TheIPFireTorrentTracker")
- random_interval = -60, 60
+ def _fuzzy_interval(self, interval, fuzz=60):
+ return interval + random.randint(-fuzz, fuzz)
- numwant = 50
+ @property
+ def interval(self):
+ return self.settings.get_int("tracker_interval", 3600)
@property
- def db(self):
- return Databases().webapp
+ def min_interval(self):
+ interval = self.settings.get_int("tracker_min_interval", self.interval // 2)
- def _fetch(self, hash, limit=None, random=False, completed=False, no_peer_id=False):
- query = "SELECT * FROM tracker_peers WHERE last_update >= %d" % self.since
+ return self._fuzzy_interval(interval)
+
+ @property
+ def numwant(self):
+ return self.settings.get_int("tracker_numwant", 50)
- if hash:
- query += " AND hash = '%s'" % hash
+ def get_peers(self, info_hash, limit=None, random=True, no_peer_id=False, ipfamily=None):
+ query = "SELECT * FROM tracker WHERE last_update >= NOW() - INTERVAL '%ss'"
+ args = [self.interval,]
- if completed:
- query += " AND left_data = 0"
- else:
- query += " AND left_data != 0"
+ if info_hash:
+ query += " AND hash = %s"
+ args.append(info_hash)
if random:
- query += " ORDER BY RAND()"
+ query += " ORDER BY RANDOM()"
if limit:
- query += " LIMIT %s" % limit
+ query += " LIMIT %s"
+ args.append(limit)
peers = []
- for peer in self.db.query(query):
- if not peer.ip or not peer.port:
- continue
-
- peer_dict = {
- "ip" : str(peer.ip),
- "port" : int(peer.port),
- }
+ for row in self.db.query(query, *args):
+ peer6 = None
+ peer4 = None
+
+ if row.address6 and row.port6:
+ peer6 = {
+ "ip" : row.address6,
+ "port" : row.port6,
+ }
+
+ if row.address4 and row.port4:
+ peer4 = {
+ "ip" : row.address4,
+ "port" : row.port4,
+ }
if not no_peer_id:
- peer_dict["peer id"] = str(peer.id),
+ if peer6:
+ peer6["peer id"] = row.id
- peers.append(peer_dict)
+ if peer4:
+ peer6["peer id"] = row.id
- return peers
+ if peer6:
+ peers.append(peer6)
- def get_peers(self, hash, **kwargs):
- return self._fetch(hash, **kwargs)
+ if peer4:
+ peers.append(peer4)
- def get_seeds(self, hash, **kwargs):
- kwargs.update({"completed" : True})
- return self._fetch(hash, **kwargs)
+ return peers
- def complete(self, hash):
- return len(self.get_seeds(hash))
+ def cleanup_peers(self):
+ """
+ Remove all peers that have timed out.
+ """
+ self.db.execute("DELETE FROM tracker \
+ WHERE last_update < NOW() - INTERVAL '%ss'", self.interval)
- def incomplete(self, hash):
- return len(self.get_peers(hash))
+ def update_peer(self, peer_id, info_hash, address6=None, port6=None,
+ address4=None, port4=None, downloaded=None, uploaded=None, left_data=None):
+ if address4 and address4.startswith("172.28.1."):
+ address = "178.63.73.246"
- def event_started(self, hash, peer_id):
- # Damn, mysql does not support INSERT IF NOT EXISTS...
- if not self.db.query("SELECT id FROM tracker_peers WHERE hash = '%s' AND peer_id = '%s'" % (hash, peer_id)):
- self.db.execute("INSERT INTO tracker_peers(hash, peer_id) VALUES('%s', '%s')" % (hash, peer_id))
+ query = "UPDATE tracker SET last_update = NOW()"
+ args = []
- if not hash in self.hashes:
- self.db.execute("INSERT INTO tracker_hashes(hash) VALUES('%s')" % hash)
+ if address6:
+ query += ", address6 = %s"
+ args.append(address6)
- def event_stopped(self, hash, peer_id):
- self.db.execute("DELETE FROM tracker_peers WHERE hash = '%s' AND peer_id = '%s'" % (hash, peer_id))
+ if port6:
+ query += ", port6 = %s"
+ args.append(port6)
- def event_completed(self, hash, peer_id):
- self.db.execute("UPDATE tracker_hashes SET completed=completed+1 WHERE hash = '%s'" % hash)
+ if address4:
+ query += ", address4 = %s"
+ args.append(address4)
- def scrape(self, hashes=[]):
- ret = {}
- for hash in self.db.query("SELECT hash, completed FROM tracker_hashes"):
- hash, completed = hash.hash, hash.completed
+ if port4:
+ query += ", port4 = %s"
+ args.append(port4)
- if hashes and hash not in hashes:
- continue
+ if downloaded:
+ query += ", downloaded = %s"
+ args.append(downloaded)
- ret[hash] = {
- "complete" : self.complete(hash),
- "downloaded" : completed or 0,
- "incomplete" : self.incomplete(hash),
- }
+ if uploaded:
+ query += ", uploaded = %s"
+ args.append(uploaded)
- return ret
+ if left_data:
+ query += ", left_data = %s"
+ args.append(left_data)
- def update(self, hash, id, ip=None, port=None, downloaded=None, uploaded=None, left=None):
- args = [ "last_update = '%s'" % self.now ]
+ query += " WHERE id = %s AND hash = %s"
+ args += [peer_id, info_hash]
- if ip:
- if ip.startswith("172.28.1."):
- ip = "178.63.73.246"
+ self.db.execute(query, *args)
- args.append("ip='%s'" % ip)
+ def complete(self, info_hash):
+ ret = self.db.get("SELECT COUNT(*) AS c FROM tracker \
+ WHERE hash = %s AND left_data = 0", info_hash)
- if port:
- args.append("port='%s'" % port)
+ if ret:
+ return ret.c
- if downloaded:
- args.append("downloaded='%s'" % downloaded)
+ def incomplete(self, info_hash):
+ ret = self.db.get("SELECT COUNT(*) AS c FROM tracker \
+ WHERE hash = %s AND left_data > 0", info_hash)
- if uploaded:
- args.append("uploaded='%s'" % uploaded)
+ if ret:
+ return ret.c
- if left:
- args.append("left_data='%s'" % left)
+ def handle_event(self, event, peer_id, info_hash, **kwargs):
+ # started
+ if event == "started":
+ self.insert_peer(peer_id, info_hash, **kwargs)
- if not args:
- return
+ # stopped
+ elif event == "stopped":
+ self.remove_peer(peer_id, info_hash)
- query = "UPDATE tracker_peers SET " + ", ".join(args) + \
- " WHERE hash = '%s' AND peer_id = '%s'" % (hash, id)
+ def peer_exists(self, peer_id, info_hash):
+ ret = self.db.get("SELECT COUNT(*) AS c FROM tracker \
+ WHERE id = %s AND hash = %s", peer_id, info_hash)
- self.db.execute(query)
+ if ret and ret.c > 0:
+ return True
- @property
- def hashes(self):
- hashes = []
- for h in self.db.query("SELECT hash FROM tracker_hashes"):
- hashes.append(h["hash"].lower())
+ return False
- return hashes
+ def insert_peer(self, peer_id, info_hash, address6=None, port6=None, address4=None, port4=None):
+ exists = self.peer_exists(peer_id, info_hash)
+ if exists:
+ return
- @property
- def now(self):
- return int(time.time())
+ self.db.execute("INSERT INTO tracker(id, hash, address6, port6, address4, port4) \
+ VALUES(%s, %s, %s, %s, %s, %s)", peer_id, info_hash, address6, port6, address4, port4)
- @property
- def since(self):
- return int(time.time() - self.interval)
+ def remove_peer(self, peer_id, info_hash):
+ self.db.execute("DELETE FROM tracker \
+ WHERE id = %s AND hash = %s", peer_id, info_hash)
- @property
- def interval(self):
- return self._interval + random.randint(*self.random_interval)
+ def scrape(self, info_hashes):
+ ret = {
+ "files" : {},
+ "flags" : {
+ "min_request_interval" : self.interval,
+ }
+ }
- @property
- def min_interval(self):
- return self._min_interval + random.randint(*self.random_interval)
+ for info_hash in info_hashes:
+ ret["files"][info_hash] = {
+ "complete" : self.complete(info_hash),
+ "incomplete" : self.incomplete(info_hash),
+ "downloaded" : 0,
+ }
+
+ return ret
##### This is borrowed from the bittorrent client libary #####
import datetime
import textile
-from databases import Databases
-from misc import Singleton
-
-class Wishlist(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
+from misc import Object
+class Wishlist(Object):
def get(self, slug):
wish = self.db.get("SELECT * FROM wishlist WHERE slug = %s", slug)
def get_all_running(self):
return self.get_all_by_query("SELECT * FROM wishlist \
- WHERE DATE(NOW()) >= date_start AND DATE(NOW()) <= date_end AND status = 'running' \
+ WHERE (CASE \
+ WHEN date_end IS NULL THEN \
+ NOW() >= date_start AND goal >= donated \
+ ELSE \
+ NOW() BETWEEN date_start AND date_end \
+ END) AND status = 'running' \
ORDER BY prio ASC, date_end ASC")
def get_all_finished(self, limit=5, offset=None):
- query = "SELECT * FROM wishlist WHERE DATE(NOW()) > date_end AND status IS NOT NULL \
+ query = "SELECT * FROM wishlist \
+ WHERE (CASE \
+ WHEN date_end IS NULL THEN \
+ donated >= goal \
+ ELSE \
+ NOW() > date_end \
+ END) AND status IS NOT NULL \
ORDER BY date_end DESC"
args = []
if limit:
+ query += " LIMIT %s"
+ args.append(limit)
+
if offset:
- query += " LIMIT %s,%s"
- args += [limit, offset]
- else:
- query += " LIMIT %s"
- args.append(limit)
+ query += " OFFSET %s"
+ args.append(offset)
return self.get_all_by_query(query, *args)
def get_hot_wishes(self, limit=3):
query = "SELECT * FROM wishlist \
- WHERE status = %s AND DATE(NOW()) BETWEEN date_start AND date_end AND ( \
- ((UNIX_TIMESTAMP() - UNIX_TIMESTAMP(date_start)) <= 864000) \
- OR ((UNIX_TIMESTAMP(date_end) - UNIX_TIMESTAMP()) <= 1209600) \
- OR ((donated / goal) >= 0.9) \
- OR (goal >= 3000) \
- OR (prio <= 5) \
- ) ORDER BY prio ASC, date_end ASC LIMIT %s"
+ WHERE \
+ status = %s \
+ AND \
+ date_start <= NOW() \
+ AND \
+ (CASE WHEN date_end IS NOT NULL THEN \
+ NOW() BETWEEN date_start AND date_end \
+ ELSE \
+ TRUE \
+ END) \
+ AND \
+ (AGE(NOW(), date_start) <= INTERVAL '10 days' \
+ OR \
+ AGE(date_end, NOW()) <= INTERVAL '14 days' \
+ OR \
+ (donated / goal) >= 0.85 \
+ OR \
+ goal >= 3000 \
+ OR \
+ prio <= 5 \
+ ) \
+ ORDER BY prio ASC, date_end ASC LIMIT %s"
return self.get_all_by_query(query, "running", limit)
@property
def running(self):
- if self.remaining_days < 0:
- return False
+ if self.date_end:
+ if self.remaining_days and self.remaining_days < 0:
+ return False
+
+ else:
+ if self.donated >= self.goal:
+ return False
return True
@property
def running_days(self):
- today = datetime.datetime.today()
- today = today.date()
-
- running = today - self.date_start
+ running = datetime.datetime.today() - self.date_start
return running.days
@property
def remaining_days(self):
- today = datetime.datetime.today()
- today = today.date()
-
- remaining = self.date_end - today
- return remaining.days
+ if self.date_end:
+ remaining = self.date_end - datetime.datetime.today()
+ return remaining.days
def is_new(self):
return self.running_days < 10
raise tornado.web.HTTPError(404)
self.render("static/%s" % name, lang=self.locale.code[:2])
+
+
+class GeoIPHandler(BaseHandler):
+ def get_address(self):
+ addr = self.get_argument("addr", None)
+
+ if not addr:
+ addr = self.get_remote_ip()
+
+ return addr
+
+ def get(self):
+ addr = self.get_address()
+
+ peer = self.geoip.get_all(addr)
+ if peer:
+ peer["country_name"] = self.geoip.get_country_name(peer.country)
+
+ self.render("geoip/index.html", addr=addr, peer=peer)
import backend
class AdminBaseHandler(BaseHandler):
- @property
- def downloads(self):
- return backend.Downloads()
-
def get_current_user(self):
return self.get_secure_cookie("account")
class AdminMirrorsBaseHandler(AdminBaseHandler):
- @property
- def mirrors(self):
- return backend.Mirrors()
+ pass
class AdminMirrorsHandler(AdminMirrorsBaseHandler):
@tornado.web.authenticated
def get(self):
- mirrors = self.mirrors.list()
+ mirrors = self.mirrors.get_all()
self.render("admin-mirrors.html", mirrors=mirrors)
@tornado.web.authenticated
def get(self, id=None):
if id:
- mirror = self.db.get("SELECT * FROM mirrors WHERE id = '%s'", int(id))
+ mirror = self.db.get("SELECT * FROM mirrors WHERE id = %s", id)
else:
mirror = tornado.database.Row(
id="",
class AdminNewsHandler(AdminNewsBaseHandler):
@tornado.web.authenticated
def get(self):
- news = self.news.list()
+ news = self.news.get_all()
self.render("admin-news.html", news=news)
import tornado.locale
import tornado.web
-import backend
-
def format_size(b):
units = ["B", "k", "M", "G"]
unit_pointer = 0
return ret
+ def get_remote_ip(self):
+ # Fix for clients behind a proxy that sends "X-Forwarded-For".
+ ip_addr = self.request.remote_ip.split(", ")
+
+ if ip_addr:
+ ip_addr = ip_addr[-1]
+
+ return ip_addr
+
+ def get_remote_location(self):
+ if not hasattr(self, "__remote_location"):
+ remote_ip = self.get_remote_ip()
+
+ self.__remote_location = self.geoip.get_location(remote_ip)
+
+ return self.__remote_location
+
@property
def backend(self):
return self.application.backend
+ @property
+ def db(self):
+ return self.backend.db
+
@property
def advertisements(self):
- return backend.Advertisements()
+ return self.backend.advertisements
@property
def accounts(self):
return self.backend.accounts
@property
- def banners(self):
- return backend.Banners()
+ def downloads(self):
+ return self.backend.downloads
+
+ @property
+ def iuse(self):
+ return self.backend.iuse
@property
def memcached(self):
- return backend.Memcached()
+ return self.backend.memcache
@property
def mirrors(self):
- return backend.Mirrors()
+ return self.backend.mirrors
+
+ @property
+ def netboot(self):
+ return self.backend.netboot
@property
def news(self):
- return backend.News()
+ return self.backend.news
@property
def config(self):
- return backend.Config()
+ return self.backend.settings
@property
def releases(self):
- return backend.Releases()
+ return self.backend.releases
@property
- def banners(self):
- return backend.Banners()
+ def geoip(self):
+ return self.backend.geoip
@property
- def geoip(self):
- return backend.GeoIP()
+ def stasy(self):
+ return self.backend.stasy
@property
def tracker(self):
- return backend.Tracker()
+ return self.backend.tracker
@property
def planet(self):
@property
def wishlist(self):
- return backend.Wishlist()
+ return self.backend.wishlist
import backend
+from handlers_base import BaseHandler
+
BASEDIR = os.path.dirname(__file__)
def word_wrap(s, width=45):
lines.append(paragraph.lstrip())
return '\n'.join(lines)
-class BootBaseHandler(tornado.web.RequestHandler):
- @property
- def netboot(self):
- return backend.NetBoot()
+class BootBaseHandler(BaseHandler):
+ pass
class MenuGPXEHandler(BootBaseHandler):
class MenuCfgHandler(BootBaseHandler):
- def _menu_string(self, menu, level=0):
- s = ""
-
- for entry in menu:
- s += self._menu_entry(entry, level=level)
-
- return s
-
- def _menu_entry(self, entry, level=0):
- lines = []
-
- ident = "\t" * level
-
- if entry.type == "seperator":
- lines.append(ident + "menu separator")
-
- elif entry.type == "header":
- lines.append(ident + "menu begin %d" % entry.id)
- lines.append(ident + "\tmenu title %s" % entry.title)
-
- # Add "Back..." entry
- lines.append(ident + "\tlabel %d.back" % entry.id)
- lines.append(ident + "\t\tmenu label Back...")
- lines.append(ident + "\t\tmenu exit")
- lines.append(ident + "\tmenu separator")
-
- lines.append("%s" % self._menu_string(entry.submenu, level=level+1))
- lines.append(ident + "menu end")
-
- elif entry.type == "config":
- config = self.netboot.get_config(entry.item)
-
- lines.append(ident + "label %d" % config.id)
- lines.append(ident + "\tmenu label %s" % config.title)
- if config.description:
- lines.append(ident + "\ttext help")
- lines.append(word_wrap(config.description))
- lines.append(ident + "\tendtext")
-
- lines.append(ident + "\tkernel %s" % config.image1)
- if config.image2:
- lines.append(ident + "\tinitrd %s" % config.image2)
- if config.args:
- lines.append(ident + "\tappend %s" % config.args)
-
- return "\n".join(lines + [""])
-
def get(self):
self.set_header("Content-Type", "text/plain")
- menu = self._menu_string(self.netboot.get_menu(1))
+ latest_release = self.releases.get_latest()
+ stable_releases = self.releases.get_stable()
+ try:
+ stable_releases.remove(latest_release)
+ except ValueError:
+ pass
+
+ development_releases = self.releases.get_unstable()
- self.render("netboot/menu.cfg", menu=menu)
+ self.render("netboot/menu.cfg", latest_release=latest_release,
+ stable_releases=stable_releases, development_releases=development_releases)
class DownloadsReleaseHandler(BaseHandler):
def get(self, release):
- release = self.releases.get_by_id(release)
+ release = self.releases.get_by_sname(release)
+
+ if not release:
+ release = self.releases.get_by_id(release)
+
if not release:
raise tornado.web.HTTPError(404)
class DownloadFileHandler(BaseHandler):
- def head(self, filename):
+ def prepare(self):
self.set_header("Pragma", "no-cache")
+ def head(self, filename):
+ self.redirect_to_mirror(filename)
+
+ def get(self, filename):
+ self.redirect_to_mirror(filename, log_download=True)
+
+ def find_mirror(self, filename):
# Get all mirrors...
mirrors = self.mirrors.get_all()
mirrors = mirrors.get_with_file(filename)
# Find mirrors located near to the user.
# If we have not found any, we use all.
- mirrors_nearby = mirrors.get_for_location(self.request.remote_ip)
- if mirrors_nearby:
- mirrors = mirrors_nearby
+ remote_location = self.get_remote_location()
- mirror = mirrors.get_random()
+ if remote_location:
+ mirrors_nearby = mirrors.get_for_location(remote_location)
- self.redirect(mirror.url + filename[len(mirror.prefix):])
- return mirror
+ if mirrors_nearby:
+ mirrors = mirrors_nearby
- def get(self, filename):
- mirror = self.head(filename)
+ return mirrors.get_random()
+
+ def redirect_to_mirror(self, filename, log_download=False):
+ # Find a random mirror.
+ mirror = self.find_mirror(filename)
+
+ # Construct the redirection URL.
+ download_url = mirror.build_url(filename)
+
+ # Redirect the request.
+ self.redirect(download_url)
- # Record the download.
- country_code = self.geoip.get_country(self.request.remote_ip)
- self.mirrors.db.execute("INSERT INTO log_download(filename, mirror, country_code) VALUES(%s, %s, %s)",
- filename, mirror.id, country_code)
+ if not log_download:
+ return
+
+ remote_location = self.get_remote_location()
+ if remote_location:
+ country_code = remote_location.country
+ else:
+ country_code = None
+
+ self.db.execute("INSERT INTO log_download(filename, mirror, country_code) \
+ VALUES(%s, %s, %s)", filename, mirror.id, country_code)
class DownloadCompatHandler(BaseHandler):
self.redirect("/%s" % _filename)
+
class DownloadSplashHandler(BaseHandler):
def get(self):
self.render("download-splash.html")
import backend
class IUseImage(BaseHandler):
- @property
- def iuse(self):
- return backend.IUse()
-
- @property
- def stasy(self):
- return backend.Stasy()
-
def get_error_html(self, status_code, **kwargs):
"""
Select a random image from the errors directory
raise tornado.web.HTTPError(404, "Profile '%s' was not found." % profile_id)
# Render the image
- image = image_cls(self, profile).to_string()
+ image = image_cls(self.backend, self, profile).to_string()
# Save the image to the memcache for 15 minutes
self.memcached.set(mem_id, image, 15*60)
class MirrorIndexHandler(BaseHandler):
def get(self):
- ip_addr = self.get_argument("addr", self.request.remote_ip)
+ ip_addr = self.get_argument("addr", None)
+ if not ip_addr:
+ ip_addr = self.get_remote_ip()
+
+ location = self.geoip.get_location(ip_addr)
# Get a list of all mirrors.
- all_mirrors = self.mirrors.get_all()
+ mirrors = self.mirrors.get_all()
# Choose the preferred ones by their location.
- preferred_mirrors = all_mirrors.get_for_location(ip_addr)
-
- # Remove the preferred ones from the list of the rest.
- other_mirrors = all_mirrors - preferred_mirrors
+ preferred_mirrors = mirrors.get_for_location(location)
self.render("mirrors.html",
- preferred_mirrors=preferred_mirrors, other_mirrors=other_mirrors)
+ preferred_mirrors=preferred_mirrors, mirrors=mirrors)
class MirrorItemHandler(BaseHandler):
- def get(self, id):
- mirror = self.mirrors.get(id)
+ def get(self, what):
+ mirror = self.mirrors.get_by_hostname(what)
if not mirror:
- raise tornado.web.HTTPError(404)
+ mirror = self.mirrors.get(id)
- ip_addr = self.get_argument("addr", self.request.remote_ip)
- client_location = self.geoip.get_all(ip_addr)
+ if not mirror:
+ raise tornado.web.HTTPError(404, what)
+
+ ip_addr = self.get_argument("addr", None)
+ if not ip_addr:
+ ip_addr = self.get_remote_ip()
+ client_location = self.geoip.get_location(ip_addr)
client_distance = mirror.distance_to(client_location, ignore_preference=True)
- client_distance *= 111.32 # to km
- self.render("mirrors-item.html", item=mirror,
- client_distance=client_distance)
+ self.render("mirrors-item.html", item=mirror, client_distance=client_distance)
class MirrorHandler(BaseHandler):
lines = []
for m in mirrors:
- if not m.mirrorlist or not m.is_pakfire2():
+ if not m.mirrorlist:
continue
# Skip all non-development mirrors
if development and not m.development:
continue
- path = [m.path,]
-
- if m.type == "full":
- path.append("pakfire2")
+ path = [m.path, "pakfire2"]
if suffix:
path.append(suffix)
#!/usr/bin/python
+import re
import tornado.web
from backend.tracker import bencode, bdecode, decode_hex
self.redirect("http://downloads.ipfire.org/%s.torrent" % file.filename)
-#class TrackerTorrentsHandler(BaseHandler):
-# @property
-# def tracker(self):
-# return self.tracker
-#
-# def get(self):
-# releases = []
-#
-# for release in self.releases.get_all():
-# if not release.torrent_hash:
-# continue
-#
-# release.torrent_hash = release.torrent_hash.lower()
-#
-# release.torrent_peers = self.tracker.incomplete(release.torrent_hash)
-# release.torrent_seeds = self.tracker.complete(release.torrent_hash)
-#
-# releases.append(release)
-#
-# self.render("tracker-torrents.html", releases=releases)
-
-
-class TrackerBaseHandler(tornado.web.RequestHandler):
- @property
- def tracker(self):
- return backend.Tracker()
-
+class TrackerBaseHandler(BaseHandler):
def get_hexencoded_argument(self, name, all=False):
try:
arguments = self.request.arguments[name]
return arguments[0]
def send_tracker_error(self, error_message):
- self.write(bencode({"failure reason" : error_message }))
- self.finish()
+ msg = bencode({"failure reason" : error_message })
+ self.finish(msg)
class TrackerAnnounceHandler(TrackerBaseHandler):
- def get(self):
+ def prepare(self):
self.set_header("Content-Type", "text/plain")
+ def get_ipv6_address(self, default_port):
+ # Get the external IP address of the client.
+ addr = self.get_remote_ip()
+
+ if ":" in addr:
+ return addr, default_port
+
+ # IPv6
+ ipv6 = self.get_argument("ipv6", None)
+ if ipv6:
+ port = default_port
+
+ m = re.match("^\[(.*)\]\:(\d)$", ipv6)
+ if m:
+ ipv6, port = (m.group(1), m.group(2))
+
+ return ipv6, port
+
+ return None, None
+
+ def get_ipv4_address(self, default_port):
+ # Get the external IP address of the client.
+ addr = self.get_remote_ip()
+
+ if not ":" in addr:
+ return addr, default_port
+
+ # IPv4
+ ipv4 = self.get_argument("ipv4", None)
+ if ipv4:
+ return ipv4, default_port
+
+ ip = self.get_argument("ip", None)
+ if ip:
+ return ip, default_port
+
+ return None, None
+
+ def get_port(self):
+ # Get the port and check it for sanity
+ port = self.get_argument("port", None)
+
+ try:
+ port = int(port)
+
+ if port < 0 or port > 65535:
+ raise ValueError
+ except (TypeError, ValueError):
+ port = None
+
+ return port
+
+ def get(self):
+ # Get the info hash
info_hash = self.get_hexencoded_argument("info_hash")
if not info_hash:
- self.send_tracker_error("Your client forgot to send your torrent's info_hash.")
+ self.send_tracker_error("Your client forgot to send your torrent's info_hash")
return
- # Fix for clients behind a proxy that sends "X-Forwarded-For".
- ip_addr = self.request.remote_ip.split(", ")
- if ip_addr:
- ip_addr = ip_addr[-1]
+ # Get the peer id
+ peer_id = self.get_hexencoded_argument("peer_id")
- peer = {
- "id" : self.get_hexencoded_argument("peer_id"),
- "ip" : ip_addr,
- "port" : self.get_argument("port", None),
- "downloaded" : self.get_argument("downloaded", 0),
- "uploaded" : self.get_argument("uploaded", 0),
- "left" : self.get_argument("left", 0),
- }
-
- event = self.get_argument("event", "")
- if not event in ("started", "stopped", "completed", ""):
- self.send_tracker_error("Got unknown event")
+ # Get the port and check it for sanity
+ port = self.get_port()
+ if not port:
+ self.send_tracker_error("Invalid port number or port number missing")
return
- if peer["port"]:
- peer["port"] = int(peer["port"])
+ addr_ipv6, port_ipv6 = self.get_ipv6_address(port)
+ addr_ipv4, port_ipv4 = self.get_ipv4_address(port)
- if peer["port"] < 0 or peer["port"] > 65535:
- self.send_tracker_error("Port number is not in valid range")
+ # Handle events
+ event = self.get_argument("event", None)
+ if event:
+ if not event in ("started", "stopped", "completed"):
+ self.send_tracker_error("Got unknown event")
return
- eventhandlers = {
- "started" : self.tracker.event_started,
- "stopped" : self.tracker.event_stopped,
- "completed" : self.tracker.event_completed,
- }
+ self.tracker.handle_event(event, peer_id, info_hash,
+ address6=addr_ipv6, port6=port_ipv6, address4=addr_ipv4, port4=port_ipv4)
- if event:
- eventhandlers[event](info_hash, peer["id"])
+ peer_info = {
+ "address6" : addr_ipv6,
+ "port6" : port_ipv6,
+ "address4" : addr_ipv4,
+ "port4" : port_ipv4,
+ "downloaded" : self.get_argument("downloaded", 0),
+ "uploaded" : self.get_argument("uploaded", 0),
+ "left_data" : self.get_argument("left", 0),
+ }
- self.tracker.update(hash=info_hash, **peer)
+ self.tracker.update_peer(peer_id, info_hash, **peer_info)
no_peer_id = self.get_argument("no_peer_id", False)
numwant = self.get_argument("numwant", self.tracker.numwant)
- self.write(bencode({
- "tracker id" : self.tracker.id,
- "interval" : self.tracker.interval,
+ peers = self.tracker.get_peers(info_hash, limit=numwant, no_peer_id=no_peer_id)
+
+ response = bencode({
+ "tracker id" : self.tracker.tracker_id,
+ "interval" : self.tracker.interval,
"min interval" : self.tracker.min_interval,
- "peers" : self.tracker.get_peers(info_hash, limit=numwant,
- random=True, no_peer_id=no_peer_id),
- "complete" : self.tracker.complete(info_hash),
- "incomplete" : self.tracker.incomplete(info_hash),
- }))
- self.finish()
+ "peers" : peers,
+ "complete" : self.tracker.complete(info_hash),
+ "incomplete" : self.tracker.incomplete(info_hash),
+ })
+ self.finish(response)
+
+ def on_finish(self):
+ """
+ Cleanup after every request.
+ """
+ self.tracker.cleanup_peers()
class TrackerScrapeHandler(TrackerBaseHandler):
def get(self):
info_hashes = self.get_hexencoded_argument("info_hash", all=True)
- self.write(bencode(self.tracker.scrape(hashes=info_hashes)))
- self.finish()
+ response = self.tracker.scrape(info_hashes)
+
+ self.finish(bencode(response))
import hashlib
import logging
import operator
+import re
import socket
import textile
import tornado.escape
import tornado.locale
import tornado.web
+import unicodedata
from tornado.database import Row
return self.render_string("modules/ads/%s.html" % where, ad=ad)
+class MapModule(UIModule):
+ def render(self, latitude, longitude):
+ return self.render_string("modules/map.html", latitude=latitude, longitude=longitude)
+
+
class MenuModule(UIModule):
def render(self):
return self.render_string("modules/menu.html")
+class MirrorItemModule(UIModule):
+ def render(self, item):
+ return self.render_string("modules/mirror-item.html", item=item)
+
+
+class MirrorsTableModule(UIModule):
+ def render(self, mirrors, preferred_mirrors=[]):
+ return self.render_string("modules/mirrors-table.html",
+ mirrors=mirrors, preferred_mirrors=preferred_mirrors)
+
+
+class NetBootMenuConfigModule(UIModule):
+ def render(self, release):
+ return self.render_string("netboot/menu-config.cfg", release=release)
+
+
+class NetBootMenuHeaderModule(UIModule):
+ def render(self, title, releases):
+ id = unicodedata.normalize("NFKD", unicode(title)).encode("ascii", "ignore")
+ id = re.sub(r"[^\w]+", " ", id)
+ id = "-".join(id.lower().strip().split())
+
+ return self.render_string("netboot/menu-header.cfg", id=id,
+ title=title, releases=releases)
+
+
+class NetBootMenuSeparatorModule(UIModule):
+ def render(self):
+ return self.render_string("netboot/menu-separator.cfg")
+
+
class NewsItemModule(UIModule):
def get_author(self, author):
# Get name of author
item.text = item.text[:400] + "..."
# Render text
- text_id = "news-%s" % hashlib.md5(item.text.encode("utf-8")).hexdigest()
-
- text = self.memcached.get(text_id)
- if not text:
- text = textile.textile(item.text)
- self.memcached.set(text_id, text, 60)
-
- item.text = text
+ item.text = textile.textile(item.text)
return self.render_string("modules/news-item.html", item=item,
uncut=uncut, announcement=announcement, show_heading=show_heading)
active=active, years=self.news.years)
-class MirrorItemModule(UIModule):
- def render(self, item):
- return self.render_string("modules/mirror-item.html", item=item)
-
-
class SidebarItemModule(UIModule):
def render(self):
return self.render_string("modules/sidebar-item.html")
return self.render_string("modules/stasy-table-geo.html", countries=countries)
-class MirrorsTableModule(UIModule):
- def render(self, mirrors):
- return self.render_string("modules/mirrors-table.html", mirrors=mirrors)
-
-
class WishlistModule(UIModule):
def render(self, wishes, short=False):
return self.render_string("wishlist/modules/wishlist.html",