first i18n implementation. It's far from complete yet

This commit is contained in:
EnTeQuAk 2008-07-08 11:19:28 +02:00
parent 449de7d79d
commit f29491f8dd
15 changed files with 185 additions and 146 deletions

View File

@ -16,6 +16,9 @@ from datetime import datetime, timedelta
from werkzeug import SharedDataMiddleware, ClosingIterator
from werkzeug.exceptions import HTTPException, NotFound
from babel import Locale
from lodgeit import i18n
from lodgeit.utils import _local_manager, ctx, jinja_environment, \
Request
from lodgeit.database import metadata, session, Paste
@ -29,17 +32,38 @@ class LodgeIt(object):
def __init__(self, dburi, secret_key):
#: the secret key used by the captcha
self.secret_key = secret_key
#: name of the error handler
self.not_found = ('static/not_found', {})
self.engine = sqlalchemy.create_engine(dburi, convert_unicode=True)
#: make sure all tables exist.
metadata.create_all(self.engine)
#: 18n setup
#TODO: load from user cookie
self.locale = None
self.set_locale('de_DE')
#: jinja_environment update
jinja_environment.filters.update(
datetimeformat=i18n.format_datetime
)
#: bind the application to the current context local
self.bind_to_context()
def bind_to_context(self):
ctx.application = self
def set_locale(self, locale):
if not self.locale or self.locale.language != locale:
self.locale = Locale(locale)
self.translations = i18n.load_translations(self.locale)
#: update gettext translations
jinja_environment.install_gettext_translations(self.translations)
def __call__(self, environ, start_response):
"""Minimal WSGI application for request dispatching."""
#: bind the application to the new context local

View File

@ -12,6 +12,7 @@ from werkzeug import redirect, Response
from werkzeug.exceptions import NotFound
from lodgeit.utils import ctx, render_template
from lodgeit.i18n import list_languages, _
from lodgeit.controllers import BaseController
from lodgeit.database import session, Paste
from lodgeit.lib import antispam
@ -41,13 +42,13 @@ class PasteController(BaseController):
spam = ctx.request.form.get('webpage') or antispam.is_spam(code)
if spam:
error = 'your paste contains spam'
error = _('your paste contains spam')
captcha = getform('captcha')
if captcha:
if check_hashed_solution(captcha):
error = None
else:
error += ' and the CAPTCHA solution was incorrect'
error += _(' and the CAPTCHA solution was incorrect')
show_captcha = True
if code and language and not error:
paste = Paste(code, language, parent, ctx.request.user_hash,
@ -163,6 +164,15 @@ class PasteController(BaseController):
if style_name in STYLES:
resp.set_cookie('style', style_name)
return resp
def set_language(self):
"""Minimal view that set's a different language. Redirects
back to the page the user is coming from."""
lang = ctx.request.form.get('language')
resp = redirect(ctx.request.environ.get('HTTP_REFERER') or '/')
if lang in list_languages():
ctx.application.set_locale(lang)
return resp
def show_captcha(self):
"""Show a captcha."""

View File

@ -11,15 +11,16 @@
from werkzeug.exceptions import NotFound
from lodgeit.utils import ctx, render_template
from lodgeit.i18n import _
from lodgeit.controllers import BaseController
from lodgeit.lib.xmlrpc import xmlrpc
HELP_PAGES = [
('pasting', 'Pasting'),
('advanced', 'Advanced Features'),
('xmlrpc', 'Using the XMLRPC Interface'),
('integration', 'Scripts and Editor Integration')
('pasting', _('Pasting')),
('advanced', _('Advanced Features')),
('xmlrpc', _('Using the XMLRPC Interface')),
('integration', _('Scripts and Editor Integration'))
]
known_help_pages = set(x[0] for x in HELP_PAGES)

View File

@ -8,6 +8,7 @@
:copyright: 2007 by Armin Ronacher.
:license: BSD
"""
from lodgeit.i18n import _
import pygments
from pygments.util import ClassNotFound
from pygments.lexers import get_lexer_by_name
@ -19,51 +20,51 @@ from pygments.formatters import HtmlFormatter
#: we use a hardcoded list here because we want to keep the interface
#: simple
LANGUAGES = {
'text': 'Text',
'python': 'Python',
'pycon': 'Python Console Sessions',
'pytb': 'Python Tracebacks',
'html+php': 'PHP',
'html+django': 'Django / Jinja Templates',
'html+mako': 'Mako Templates',
'html+myghty': 'Myghty Templates',
'apache': 'Apache Config (.htaccess)',
'bash': 'Bash',
'bat': 'Batch (.bat)',
'c': 'C',
'cpp': 'C++',
'csharp': 'C#',
'css': 'CSS',
'd': 'D',
'minid': 'MiniD',
'smarty': 'Smarty',
'html': 'HTML',
'html+php': 'PHP',
'html+genshi': 'Genshi Templates',
'js': 'JavaScript',
'java': 'Java',
'jsp': 'JSP',
'lua': 'Lua',
'haskell': 'Haskell',
'scheme': 'Scheme',
'ruby': 'Ruby',
'irb': 'Interactive Ruby',
'perl': 'Perl',
'rhtml': 'eRuby / rhtml',
'tex': 'TeX / LaTeX',
'xml': 'XML',
'rst': 'reStructuredText',
'irc': 'IRC Logs',
'diff': 'Unified Diff',
'vim': 'Vim Scripts',
'ocaml': 'OCaml',
'sql': 'SQL',
'squidconf': 'SquidConf',
'sourceslist': 'sources.list',
'erlang': 'Erlang',
'vim': 'Vim',
'dylan': 'Dylan',
'gas': 'GAS'
'text': _('Text'),
'python': _('Python'),
'pycon': _('Python Console Sessions'),
'pytb': _('Python Tracebacks'),
'html+php': _('PHP'),
'html+django': _('Django / Jinja Templates'),
'html+mako': _('Mako Templates'),
'html+myghty': _('Myghty Templates'),
'apache': _('Apache Config (.htaccess)'),
'bash': _('Bash'),
'bat': _('Batch (.bat)'),
'c': _('C'),
'cpp': _('C++'),
'csharp': _('C#'),
'css': _('CSS'),
'd': _('D'),
'minid': _('MiniD'),
'smarty': _('Smarty'),
'html': _('HTML'),
'html+php': _('PHP'),
'html+genshi': _('Genshi Templates'),
'js': _('JavaScript'),
'java': _('Java'),
'jsp': _('JSP'),
'lua': _('Lua'),
'haskell': _('Haskell'),
'scheme': _('Scheme'),
'ruby': _('Ruby'),
'irb': _('Interactive Ruby'),
'perl': _('Perl'),
'rhtml': _('eRuby / rhtml'),
'tex': _('TeX / LaTeX'),
'xml': _('XML'),
'rst': _('reStructuredText'),
'irc': _('IRC Logs'),
'diff': _('Unified Diff'),
'vim': _('Vim Scripts'),
'ocaml': _('OCaml'),
'sql': _('SQL'),
'squidconf': _('SquidConf'),
'sourceslist': _('sources.list'),
'erlang': _('Erlang'),
'vim': _('Vim'),
'dylan': _('Dylan'),
'gas': _('GAS')
}
STYLES = dict((x, x.title()) for x in get_all_styles())

View File

@ -9,6 +9,7 @@
:license: BSD
"""
import math
from lodgeit.i18n import _
def generate_pagination(page, per_page, total, link_builder=None,
@ -71,15 +72,15 @@ def generate_pagination(page, per_page, total, link_builder=None,
if next_link:
if next is not None:
result.append(u' <a href="%s">Next &raquo;</a>' %
result.append(_(u' <a href="%(link)s">Next &raquo;</a>') %
link_builder(next))
elif gray_next_link:
result.append(u' <span class="disabled">Next &raquo;</span>')
result.append(_(u' <span class="disabled">Next &raquo;</span>'))
if prev_link:
if prev is not None:
result.insert(0, u'<a href="%s">&laquo; Prev</a> ' %
result.insert(0, _(u'<a href="%(link)s">&laquo; Prev</a> ') %
link_builder(prev))
elif gray_prev_link:
result.insert(0, u'<span class="disabled">&laquo; Prev</span> ')
result.insert(0, _(u'<span class="disabled">&laquo; Prev</span> '))
return u''.join(result)

View File

@ -29,17 +29,18 @@ _local_manager = LocalManager(ctx)
#: jinja environment for all the templates
jinja_environment = Environment(loader=FileSystemLoader(
path.join(path.dirname(__file__), 'views')))
path.join(path.dirname(__file__), 'views')),
extensions=['jinja2.ext.i18n'])
_word_only = partial(re.compile(r'[^a-zA-Z0-9]').sub, '')
def datetimeformat(obj):
"""Helper filter for the template"""
return obj.strftime('%Y-%m-%d @ %H:%M')
def get_application():
return getattr(ctx, 'application', None)
jinja_environment.filters['datetimeformat'] = datetimeformat
def get_request():
return getattr(ctx, 'request', None)
def generate_user_hash():

View File

@ -1,64 +1,64 @@
{% extends "layout.html" %}
{% set page_title = 'About LodgeIt' %}
{% set page_title = _('About LodgeIt') %}
{% set active_page = 'about' %}
{% block body %}
<div class="text">
<h3 id="why-the-hell-another-pastebin">Why the hell another pastebin?</h3>
<p>
<h3 id="why-the-hell-another-pastebin">{% trans %} Why the hell another pastebin?{% endtrans %}</h3>
<p>{% trans %}
Good question. Basically the world doesn't need another pastebin.
There is <a href="http://pastie.caboo.se/">pastie</a> and
<a href="http://dpaste.com/">dpaste.com</a> which
both use kick-ass highlighting libraries for highlighting the
code and both have an intuitive user interface. Nevertheless there
are some features which are unique to LodgeIt.
are some features which are unique to LodgeIt.{% endtrans %}
</p>
<h3 id="features">Features</h3>
<h3 id="features">{% trans %}Features{% endtrans %}</h3>
<ul>
<li>clean user interface</li>
<li>different color schemes for the sourcecode</li>
<li>reply to pastes</li>
<li>diffs of different pastes</li>
<li>support for many python template languages</li>
<li>support for many scripting languages like Python and Ruby, even with
weird syntax (ruby *cough*)</li>
<li><a href="/help/xmlrpc/">XMLRPC support</a></li>
<li>command-line <a href="http://dev.pocoo.org/hg/lodgeit-main/raw-file/-1/scripts/lodgeit.py">client script</a></li>
<li><a href="http://www.vim.org/scripts/script.php?script_id=1965">vim integration</a></li>
<li><a href="http://lunaryorn.de/projects/paste/">emacs integration</a></li>
<li>persistent pastes</li>
<li>reply notification</li>
<li>valid HTML 4.0</li>
<li>{% trans %}clean user interface{% endtrans %}</li>
<li>{% trans %}different color schemes for the sourcecode{% endtrans %}</li>
<li>{% trans %}reply to pastes{% endtrans %}</li>
<li>{% trans %}diffs of different pastes{% endtrans %}</li>
<li>{% trans %}support for many python template languages{% endtrans %}</li>
<li>{% trans %}support for many scripting languages like Python and Ruby, even with
weird syntax (ruby *cough*){% endtrans %}</li>
<li><a href="/help/xmlrpc/">{% trans %}XMLRPC support{% endtrans %}</a></li>
<li>{% trans %}command-line <a href="http://dev.pocoo.org/hg/lodgeit-main/raw-file/-1/scripts/lodgeit.py">client script</a>{% endtrans %}</li>
<li><a href="http://www.vim.org/scripts/script.php?script_id=1965">{% trans %}vim integration{% endtrans %}</a></li>
<li><a href="http://lunaryorn.de/projects/paste/">{% trans %}emacs integration{% endtrans %}</a></li>
<li>{% trans %}persistent pastes{% endtrans %}</li>
<li>{% trans %}reply notification{% endtrans %}</li>
<li>{% trans %}valid HTML 4.0{% endtrans %}</li>
</ul>
<h3 id="request-more-languages">Request More Languages</h3>
<p>
<h3 id="request-more-languages">{% trans %}Request More Languages{% endtrans %}</h3>
<p>{% trans %}
A language is missing in the list? File a ticket in the
<a href="http://dev.pocoo.org/projects/pygments">Pygments trac</a> and we add that as soon
as possible.
as possible.{% endtrans %}
</p>
<h3 id="software-used">Software Used</h3>
<h3 id="software-used">{% trans %}Software Used{% endtrans %}</h3>
<ul>
<li><a href="http://pygments.pocoo.org/">Pygments</a> for syntax highlighting</li>
<li><a href="http://www.python.org/">Python</a> as scripting language</li>
<li><a href="http://jinja.pocoo.org/2">Jinja 2</a> for templating</li>
<li><a href="http://werkzeug.pocoo.org/">Werkzeug</a> for the WSGI implementation</li>
<li><a href="http://www.sqlalchemy.org">SQLAlchemy</a> as database layer</li>
<li><a href="http://www.jquery.com/">jQuery</a> for scripting</li>
<li>{% trans %}<a href="http://pygments.pocoo.org/">Pygments</a> for syntax highlighting{% endtrans %}</li>
<li>{% trans %}<a href="http://www.python.org/">Python</a> as scripting language{% endtrans %}</li>
<li>{% trans %}<a href="http://jinja.pocoo.org/2">Jinja 2</a> for templating{% endtrans %}</li>
<li>{% trans %}<a href="http://werkzeug.pocoo.org/">Werkzeug</a> for the WSGI implementation{% endtrans %}</li>
<li>{% trans %}<a href="http://www.sqlalchemy.org">SQLAlchemy</a> as database layer{% endtrans %}</li>
<li>{% trans %}<a href="http://www.jquery.com/">jQuery</a> for scripting{% endtrans %}</li>
</ul>
<h3 id="who">Who?</h3>
<p>
<h3 id="who">{% trans %}Who?{% endtrans %}</h3>
<p>{% trans %}
This paste was founded by <a href="http://lucumr.pocoo.org/">Armin Ronacher</a> from the pocoo
team and is now maintained by <a href="http://webshox.org">Christopher Grebs</a>.
Pygments is a pocoo project led by Georg Brandl.
Pygments is a pocoo project led by Georg Brandl.{% endtrans %}
</p>
<h3 id="privacy">Privacy</h3>
<p>
<h3 id="privacy">{% trans %}Privacy{% endtrans %}</h3>
<p>{% trans %}
LodgeIt does not use user accounts because it's logging in for using a
pastebin is useles. However this pastebin creates unique user ids for you
and for 31 days. Whenever you return to the pastebin it will notify you
about replies to your pastes. If you don't want to have that feature you
can let lodgeit forget about you by
<a href="javascript:LodgeIt.removeCookie()">removing the cookie</a>.
Please note that on the next request you will get a new id.
Please note that on the next request you will get a new id.{% endtrans %}
</p>
</div>
{% endblock %}

View File

@ -19,9 +19,9 @@
<div id="header"><h1>Lodge It</h1></div>
<ul id="navigation">
{%- for href, id, caption in [
('/', 'new', 'New'),
('/all/', 'all', 'All'),
('/about/', 'about', 'About'),
('/', 'new', _('New')),
('/all/', 'all', _('All')),
('/about/', 'about', _('About')),
('/help/', 'help', '?')
] %}
<li{% if active_page == id %} class="active"{%
@ -32,29 +32,30 @@
<h2>{{ page_title|e }}</h2>
{%- if new_replies %}
<div class="notification">
<h3>Someone Replied To Your Paste</h3>
<h3>{% trans %}Someone Replied To Your Paste{% endtrans %}</h3>
{% for paste in new_replies %}
<p>
on {{ paste.pub_date|datetimeformat }} someone replied to
your paste <a href="{{ paste.parent.url|e }}">#{{ paste.parent.paste_id }}</a>,
in paste <a href="{{ paste.url|e }}">#{{ paste.paste_id }}</a>. Click here to
<a href="/compare/{{ paste.paste_id }}/{{ paste.parent.paste_id }}/">compare
those two pastes</a>.
<p>{% trans date=paste.pub_date|datetimeformat, parent=paste.parent.paste_id,
paste=paste.paste_id, paste_url=paste.url|e, parent_url=paste.parnent.url|e %}
on {{ date }} someone replied to your paste
<a href="{{ parent_url }}">#{{ parent }}</a>,
in paste <a href="{{ paste_url }}">#{{ paste }}</a>. Click here to
<a href="/compare/{{ paste }}/{{ parent }}/">compare
those two pastes</a>.{% endtrans %}
</p>
{% endfor %}
<p><a href="javascript:LodgeIt.hideNotification()">hide this notification</a></p>
<p><a href="javascript:LodgeIt.hideNotification()">{% trans %}hide this notification{% endtrans %}</a></p>
</div>
{% elif request.first_visit %}
<div class="notification">
<h3>Welcome On LodgeIt</h3>
<p>
<h3>{% trans %}Welcome On LodgeIt{% endtrans %}</h3>
<p>{%- trans -%}
Welcome to the LodgeIt pastebin. In order to use the notification feature
a 31 day cookie with an unique ID was created for you. The lodgeit database
does not store any information about you, it's just used for an advanced
pastebin experience :-). Read more on the <a href="/about/#privacy">about
lodgeit</a> page. Have fun :-)
lodgeit</a> page. Have fun :-){%- endtrans -%}
</p>
<p><a href="javascript:LodgeIt.hideNotification()">hide this notification</a></p>
<p><a href="javascript:LodgeIt.hideNotification()">{% trans %}hide this notification{% endtrans %}</a></p>
</div>
{% endif -%}
{% block body %}{% endblock -%}

View File

@ -1,20 +1,20 @@
{% extends "layout.html" %}
{% set page_title = 'New Paste' %}
{% set page_title = _('New Paste') %}
{% set active_page = 'new' %}
{% block body %}
<form action="/" method="post" class="submitform">
{%- if error %}
<div class="notification">
<h3>Error While Pasting</h3>
<p>Could not submit your paste because {{ error|e }}.</p>
<h3>{% trans %}Error While Pasting{% endtrans %}</h3>
<p>{% trans error=error|e %}Could not submit your paste because {{ error }}.{% endtrans %}</p>
{%- if show_captcha %}
<div class="captcha">
<p>Please fill out the CAPTCHA to proceed:</p>
<img src="/_captcha.png" alt="a captcha you can't see. Sorry :(">
<p>{% trans %}Please fill out the CAPTCHA to proceed:{% endtrans %}</p>
<img src="/_captcha.png" alt="{% trans %}a captcha you can't see. Sorry :({% endtrans %}">
<input type="text" name="captcha" size="20">
</div>
{%- else %}
<p><a href="javascript:LodgeIt.hideNotification()">hide this message</a></p>
<p><a href="javascript:LodgeIt.hideNotification()">{% trans %}hide this message{% endtrans %}</a></p>
{%- endif %}
</div>
{%- endif %}
@ -29,10 +29,10 @@
{%- endfor %}
</select>
<input type="text" value="" name="webpage" id="webpage">
<input type="submit" value="Paste!">
<input type="submit" value="{% trans %}Paste!{% endtrans %}">
<input type="button" value="▲" onclick="LodgeIt.resizeTextarea(-100)">
<input type="button" value="▼" onclick="LodgeIt.resizeTextarea(100)">
<input type="checkbox" name="private" id="private"{% if private
%} checked{% endif %}><label for="private">make this paste private</label>
%} checked{% endif %}><label for="private">{% trans %}make this paste private{% endtrans %}</label>
</form>
{% endblock %}

View File

@ -1,16 +1,16 @@
{% extends "layout.html" %}
{% set page_title = 'Page Not Found' %}
{% set page_title = _('Page Not Found') %}
{% block body %}
<p>
Sorry, but the page you requested was not found on this server.
{% trans %}Sorry, but the page you requested was not found on this server.{% endtrans %}
</p>
<p>
<p>{% trans %}
We've recently updated this pastebin. While it is out goal for nothing to get
lost, you may have found a page that was mis-placed. Check your URL to ensure
you have gone where you intended. If everything looks OK and you still see
this error page, please consider <a href="/about">contacting us</a>.
this error page, please consider <a href="/about">contacting us</a>.{% endtrans %}
</p>
<p>
Click <a href="/">here</a> to add a new paste.
{% trans %}Click <a href="/">here</a> to add a new paste.{% endtrans %}
</p>
{% endblock %}

View File

@ -1,10 +1,10 @@
{% extends "layout.html" %}
{% set page_title = 'Paste Tree' %}
{% set page_title = _('Paste Tree') %}
{% set active_page = 'all' %}
{% block body %}
<p>
<p>{% trans %}
Here you can see the requested tree of paste replies. The paste you're
coming from is highlighted.
coming from is highlighted.{% endtrans %}
</p>
<ul class="paste_tree">
{%- for paste in [paste] recursive %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% set page_title = 'All Pastes' %}
{% set page_title = _('All Pastes') %}
{% set active_page = 'all' %}
{% block body %}
<ul class="paste_list">

View File

@ -3,18 +3,18 @@
{% set active_page = 'all' %}
{% block body %}
<div class="related">
<h3><a href="javascript:LodgeIt.toggleRelatedBox()">Paste Details</a></h3>
<h3><a href="javascript:LodgeIt.toggleRelatedBox()">{% trans %}Paste Details{% endtrans %}</a></h3>
<div class="content">
<p>posted on {{ paste.pub_date|datetimeformat }}</p>
<p>{% trans pub_date=paste.pub_date|datetimeformat %}posted on {{ pub_date }}{% endtrans %}</p>
<ul>
<li><a class="autoclose" href="/?reply_to={{ paste.identifier }}">reply to this paste</a></li>
<li><a class="autoclose" href="/?reply_to={{ paste.identifier }}">{% trans %}reply to this paste{% endtrans %}</a></li>
{% if paste.parent %}
<li><a class="autoclose" href="/compare/{{ paste.identifier }}/{{
paste.parent.identifier }}/">compare it with the parent paste</a></li>
<li><a class="autoclose" href="{{ paste.parent.url|e }}">look at the parent paste</a></li>
paste.parent.identifier }}/">{% trans %}compare it with the parent paste{% endtrans %}</a></li>
<li><a class="autoclose" href="{{ paste.parent.url|e }}">{% trans %}look at the parent paste{% endtrans %}</a></li>
{% endif %}
{% if paste.children %}
<li>the following pastes replied to this paste:
<li>{% trans %}the following pastes replied to this paste:{% endtrans %}
{% for child in paste.children %}
<a class="autoclose" href="{{ child.url|e }}">#{{ child.identifier }}</a>
{%- if not loop.last %},{% endif -%}
@ -22,24 +22,24 @@
</li>
{% endif %}
{% if paste.parent or paste.children %}
<li><a href="/tree/{{ paste.identifier }}/">show paste tree</a></li>
<li><a href="/tree/{{ paste.identifier }}/">{% trans %}show paste tree{% endtrans %}</a></li>
{% endif %}
<li><a href="/raw/{{ paste.identifier }}/">download paste</a></li>
<li>compare with paste <form action="/compare/" method="post">
<li><a href="/raw/{{ paste.identifier }}/">{% trans %}download paste{% endtrans %}</a></li>
<li>{% trans %}compare with paste{% endtrans %} <form action="/compare/" method="post">
<input type="hidden" name="old" value="{{ paste.identifier }}">
<input type="text" name="new" value="#">
<input type="submit" value="compare">
<input type="submit" value="{% trans %}compare{% endtrans %}">
</form></li>
<li>select different colorscheme <form action="/colorscheme/" method="post">
<li>{% trans %}select different colorscheme{% endtrans %} <form action="/colorscheme/" method="post">
<select name="style">
{%- for key, caption in styles|dictsort %}
<option value="{{ key }}"{% if key == style
%} selected="selected"{% endif %}>{{ caption }}</option>
{%- endfor %}
</select>
<input type="submit" value="change">
<input type="submit" value="{% trans %}change{% endtrans %}">
</form></li>
<li><a href="?linenos={{ linenos and 'no' or 'yes' }}" onclick="LodgeIt.toggleLineNumbers(); return false;">toggle line numbers</a></li>
<li><a href="?linenos={{ linenos and 'no' or 'yes' }}" onclick="LodgeIt.toggleLineNumbers(); return false;">{% trans %}toggle line numbers{% endtrans %}</a></li>
</ul>
</div>
</div>

View File

@ -1,13 +1,13 @@
{% extends "layout.html" %}
{% set page_title = "XMLRPC" %}
{% set page_title = _('XMLRPC') %}
{% set active_page = 'about' %}
{% block body %}
<div class="text">
<h3>XMLRPC Entrypoint</h3>
<p>
<h3>{% trans %}XMLRPC Entrypoint{% endtrans %}</h3>
<p>{% trans %}
This is the entrypoint for the XMLRPC system. If you're interested
in using it head over to the <a href="/help/xmlrpc/">XMLRPC
documentation</a>.
in using it head over to the <a href="/help/xmlrpc/">XMLRPC documentation</a>.
{%- endtrans %}
</p>
</div>
{% endblock %}