Convert Zulip to use Jinja2 templates.

This results in a substantial performance improvement for all of
Zulip's backend templates.

Changes in templates:
- Change `block.super` to `super()`.
- Remove `load` tag because Jinja2 doesn't support it.
- Use `minified_js()|safe` instead of `{% minified_js %}`.
- Use `compressed_css()|safe` instead of `{% compressed_css %}`.
- `forloop.first` -> `loop.first`.
- Use `{{ csrf_input }}` instead of `{% csrf_token %}`.
- Use `{# ... #}` instead of `{% comment %}`.
- Use `url()` instead of `{% url %}`.
- Use `_()` instead of `{% trans %}` because in Jinja `trans` is a block tag.
- Use `{% trans %}` instead of `{% blocktrans %}`.
- Use `{% raw %}` instead of `{% verbatim %}`.

Changes in tools:
- Check for `trans` block in `check-templates` instead of `blocktrans`

Changes in backend:
- Create custom `render_to_response` function which takes `request` objects
  instead of `RequestContext` object. There are two reasons to do this:
    1. `RequestContext` is not compatible with Jinja2
    2. `RequestContext` in `render_to_response` is deprecated.
- Add Jinja2 related support files in zproject/jinja2 directory. It
  includes a custom backend and a template renderer, compressors for js
  and css and Jinja2 environment handler.
- Enable `slugify` and `pluralize` filters in Jinja2 environment.

Fixes #620.
This commit is contained in:
Umair Khan 2016-04-21 11:48:33 +05:00 committed by Tim Abbott
parent cec0530fd8
commit 5359e6b0d4
64 changed files with 706 additions and 524 deletions

View File

@ -4,10 +4,9 @@ from typing import Any, Dict, List, Tuple
from django.db import connection
from django.template import RequestContext, loader
from django.utils.html import mark_safe
from django.shortcuts import render_to_response
from django.core import urlresolvers
from django.http import HttpResponseNotFound
from jinja2 import Markup as mark_safe
from zerver.decorator import has_request_variables, REQ, zulip_internal
from zerver.models import get_realm, UserActivity, UserActivityInterval, Realm
@ -25,6 +24,8 @@ from six.moves import range
from six.moves import zip
eastern_tz = pytz.timezone('US/Eastern')
from zproject.jinja2 import render_to_response
def make_table(title, cols, rows, has_row_class=False):
if not has_row_class:
@ -569,7 +570,7 @@ def get_activity(request):
return render_to_response(
'analytics/activity.html',
dict(data=data, title=title, is_home=True),
context_instance=RequestContext(request)
request=request
)
def get_user_activity_records_for_realm(realm, is_bot):
@ -863,7 +864,7 @@ def get_realm_activity(request, realm):
return render_to_response(
'analytics/activity.html',
dict(data=data, realm_link=realm_link, title=title),
context_instance=RequestContext(request)
request=request
)
@zulip_internal
@ -883,5 +884,5 @@ def get_user_activity(request, email):
return render_to_response(
'analytics/activity.html',
dict(data=data, title=title),
context_instance=RequestContext(request)
request=request
)

View File

@ -10,6 +10,7 @@ from django.template import RequestContext
from django.conf import settings
from confirmation.models import Confirmation
from zproject.jinja2 import render_to_response
def confirm(request, confirmation_key):
@ -39,5 +40,4 @@ def confirm(request, confirmation_key):
if obj:
# if we have an object, we can use specific template
templates.insert(0, 'confirmation/confirm_%s.html' % obj._meta.model_name)
return render_to_response(templates, ctx,
context_instance=RequestContext(request))
return render_to_response(templates, ctx, request=request)

View File

@ -47,6 +47,18 @@ Views
| ``zerver/views/__init__.py`` | other Django views |
+--------------------------------+-----------------------------------------+
Jinja2 Compatibility Files
==========================
+-------------------------------------+--------------------------------------------------------------------+
| ``zproject/jinja2/__init__.py`` | Jinja2 environment |
+-------------------------------------+--------------------------------------------------------------------+
| ``zproject/jinja2/backends.py`` | Jinja2 backend |
+-------------------------------------+--------------------------------------------------------------------+
| ``zproject/jinja2/compressors.py`` | Jinja2 compatible functions of Django-Pipeline |
+-------------------------------------+--------------------------------------------------------------------+
Static assets
=============
@ -67,7 +79,7 @@ Templates
=========
+--------------------------+--------------------------------------------------------+
| ``templates/zerver`` | For templates related to zerver views |
| ``templates/zerver`` | For Jinja2 templates for the backend (for zerver app) |
+--------------------------+--------------------------------------------------------+
| ``static/templates`` | Handlebars templates for the frontend |
+--------------------------+--------------------------------------------------------+

View File

@ -55,7 +55,7 @@ new event that is sent to clients, be sure to add a handler for it to
**CSS:** The primary CSS file is ``static/styles/zulip.css``. If your new
feature requires UI changes, you may need to add additional CSS to this file.
**Templates:** The initial page structure is rendered via Django templates
**Templates:** The initial page structure is rendered via Jinja2 templates
located in ``templates/zerver``. For JavaScript, Zulip uses Handlebars templates located in
``static/templates``. Templates are precompiled as part of the build/deploy
process.

View File

@ -13,6 +13,7 @@ class zulip::app_frontend_base {
"python-django-guardian",
"python-django-pipeline",
"python-django-bitfield",
"python-jinja2",
# Needed for mock objects in decorators
"python-mock",
# Tornado dependencies

View File

@ -3,7 +3,7 @@
{% block for_you %} isn't feeling too good. {% endblock %}
{% block customhead %}
{{ block.super }}
{{ super() }}
<meta http-equiv="refresh" content="60;URL='/'">
{% endblock %}

View File

@ -1,8 +1,5 @@
{% extends "zerver/base.html" %}
{% load compressed %}
{% load minified_js %}
{# User Activity. #}
{% block title %}
@ -11,9 +8,9 @@
{% block customhead %}
{{ block.super }}
{% minified_js 'activity' %}
{% compressed_css 'activity' %}
{{ super() }}
{{ minified_js('activity')|safe }}
{{ compressed_css('activity')|safe }}
{% endblock %}
{% block content %}
@ -31,7 +28,7 @@
<ul class="nav nav-tabs">
{% for name, activity in data %}
<li {% if forloop.first %} class="active" {% endif %}>
<li {% if loop.first %} class="active" {% endif %}>
<a href="#{{ name|slugify }}" data-toggle="tab">{{ name }}</a>
</li>
{% endfor %}
@ -41,8 +38,8 @@
{% for name, activity in data %}
<div class="tab-pane {% if forloop.first %} active {% endif %}" id="{{ name|slugify }}">
{{ activity }}
<div class="tab-pane {% if loop.first %} active {% endif %}" id="{{ name|slugify }}">
{{ activity|safe }}
</div>
{% endfor %}

View File

@ -3,7 +3,7 @@
{% block content %}
<form id="register" action="/accounts/register/" method="post">
{% csrf_token %}
{{ csrf_input }}
<input type="hidden" value="{{ key }}" name="key"/>
<input type="hidden" value="1" name="from_confirmation"/>
</form>

View File

@ -2,14 +2,14 @@
{% block content %}
{% comment %}
{#
This template is referenced by the confirmation code and does not have the
requisite context to make a useful signup form. Therefore, we immediately
post to another view which executes in our code to produce the desired form.
{% endcomment %}
#}
<form id="register" action="/accounts/register/" method="post">
{% csrf_token %}
{{ csrf_input }}
<input type="hidden" value="{{ key }}" name="key"/>
<input type="hidden" value="1" name="from_confirmation"/>
<input type="hidden" value="{% if full_name %}{{ full_name }}{% endif %}" name="full_name"/>

View File

@ -1,7 +1,7 @@
Psst. Word on the street is that you forgot your password, {{ email}}.
It's all good. Follow the link below and we'll take care of the rest:
<{{ protocol}}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb64=uid token=token %}>
<{{ protocol}}://{{ domain }}{{ url('django.contrib.auth.views.password_reset_confirm', uidb64=uid, token=token) }}>
Thanks,
Your friends at Zulip HQ

View File

@ -1,34 +1,33 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{% comment %}
{#
Allow the user to accept the terms, creating an email record of that fact.
{% endcomment %}
#}
{% block for_you %}for {% if company_name %} {{company_name}} {% else %} __________ {% endif %} {% endblock %}
{% block portico_content %}
<p>({% trans "Welcome! We think you'll like it here" %}.)</p>
<p>({{ _("Welcome! We think you'll like it here") }}.)</p>
<div class="pitch">
<hr/>
<p>{% trans "You're almost there. We just need you to do one last thing" %}.</p>
<h3>{% trans "Accept the Zulip terms of service" %}</h3>
<p>{{ _("You're almost there. We just need you to do one last thing") }}.</p>
<h3>{{ _("Accept the Zulip terms of service") }}</h3>
</div>
<form method="post" class="form-horizontal" id="registration" action="{% url 'zerver.views.accounts_accept_terms' %}">
{% csrf_token %}
<form method="post" class="form-horizontal" id="registration" action="{{ url('zerver.views.accounts_accept_terms') }}">
{{ csrf_input }}
<div class="control-group">
<label for="id_email" class="control-label">{% trans "Email" %}</label>
<label for="id_email" class="control-label">{{ _("Email") }}</label>
<div class="controls fakecontrol">
<p>{{ email }}</p>
</div>
</div>
<div class="control-group">
<label for="id_full_name" class="control-label">{% trans "Your name" %}</label>
<label for="id_full_name" class="control-label">{{ _("Your name") }}</label>
<div class="controls">
<input id="id_full_name" class="required" type="text" name="full_name"
value="{% if form.full_name.value %}{{ form.full_name.value }}{% endif %}"
value="{% if form.full_name.value() %}{{ form.full_name.value() }}{% endif %}"
maxlength="100" />
{% if form.full_name.errors %}
{% for error in form.full_name.errors %}
@ -41,17 +40,17 @@ Allow the user to accept the terms, creating an email record of that fact.
<div class="control-group">
<div class="controls">
<label class="checkbox">
{% comment %}
{#
This is somewhat subtle.
Checkboxes have a name and value, and when the checkbox is ticked, the form posts
with name=value. If the checkbox is unticked, the field just isn't present at all.
This is distinct from 'checked', which determines whether the checkbox appears
at all. (So, it's not symmetric to the code above.)
{% endcomment %}
#}
<input id="id_terms" class="required" type="checkbox" name="terms"
{% if form.terms.value %}checked="checked"{% endif %} />
{% trans "I agree to the" %} <a href="/terms">{% trans "Terms of Service" %}</a>.
{% if form.terms.value() %}checked="checked"{% endif %} />
{{ _("I agree to the") }} <a href="/terms">{{ _("Terms of Service") }}</a>.
</label>
{% if form.terms.errors %}
{% for error in form.terms.errors %}

View File

@ -1,5 +1,4 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{# Home page for not logged-in users. #}
{# This is where we pitch the app and solicit signups. #}
@ -16,14 +15,14 @@ $(function () {
<div class="register-form">
<p class="lead">
<div class="register-page-header">{% trans "Let's get started" %}…</div>
<div class="register-page-header">{{ _("Let's get started") }}…</div>
</p>
<form class="form-inline" id="send_confirm" name="email_form"
action="{{ current_url }}" method="post">
{% csrf_token %}
<input type="text" class="email required" placeholder="{% trans "Enter your work email address" %}"
action="{{ current_url() }}" method="post">
{{ csrf_input }}
<input type="text" class="email required" placeholder="{{ _("Enter your work email address") }}"
id="email" name="email"/>
<input type="submit" class="btn btn-primary btn-large register-button" value="{% trans "Sign up" %}"/>
<input type="submit" class="btn btn-primary btn-large register-button" value="{{ _("Sign up") }}"/>
</form>
<div id="errors"></div>
{% if form.email.errors %}
@ -32,12 +31,12 @@ $(function () {
{% endfor %}
{% endif %}
<div class="alert alert-pitch" id="company-email">{% blocktrans %}Please use your
<div class="alert alert-pitch" id="company-email">{% trans %}Please use your
company email address to sign up. Otherwise, we wont be able to
connect you with your coworkers{% endblocktrans %}.</div>
connect you with your coworkers{% endtrans %}.</div>
{% if google_auth_enabled %}
<div class="register-google">
<a href="{% url 'zerver.views.start_google_oauth2' %}" class="zocial google register-google-button">{% trans "Sign up with Google" %}</a>
<a href="{{ url('zerver.views.start_google_oauth2') }}" class="zocial google register-google-button">{{ _("Sign up with Google") }}</a>
</div>
{% endif %}
</div>

View File

@ -1,17 +1,16 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{# Displayed after a user attempts to sign up. #}
{% block portico_content %}
<div class="app portico-page">
<div class="app-main portico-page-container">
<h2>{% trans "Thanks for signing up!" %}</h2>
<p class="lead">{% trans "Check your email so we can get started" %}.</p>
<h2>{{ _("Thanks for signing up!") }}</h2>
<p class="lead">{{ _("Check your email so we can get started") }}.</p>
<p>{% blocktrans %}Still no email? We can <a href="#" id="resend_email_link">resend it</a>{% endblocktrans %}.<br/>
<small>({% trans "Just in case, take a look at your Spam folder" %}.)</small></p>
<p>{% trans %}Still no email? We can <a href="#" id="resend_email_link">resend it</a>{% endtrans %}.<br/>
<small>({{ _("Just in case, take a look at your Spam folder") }}.)</small></p>
<form id="resend_confirm" action="/accounts/home/" method="post" style="position: absolute;">
{% csrf_token %}
{{ csrf_input }}
<input type="hidden" class="email" id="email" value="{{ email }}" name="email"/>&nbsp;
</form>
</div>
@ -19,7 +18,7 @@
{% endblock %}
{% block customhead %}
{{ block.super }}
{{ super() }}
<script type="text/javascript">
$(function() {
$("#resend_email_link").click(function () {

View File

@ -39,11 +39,11 @@
<div class="tab-pane active" id="curl">
<p>No download required!</p>
{% comment %}
{#
These code snippets are generated using our very own Zulip tool, by
sending them to myself in a code block, and then using the inspector
to pull out the resulting HTML :)
{% endcomment %}
#}
<h4>Stream message</h4>
<div class="codehilite"><pre>curl {{ external_api_uri }}/v1/messages <span class="se">\</span>

View File

@ -2,11 +2,9 @@
{# API information page #}
{% load minified_js %}
{% block customhead %}
{{ block.super }}
{% minified_js 'api' %}
{{ super() }}
{{ minified_js('api')|safe }}
{% endblock %}

View File

@ -1,12 +1,11 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{# API information page #}
{% block portico_content %}
<div class="apps-page-header">{% blocktrans %}Do we have apps? Appsolutely.{% endblocktrans %}</div>
<div class="apps-muted">{% blocktrans %}Ok, I take it back, I'm sorry, please don't go.{% endblocktrans %}</div>
<div class="apps-page-header">{% trans %}Do we have apps? Appsolutely.{% endtrans %}</div>
<div class="apps-muted">{% trans %}Ok, I take it back, I'm sorry, please don't go.{% endtrans %}</div>
<h3 class="apps-instructions-header">{% blocktrans %}Installation instructions{% endblocktrans %}</h3>
<h3 class="apps-instructions-header">{% trans %}Installation instructions{% endtrans %}</h3>
<ul class="nav nav-tabs" id="apps-tabs">
{% if not_voyager %}
<li class="active"><a href="#android" data-toggle="tab">Android</a></li>
@ -23,10 +22,10 @@
<div class="tab-pane active" id="android">
<img class="screenshot android-screenshot pull-left" src="/static/images/app-screenshots/zulip-android.png" alt="screenshot of the Zulip app on Android" />
<p>{% blocktrans %}Zulip has a free, <strong>100% native app</strong> for Android,
<p>{% trans %}Zulip has a free, <strong>100% native app</strong> for Android,
and you can easily grab it from
the <a href="https://play.google.com/store/apps/details?id=com.zulip.android">Google
Play Store</a>{% endblocktrans %}.</p>
Play Store</a>{% endtrans %}.</p>
<a href="https://play.google.com/store/apps/details?id=com.zulip.android">
<img alt="Get it on Google Play"
@ -37,9 +36,9 @@
<div class="tab-pane" id="iphone">
<img class="screenshot iphone-screenshot pull-left" src="/static/images/app-screenshots/zulip-iphone.png" alt="screenshot of the Zulip app on iOS" />
<p>{% blocktrans %}Zulip has a free, <strong>100% native app</strong> for iPhone and
<p>{% trans %}Zulip has a free, <strong>100% native app</strong> for iPhone and
iPad. Please grab it from
the <a href="http://itunes.com/apps/zulip">App Store</a>{% endblocktrans %}!</p>
the <a href="http://itunes.com/apps/zulip">App Store</a>{% endtrans %}!</p>
<a href="http://itunes.com/apps/zulip">
<img alt="Get it in the App Store" src="/static/images/app-screenshots/ios_badge.png" alt="Apple App Store icon for Zulip" />
@ -48,16 +47,16 @@
</div>
{% endif %}
<div class="tab-pane" id="mac">
<p>{% blocktrans %}You love your Mac. And you love Zulip. So what could be
<p>{% trans %}You love your Mac. And you love Zulip. So what could be
better than a Zulip app for Mac? Enjoy notifications for
messages and PMs in your dock whether you're in Sublime,
emacs, or Photoshop.{% endblocktrans %}</p>
emacs, or Photoshop.{% endtrans %}</p>
<p style="text-align: center">
{% if only_sso %}
<a href="https://zulip.com/dist/apps/sso/mac/Zulip-latest.dmg" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% blocktrans %}Download Zulip for Mac{% endblocktrans %}</a>
<a href="https://zulip.com/dist/apps/sso/mac/Zulip-latest.dmg" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% trans %}Download Zulip for Mac{% endtrans %}</a>
{% else %}
<a href="https://zulip.com/dist/apps/mac/Zulip-latest.dmg" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% blocktrans %}Download Zulip for Mac{% endblocktrans %}</a>
<a href="https://zulip.com/dist/apps/mac/Zulip-latest.dmg" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% trans %}Download Zulip for Mac{% endtrans %}</a>
{% endif %}
</p>
@ -65,12 +64,12 @@
</div>
<div class="tab-pane" id="linux">
<p>{% blocktrans %}Zulip provides a native Linux app that runs standalone
<p>{% trans %}Zulip provides a native Linux app that runs standalone
outside of your browser. How you install it depends on what
you're running:{% endblocktrans %}</p>
you're running:{% endtrans %}</p>
<h3>{% blocktrans %}Debian and Ubuntu{% endblocktrans %}</h3>
{% blocktrans %}We have an APT repository for Zulip, so adding and installing the app is easy:{% endblocktrans %}
<h3>{% trans %}Debian and Ubuntu{% endtrans %}</h3>
{% trans %}We have an APT repository for Zulip, so adding and installing the app is easy:{% endtrans %}
<div class="codehilite"><pre>wget https://zulip.com/dist/keys/user-apt.asc
cat user-apt.asc | sudo apt-key add -
sudo apt-add-repository http://apt.zulip.com/user/
@ -83,29 +82,29 @@ sudo apt-get install zulip-desktop
<h3>{% trans "Other" %}</h3>
<h3>{{ _("Other") }}</h3>
{% if only_sso %}
<p>{% blocktrans %}We provide a <a href="https://zulip.com/dist/apps/sso/linux/zulip-desktop_latest.bin.tar.gz">binary tarball</a> of the Zulip application, built for 64-bit systems.{% endblocktrans %}
<p>{% trans %}We provide a <a href="https://zulip.com/dist/apps/sso/linux/zulip-desktop_latest.bin.tar.gz">binary tarball</a> of the Zulip application, built for 64-bit systems.{% endtrans %}
</p>
{% else %}
<p>{% blocktrans %}We provide a <a href="https://zulip.com/dist/apps/linux/zulip-desktop_latest.bin.tar.gz">binary tarball</a> of the Zulip application, built for 64-bit systems.{% endblocktrans %}
<p>{% trans %}We provide a <a href="https://zulip.com/dist/apps/linux/zulip-desktop_latest.bin.tar.gz">binary tarball</a> of the Zulip application, built for 64-bit systems.{% endtrans %}
</p>
{% endif %}
</div>
<div class="tab-pane" id="windows">
<p>{% blocktrans %}Windows. It's the best OS for your needs: gaming,
<p>{% trans %}Windows. It's the best OS for your needs: gaming,
coding, expense reports. But you always felt that something
was missing... until now.{% endblocktrans %}</p>
was missing... until now.{% endtrans %}</p>
<p>{% blocktrans %}We proudly present <b>Zulip for Windows</b>: the second-best app for Windows on the market today (after
Solitaire, obviously.){% endblocktrans %}</p>
<p>{% trans %}We proudly present <b>Zulip for Windows</b>: the second-best app for Windows on the market today (after
Solitaire, obviously.){% endtrans %}</p>
<p style="text-align: center">
{% if only_sso %}
<a href="https://zulip.com/dist/apps/sso/win/zulip-latest.exe" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% blocktrans %}Download Zulip for Windows{% endblocktrans %}</a>
<a href="https://zulip.com/dist/apps/sso/win/zulip-latest.exe" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% trans %}Download Zulip for Windows{% endtrans %}</a>
{% else %}
<a href="https://zulip.com/dist/apps/win/zulip-latest.exe" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% blocktrans %}Download Zulip for Windows{% endblocktrans %}</a>
<a href="https://zulip.com/dist/apps/win/zulip-latest.exe" class="btn btn-large btn-primary btn-app-download"><i class="icon-vector-download"></i> {% trans %}Download Zulip for Windows{% endtrans %}</a>
{% endif %}
</p>
@ -113,10 +112,10 @@ sudo apt-get install zulip-desktop
</div>
<div class="tab-pane" id="plan9">
<p>{% blocktrans %}First, connect to our hosted 9P filesystem
<p>{% trans %}First, connect to our hosted 9P filesystem
at <code>plan9.zulip.com</code> and then... no, we're
totally kidding. There definitely isn't a version of Zulip
for Plan 9.{% endblocktrans %}</p>
for Plan 9.{% endtrans %}</p>
</div>

View File

@ -1,18 +1,17 @@
{% load i18n %}
<div class="modal hide" id="bankruptcy" tabindex="-1" role="dialog"
aria-labelledby="bankruptcy-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="bankruptcy-label">{% trans 'Welcome back' %}</h3>
<h3 id="bankruptcy-label">{{ _('Welcome back') }}</h3>
</div>
<div id="bankruptcy-unread-count"></div>
<div class="modal-footer">
<button id="yes-bankrupt" class="bankruptcy_button btn btn-primary"
aria-hidden="true">{% trans 'Yes, please!' %}</button>
aria-hidden="true">{{ _('Yes, please!') }}</button>
<button id="no-bankrupt" class="bankruptcy_button btn btn-default"
data-dismiss="modal" aria-hidden="true">{% trans "No, I'll catch up" %}.</button>
data-dismiss="modal" aria-hidden="true">{{ _("No, I'll catch up") }}.</button>
</div>
</div>

View File

@ -2,8 +2,6 @@
<html>
{# Base template for the whole site. #}
{% load compressed %}
{% load minified_js %}
<head>
<meta charset="UTF-8">
@ -25,14 +23,14 @@
{% endif %}
{# We need to import jQuery before Bootstrap #}
{% compressed_css 'common' %}
{{ compressed_css('common')|safe }}
{% block page_params %}
{# blueslip needs page_params.debug_mode. Set it to false by default. #}
<script type="text/javascript">
var page_params = {debug_mode: false};
</script>
{% endblock %}
{% minified_js 'common' %}
{{ minified_js('common')|safe }}
{% block customhead %}
{% endblock %}
</head>

View File

@ -1,11 +1,10 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% block portico_content %}
<h3>{% trans 'Closed realm' %}</h3>
<h3>{{ _('Closed realm') }}</h3>
<p>{% trans 'Hi there! Thank you for your interest in Zulip' %}.</p>
<p>{{ _('Hi there! Thank you for your interest in Zulip') }}.</p>
<p>{% blocktrans %}The organization you are trying to join, {{ closed_domain_name }}, only allows users with e-mail addresses within the organization. Please ask for a new invite to an appropriate e-mail address{% endblocktrans %}.</p>
<p>{% trans %}The organization you are trying to join, {{ closed_domain_name }}, only allows users with e-mail addresses within the organization. Please ask for a new invite to an appropriate e-mail address{% endtrans %}.</p>
{% endblock %}

View File

@ -1,4 +1,3 @@
{% load i18n %}
<div id="compose">
<div id="compose-notifications" class="notifications above-composebox">
</div>
@ -8,14 +7,14 @@
<span class="new_message_button">
<button type="button" class="btn btn-default btn-large compose_stream_button"
id="left_bar_compose_stream_button_big" title="New stream message (c)">
<i class="icon-vector-bullhorn"></i><span class="compose_stream_button_label">&nbsp;&nbsp;{% trans 'New stream message' %}</span>
<i class="icon-vector-bullhorn"></i><span class="compose_stream_button_label">&nbsp;&nbsp;{{ _('New stream message') }}</span>
</button>
</span>
{% if not embedded %}
<span class="new_message_button">
<button type="button" class="btn btn-default btn-large compose_private_button"
id="left_bar_compose_private_button_big" title="New private message (C)">
<i class="icon-vector-user"></i><span class="compose_private_button_label">&nbsp;&nbsp;{% trans 'New private message' %}</span>
<i class="icon-vector-user"></i><span class="compose_private_button_label">&nbsp;&nbsp;{{ _('New private message') }}</span>
</button>
</span>
{% endif %}
@ -32,7 +31,7 @@
<div class="composition-area">
<button type="button" class="close" id='compose_close'>×</button>
<form id="send_message_form" action="/json/messages" method="post">
{% csrf_token %}
{{ csrf_input }}
<table class="compose_table">
<tbody>
<tr class="ztable_layout_row">
@ -44,15 +43,15 @@
</td>
<td class="right_part">
<span id="compose-lock-icon">
<i class="icon-vector-lock" title="{% trans 'This is an invite-only stream' %}"></i>
<i class="icon-vector-lock" title="{{ _('This is an invite-only stream') }}"></i>
</span>
<input type="text" class="recipient_box" name="stream" id="stream"
maxlength="30"
value="" placeholder="{% trans 'Stream' %}" autocomplete="off" tabindex="120"/>
value="" placeholder="{{ _('Stream') }}" autocomplete="off" tabindex="120"/>
<i class="icon-vector-narrow icon-vector-small"></i>
<input type="text" class="recipient_box" name="subject" id="subject"
maxlength="60"
value="" placeholder="{% trans 'Topic' %}" autocomplete="off" tabindex="130"/>
value="" placeholder="{{ _('Topic') }}" autocomplete="off" tabindex="130"/>
</td>
</tr>
<tr id="private-message">
@ -61,28 +60,28 @@
</td>
<td class="right_part">
<div class="pm_recipient">
<span class="you_text">{% trans 'You and' %}</span>
<span class="you_text">{{ _('You and') }}</span>
<input type="text" class="recipient_box" name="recipient" id="private_message_recipient"
value="" placeholder="{% trans 'one or more people' %}..." autocomplete="off" tabindex="130"/>
value="" placeholder="{{ _('one or more people') }}..." autocomplete="off" tabindex="130"/>
</div>
</td>
</tr>
<tr>
<td class="messagebox" colspan="2">
<textarea class="new_message_textarea" name="content" id="new_message_content"
value="" placeholder="{% trans 'Compose your message here' %}..." tabindex="140" maxlength="10000"></textarea>
value="" placeholder="{{ _('Compose your message here') }}..." tabindex="140" maxlength="10000"></textarea>
<div id="below-compose-content">
<input type="file" id="file_input" class="notvisible pull-left" multiple />
<a class="message-control-button icon-vector-dropbox notdisplayed"
id="attach_dropbox_files" href="#" title="{% trans 'Attach files from Dropbox' %}"></a>
id="attach_dropbox_files" href="#" title="{{ _('Attach files from Dropbox') }}"></a>
<a class="message-control-button icon-vector-paper-clip notdisplayed"
id="attach_files" href="#" title="{% trans 'Attach files' %}"></a>
id="attach_files" href="#" title="{{ _('Attach files') }}"></a>
<a class="message-control-button icon-vector-font"
href="#markdown-help" title="Formatting" data-toggle="modal"></a>
<a id="restore-draft" onclick="compose.restore_message();">{% trans 'Restore draft' %}</a>
<span id="sending-indicator">{% trans 'Sending' %}...</span>
<a id="restore-draft" onclick="compose.restore_message();">{{ _('Restore draft') }}</a>
<span id="sending-indicator">{{ _('Sending') }}...</span>
<div id="send_controls">
<label id="enter-sends-label" class="compose_checkbox_label" for="enter_sends">{% trans 'Press Enter to send' %}&nbsp;</label>
<label id="enter-sends-label" class="compose_checkbox_label" for="enter_sends">{{ _('Press Enter to send') }}&nbsp;</label>
<input type="checkbox" id="enter_sends" name="enter_sends" value="enter_sends" />
<input type="submit" value="Send" id="compose-send-button" class="btn btn-primary send_message" tabindex="150"/>
</div>

View File

@ -1,14 +1,13 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% block portico_content %}
<h3>{% trans 'Deactivated organization' %}</h3>
<h3>{{ _('Deactivated organization') }}</h3>
<p>{% trans 'Hi there! Thank you for your interest in Zulip' %}.</p>
<p>{{ _('Hi there! Thank you for your interest in Zulip') }}.</p>
<p>{% blocktrans %} The organization you are trying to join, {{ deactivated_domain_name }}, has
<p>{% trans %} The organization you are trying to join, {{ deactivated_domain_name }}, has
been deactivated. Please
contact <a href="mailto:{{ zulip_administrator }}">{{ zulip_administrator }}</a> to reactivate
this group{% endblocktrans %}.</p>
this group{% endtrans %}.</p>
{% endblock %}

View File

@ -1,9 +1,9 @@
{% comment %}
{#
Debug tab of the app.
Included if Django's DEBUG = True and the query
parameter ?show_debug is present.
{% endcomment %}
#}
<style>
/* Hack to make it scrollable */

View File

@ -1,7 +1,7 @@
{% load app_filters %}
{% comment %}
{#
Mail sent to a user who hasn't logged in for 24 hours.
{% endcomment %}
#}
Hello {{ name }},

View File

@ -1,7 +1,7 @@
{% load app_filters %}
{% comment %}
{#
Mail sent to a user who hasn't logged in for 24 hours.
{% endcomment %}
#}
Hello {{ name }},

View File

@ -1,151 +1,150 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% block portico_content %}
<div class="feature-page-header">{% blocktrans %}Zulip Features{% endblocktrans %}</div>
<div class="feature-page-header">{% trans %}Zulip Features{% endtrans %}</div>
<div class="feature-block left">
<i class="icon-vector-random icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Threaded group conversations{% endblocktrans %}</h4>
<p>{% blocktrans %}Talk about multiple topics at once without getting lost or
overwhelmed.{% endblocktrans %}</p>
<h4>{% trans %}Threaded group conversations{% endtrans %}</h4>
<p>{% trans %}Talk about multiple topics at once without getting lost or
overwhelmed.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-comments icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}One-on-one and group private conversations{% endblocktrans %}</h4>
<p>{% blocktrans %}Have private conversations with one or as many people as you need.{% endblocktrans %}</p>
<h4>{% trans %}One-on-one and group private conversations{% endtrans %}</h4>
<p>{% trans %}Have private conversations with one or as many people as you need.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-home icon-vector-3x feature-icon"></i>
<h4>{% trans "Persistence" %}</h4>
<p>{% blocktrans %}We're always receiving messages for you, even when you're
logged out.{% endblocktrans %}</p>
<h4>{{ _("Persistence") }}</h4>
<p>{% trans %}We're always receiving messages for you, even when you're
logged out.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-road icon-vector-3x feature-icon"></i>
<h4>{% trans "History" %}</h4>
<p>{% blocktrans %}Join a stream and see its history, so even new team
members are never out of the loop.{% endblocktrans %}</p>
<h4>{{ _("History") }}</h4>
<p>{% trans %}Join a stream and see its history, so even new team
members are never out of the loop.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-search icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Full-history search{% endblocktrans %}</h4>
<p>{% blocktrans %}Search is both snappy and smart, helping you look for text,
<h4>{% trans %}Full-history search{% endtrans %}</h4>
<p>{% trans %}Search is both snappy and smart, helping you look for text,
people, and threads of conversation, with advanced search
operators for fine-grained control.{% endblocktrans %}</p>
operators for fine-grained control.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-group icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Team presence and buddy list{% endblocktrans %}</h4>
<p>{% blocktrans %}See who is online at a glance.{% endblocktrans %}</p>
<h4>{% trans %}Team presence and buddy list{% endtrans %}</h4>
<p>{% trans %}See who is online at a glance.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-picture icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Inline image, video, and tweet previews{% endblocktrans %}</h4>
<p>{% blocktrans %}Send a link and we'll automatically generate an inline
preview.{% endblocktrans %}</p>
<h4>{% trans %}Inline image, video, and tweet previews{% endtrans %}</h4>
<p>{% trans %}Send a link and we'll automatically generate an inline
preview.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-paper-clip icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Drag-and-drop file uploads{% endblocktrans %}</h4>
<p>{% blocktrans %}Drag a file into the compose box and we'll upload and
<h4>{% trans %}Drag-and-drop file uploads{% endtrans %}</h4>
<p>{% trans %}Drag a file into the compose box and we'll upload and
preview it for you. Sharing and discussing work with team
mates has never been easier.{% endblocktrans %}</p>
mates has never been easier.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-user icon-vector-3x feature-icon"></i>
<h4>{% trans "@-notifications" %}</h4>
<p>{% blocktrans %}Want someone's attention in a conversation? @-notify them
and they'll be right over.{% endblocktrans %}</p>
<h4>{{ _("@-notifications") }}</h4>
<p>{% trans %}Want someone's attention in a conversation? @-notify them
and they'll be right over.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-bullhorn icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Stream-wide announcements{% endblocktrans %}</h4>
<p>{% blocktrans %}Use <code>@all</code> or <code>@everyone</code> to get the
attention of everyone in a stream.{% endblocktrans %}</p>
<h4>{% trans %}Stream-wide announcements{% endtrans %}</h4>
<p>{% trans %}Use <code>@all</code> or <code>@everyone</code> to get the
attention of everyone in a stream.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-envelope icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Emails for important missed messages{% endblocktrans %}</h4>
<p>{% blocktrans %}If you're missing important conversations when you're away from
<h4>{% trans %}Emails for important missed messages{% endtrans %}</h4>
<p>{% trans %}If you're missing important conversations when you're away from
Zulip, we'll send you an email summary so you're always in the
loop.{% endblocktrans %}</p>
loop.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-info-sign icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Desktop notifications{% endblocktrans %}</h4>
<p>{% blocktrans %}Configurable for private and stream messages.{% endblocktrans %}</p>
<h4>{% trans %}Desktop notifications{% endtrans %}</h4>
<p>{% trans %}Configurable for private and stream messages.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-bell icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Audible notifications{% endblocktrans %}</h4>
<p>{% blocktrans %}So you don't miss important messages even when your eyes
are elsewhere.{% endblocktrans %}</p>
<h4>{% trans %}Audible notifications{% endtrans %}</h4>
<p>{% trans %}So you don't miss important messages even when your eyes
are elsewhere.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-font icon-vector-3x feature-icon"></i>
<h4>{% trans "Hotkeys" %}</h4>
<p>{% blocktrans %}Communicate as efficiently as you use your favorite text editor.{% endblocktrans %}</p>
<h4>{{ _("Hotkeys") }}</h4>
<p>{% trans %}Communicate as efficiently as you use your favorite text editor.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-thumbs-up icon-vector-3x feature-icon"></i>
<h4>{% trans "Emoji" %}</h4>
<p>{% blocktrans %}Sometimes it's the simple things in life, like being able
to give a <tt>:thumbsup:</tt> while chatting.{% endblocktrans %}</p>
<h4>{{ _("Emoji") }}</h4>
<p>{% trans %}Sometimes it's the simple things in life, like being able
to give a <tt>:thumbsup:</tt> while chatting.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-edit icon-vector-3x feature-icon"></i>
<h4>{% trans "Code" %}</h4>
<p>{% blocktrans %}Discuss code, even multi-line code, with ease, including
syntax-highlighting.{% endblocktrans %}</p>
<h4>{{ _("Code") }}</h4>
<p>{% trans %}Discuss code, even multi-line code, with ease, including
syntax-highlighting.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-quote-left icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Lightweight markup{% endblocktrans %}</h4>
<p>{% blocktrans %}Get bulleted lists, clickable links, and nicely-formatted
e-mail pastes automatically.{% endblocktrans %}</p>
<h4>{% trans %}Lightweight markup{% endtrans %}</h4>
<p>{% trans %}Get bulleted lists, clickable links, and nicely-formatted
e-mail pastes automatically.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-eraser icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Message editing{% endblocktrans %}</h4>
<p>{% blocktrans %}Don't worry, you can always fix that typo.{% endblocktrans %}</p>
<h4>{% trans %}Message editing{% endtrans %}</h4>
<p>{% trans %}Don't worry, you can always fix that typo.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-lock icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Invite-only streams{% endblocktrans %}</h4>
<p>{% blocktrans %}Enjoy the benefits of threaded conversations while
controlling your audience and privacy.{% endblocktrans %}</p>
<h4>{% trans %}Invite-only streams{% endtrans %}</h4>
<p>{% trans %}Enjoy the benefits of threaded conversations while
controlling your audience and privacy.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-star-empty icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Starred messages{% endblocktrans %}</h4>
<p>{% blocktrans %}Keep a todo list or keep track of interesting
conversations.{% endblocktrans %}</p>
<h4>{% trans %}Starred messages{% endtrans %}</h4>
<p>{% trans %}Keep a todo list or keep track of interesting
conversations.{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-github icon-vector-3x feature-icon"></i>
<h4>{% trans "Integrations" %}</h4>
<p>{% blocktrans %}Get alerts and updates from your favorite services with
<h4>{{ _("Integrations") }}</h4>
<p>{% trans %}Get alerts and updates from your favorite services with
off-the-shelf <a href="/integrations">integrations</a> for
Trac, Nagios, Github, Jenkins, and more.{% endblocktrans %}</p>
Trac, Nagios, Github, Jenkins, and more.{% endtrans %}</p>
</div>
<div class="feature-block">
<i class="icon-vector-sitemap icon-vector-3x feature-icon"></i>
<h4>{% trans "API" %}</h4>
<p>{% blocktrans %}Want to roll your own notifications? We've got a
<h4>{{ _("API") }}</h4>
<p>{% trans %}Want to roll your own notifications? We've got a
dead-simple RESTful <a href="/api">API and Python bindings</a>
that will make integrations&mdash;both sending and
receiving&mdash;a snap!{% endblocktrans %}</p>
receiving&mdash;a snap!{% endtrans %}</p>
</div>
<div class="feature-block left">
<i class="icon-vector-mobile-phone icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Mobile apps{% endblocktrans %}</h4>
<p>{% blocktrans %}Check Zulip on the go with native <a href="/apps">iOS and
Android apps</a>{% endblocktrans %}.</p>
<h4>{% trans %}Mobile apps{% endtrans %}</h4>
<p>{% trans %}Check Zulip on the go with native <a href="/apps">iOS and
Android apps</a>{% endtrans %}.</p>
</div>
<div class="feature-block">
<i class="icon-vector-desktop icon-vector-3x feature-icon"></i>
<h4>{% blocktrans %}Desktop apps{% endblocktrans %}</h4>
<p>{% blocktrans %}Prefer Zulip in its own window and rich, OS-level notifications?
Enjoy <a href="/apps">Zulip on your desktop</a>{% endblocktrans %}.</p>
<h4>{% trans %}Desktop apps{% endtrans %}</h4>
<p>{% trans %}Prefer Zulip in its own window and rich, OS-level notifications?
Enjoy <a href="/apps">Zulip on your desktop</a>{% endtrans %}.</p>
</div>
{% endblock %}

View File

@ -1,5 +1,4 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% block hello_page_container %} hello-main{% endblock %}
{% block hello_page_footer %} hello-footer{% endblock %}
{% block os_announcement %}
@ -8,10 +7,10 @@
<img src="/static/images/logo/zballoon.png" class="os-illustration" alt="Zulip balloon" />
<div class="main-headline-text">
<span class="tagline os-tagline">
{% trans 'Zulip has been released as open source software!' %}
{{ _('Zulip has been released as open source software!') }}
</span>
<span class="footnote os-footnote">
{% blocktrans %}Read the <a href="https://blogs.dropbox.com/tech/2015/09/open-sourcing-zulip-a-dropbox-hack-week-project" target="_blank">announcement</a> or go to <a href="https://www.zulip.org" target="_blank">the Zulip open source project website</a>.{% endblocktrans %}
{% trans %}Read the <a href="https://blogs.dropbox.com/tech/2015/09/open-sourcing-zulip-a-dropbox-hack-week-project" target="_blank">announcement</a> or go to <a href="https://www.zulip.org" target="_blank">the Zulip open source project website</a>.{% endtrans %}
</span>
</div>
</div>
@ -24,14 +23,14 @@
<img src="/static/images/logo/textlogo@2x.png" class="main-headline-logo" alt="Zulip logo" />
<div class="main-headline-text">
<span class="tagline">
{% trans 'Finally, workplace chat that actually improves your productivity.*' %}
{{ _('Finally, workplace chat that actually improves your productivity.*') }}
</span>
<span class="footnote">{% trans "* It's also great for sharing cat pictures" %}.</span>
<span class="footnote">{{ _("* It's also great for sharing cat pictures") }}.</span>
{% if not_voyager %}
{% elif only_sso %}
<a href="{% url 'login-sso' %}" class="main-signup-button btn btn-large btn-primary">{% trans 'Log in now!' %}</a>
<a href="{{ url('login-sso') }}" class="main-signup-button btn btn-large btn-primary">{{ _('Log in now!') }}</a>
{% else %}
<a href="{% url 'register' %}" class="main-signup-button btn btn-large btn-primary">{% trans 'Register now!' %}</a>
<a href="{{ url('register') }}" class="main-signup-button btn btn-large btn-primary">{{ _('Register now!') }}</a>
{% endif %}
</div>
<img src="/static/images/landing-page/laptop-screenshot.png" class="main-image" alt="Screenshot of Zulip" />
@ -42,15 +41,15 @@
<div class="app-main feature-line-container">
<div class="feature-text">
<span class="tagline">
{% trans 'Conversations, not messages' %}.
{{ _('Conversations, not messages') }}.
</span>
<span class="description">
<p>{% blocktrans %}Every conversation in Zulip has a <em>topic</em>, so it&rsquo;s
<p>{% trans %}Every conversation in Zulip has a <em>topic</em>, so it&rsquo;s
easy to keep conversations straight. Are your coworkers discussing
a software bug and the content of your website at the same time?
No problem.{% endblocktrans %}
No problem.{% endtrans %}
</p>
<p>{% trans "You wouldnt tolerate email without subject lines or threading, so why do you for chat?" %}</p>
<p>{{ _("You wouldnt tolerate email without subject lines or threading, so why do you for chat?") }}</p>
</span>
</div>
<div class="feature-illustration">
@ -63,15 +62,15 @@
<div class="app-main feature-line-container">
<div class="feature-text">
<span class="tagline">
{% trans 'Easily read just the important things' %}.
{{ _('Easily read just the important things') }}.
</span>
<span class="description">
<p>{% blocktrans %}Sometimes, important things get discussed when you&rsquo;re not
around. Unfortunately, so do a lot of unimportant things.{% endblocktrans %}</p>
<p>{% trans %}Sometimes, important things get discussed when you&rsquo;re not
around. Unfortunately, so do a lot of unimportant things.{% endtrans %}</p>
<p>{% blocktrans %}<em>Narrowing</em> by stream or topic lets you focus on that important
<p>{% trans %}<em>Narrowing</em> by stream or topic lets you focus on that important
customer project without having to read about how Jim&rsquo;s guitar lessons
are going.{% endblocktrans %}</p>
are going.{% endtrans %}</p>
</span>
</div>
<div class="feature-illustration">
@ -84,12 +83,12 @@
<div class="app-main feature-line-container">
<div class="feature-text">
<span class="tagline">
{% trans "Search that's better than Gmail's" %}.
{{ _("Search that's better than Gmail's") }}.
</span>
<span class="description">
{% blocktrans %}An impressive amount of knowledge lives in your chat system. Zulip&rsquo;s
{% trans %}An impressive amount of knowledge lives in your chat system. Zulip&rsquo;s
powerful and fast search will delight you with how quickly you can find
exactly what you&rsquo;re looking for.{% endblocktrans %}
exactly what you&rsquo;re looking for.{% endtrans %}
</span>
</div>
<div class="feature-illustration">
@ -102,14 +101,14 @@
<div class="app-main feature-line-container">
<div class="feature-text">
<span class="tagline">
{% trans "Integrations that don't intrude" %}.
{{ _("Integrations that don't intrude") }}.
</span>
<span class="description">
<p>{% blocktrans %}Zulip has <a href="/integrations">many integrations</a> and
<p>{% trans %}Zulip has <a href="/integrations">many integrations</a> and
a powerful <a href="/api">API</a> to match. But here&rsquo;s
where it gets interesting: thanks to how Zulip categorizes messages,
automated messages never overwhelm you. As with any topic in Zulip,
they&rsquo;re easy to focus on, skim, defer to later, or ignore&mdash;as appropriate.{% endblocktrans %}</p>
they&rsquo;re easy to focus on, skim, defer to later, or ignore&mdash;as appropriate.{% endtrans %}</p>
</span>
</div>
<div class="feature-illustration">
@ -122,12 +121,12 @@
<div class="app-main feature-line-container">
<div class="feature-text">
<span class="tagline">
{% trans 'As technical as you want to be' %}.
{{ _('As technical as you want to be') }}.
</span>
<span class="description">
<p>{% trans 'Keyboard shortcuts? Check.' %}<br />
{% trans 'Syntax highlighting? Check.' %}<br />
{% trans 'Discuss code and technical topics with ease.' %}</p>
<p>{{ _('Keyboard shortcuts? Check.') }}<br />
{{ _('Syntax highlighting? Check.') }}<br />
{{ _('Discuss code and technical topics with ease.') }}</p>
</span>
</div>
<div class="feature-illustration">
@ -140,12 +139,12 @@
<div class="app-main feature-line-container">
<div class="feature-text">
<span class="tagline">
&hellip; {% trans 'and all the obvious stuff, too.' %}
&hellip; {{ _('and all the obvious stuff, too.') }}
</span>
<span class="description">
<p>{% blocktrans %}Drag-and-drop file uploads, image pasting, group private messages,
<p>{% trans %}Drag-and-drop file uploads, image pasting, group private messages,
audible notifications, missed-message emails, desktop apps, and
<a href="/features">everything else you might want</a>. Including emoji, naturally.{% endblocktrans %}</p>
<a href="/features">everything else you might want</a>. Including emoji, naturally.{% endtrans %}</p>
</span>
</div>
<div class="feature-illustration">
@ -158,7 +157,7 @@
<div class="app-main feature-line-container">
<div class="platform-text">
<span class="tagline">
{% trans 'On the platform of your choice.' %}
{{ _('On the platform of your choice.') }}
</span>
</div>
<div class="platform-icons">
@ -194,9 +193,9 @@
<div class="app-main feature-line-container centered-content">
{% if not_voyager %}
{% elif only_sso %}
<a href="{% url 'login-sso' %}" class="bottom-signup-button btn btn-large btn-primary">{% trans 'Log in now' %}</a>
<a href="{{ url('login-sso') }}" class="bottom-signup-button btn btn-large btn-primary">{{ _('Log in now') }}</a>
{% else %}
<a href="{% url 'register' %}" class="bottom-signup-button btn btn-large btn-primary">{% trans 'Register now' %}</a>
<a href="{{ url('register') }}" class="bottom-signup-button btn btn-large btn-primary">{{ _('Register now') }}</a>
{% endif %}
</div>
</div>

View File

@ -1,55 +1,54 @@
{% load i18n %}
{# Home tab of the app, containing messages. #}
<div class="message_area_padder message_list" id="main_div">
<div id="loading_more_messages_indicator"></div>
<div id="page_loading_indicator"></div>
<div id="first_run_message" class="empty_feed_notice">
<h4>{% trans 'Welcome to' %} {{product_name}}</h4>
<p>{% blocktrans %}See, the thing about it is... there aren't any messages
<h4>{{ _('Welcome to') }} {{product_name}}</h4>
<p>{% trans %}See, the thing about it is... there aren't any messages
here for you right now. I'm sure someone will eventually send
you one.{% endblocktrans %}</p>
you one.{% endtrans %}</p>
<p>{% trans 'Or' %}, <strong>{% trans 'take matters into your own hands' %}</strong>,
{% trans 'and' %} <a href="#" class="empty_feed_compose_stream">
{% trans 'compose a new stream message' %}</a>.</p>
<p>{{ _('Or') }}, <strong>{{ _('take matters into your own hands') }}</strong>,
{{ _('and') }} <a href="#" class="empty_feed_compose_stream">
{{ _('compose a new stream message') }}</a>.</p>
</div>
<div id="empty_narrow_message" class="empty_feed_notice">
<h4>{% trans "Nothing's been sent here yet!" %}</h4>
<h4>{{ _("Nothing's been sent here yet!") }}</h4>
<p>{% trans 'Why not' %} <a href="#" class="empty_feed_compose_stream">
{% trans 'start the conversation' %}</a>?</p>
<p>{{ _('Why not') }} <a href="#" class="empty_feed_compose_stream">
{{ _('start the conversation') }}</a>?</p>
</div>
<div id="empty_narrow_all_private_message" class="empty_feed_notice">
<h4>{% trans 'You have no private messages yet!' %}</h4>
<h4>{{ _('You have no private messages yet!') }}</h4>
<p>{% trans 'Why not' %} <a href="#" class="empty_feed_compose_private">
{% trans 'start the conversation' %}</a>?</p>
<p>{{ _('Why not') }} <a href="#" class="empty_feed_compose_private">
{{ _('start the conversation') }}</a>?</p>
</div>
<div id="empty_narrow_private_message" class="empty_feed_notice">
<h4>{% trans 'You have no private messages with this person yet!' %}</h4>
<h4>{{ _('You have no private messages with this person yet!') }}</h4>
<p>{% trans 'Why not' %} <a href="#" class="empty_feed_compose_private">
{% trans 'start the conversation' %}</a>?</p>
<p>{{ _('Why not') }} <a href="#" class="empty_feed_compose_private">
{{ _('start the conversation') }}</a>?</p>
</div>
<div id="empty_narrow_multi_private_message" class="empty_feed_notice">
<h4>{% trans 'You have no private messages with these people yet!' %}</h4>
<h4>{{ _('You have no private messages with these people yet!') }}</h4>
<p>{% trans 'Why not' %} <a href="#" class="empty_feed_compose_private">
{% trans 'start the conversation' %}</a>?</p>
<p>{{ _('Why not') }} <a href="#" class="empty_feed_compose_private">
{{ _('start the conversation') }}</a>?</p>
</div>
<div id="nonsubbed_stream_narrow_message" class="empty_feed_notice">
<h4>{% trans "You aren't subscribed to this stream!" %}</h4>
<h4>{{ _("You aren't subscribed to this stream!") }}</h4>
<p>{% trans 'Want to' %} <a href="#" class="empty_feed_join">{% trans 'join it' %}</a>?</p>
<p>{{ _('Want to') }} <a href="#" class="empty_feed_join">{{ _('join it') }}</a>?</p>
</div>
<div id="empty_star_narrow_message" class="empty_feed_notice">
<h4>{% trans "You haven't starred anything yet!" %}</h4>
<h4>{{ _("You haven't starred anything yet!") }}</h4>
</div>
<div id="empty_narrow_all_mentioned" class="empty_feed_notice">
<h4>{% trans "You haven't been mentioned yet" %}.</h4>
<h4>{{ _("You haven't been mentioned yet") }}.</h4>
</div>
<div id="empty_search_narrow_message" class="empty_feed_notice">
<h4>{% trans 'Nobody has talked about that yet!' %}</h4>
<h4>{{ _('Nobody has talked about that yet!') }}</h4>
</div>
<div class="message_table focused_table" id="zhome">
</div>

View File

@ -1,11 +1,7 @@
{% extends "zerver/base.html" %}
{% load i18n %}
{# The app itself. #}
{# Includes some other templates as tabs. #}
{% load compressed %}
{% load minified_js %}
{% block page_params %}
{# Insert parameters, which have been encoded with JSONEncoderForHTML. #}
<script type="text/javascript">
@ -35,25 +31,25 @@ var page_params = {{ page_params }};
{% if nofontface %}
{# We can't use @font-face on qtwebkit, so use differently minified CSS #}
{% compressed_css 'app-fontcompat' %}
{{ compressed_css('app-fontcompat')|safe }}
{% else %}
{% compressed_css 'app' %}
{{ compressed_css('app')|safe }}
{% endif %}
{% minified_js 'app' %}
{{ minified_js('app')|safe }}
{% if not pipeline %}
<script type="text/javascript" src="/webpack/bundle.js"></script>
{% endif %}
{% if debug %}
{% minified_js 'app_debug' %}
{{ minified_js('app_debug')|safe }}
{% endif %}
{% endblock %}
{% block content %}
<div id="css-loading">
<h3>{% trans 'Loading' %}...</h3>
<p>{% trans 'If this message does not go away, please wait a couple seconds and' %} <a href="javascript:location.reload(true)">{% trans 'reload' %}</a> {% trans 'the page' %}.</p>
<h3>{{ _('Loading') }}...</h3>
<p>{{ _('If this message does not go away, please wait a couple seconds and') }} <a href="javascript:location.reload(true)">{{ _('reload') }}</a> {{ _('the page') }}.</p>
</div>
<div id="top-screen" class="screen"></div>

View File

@ -1,14 +1,12 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% load minified_js %}
{# A landing page for the first user in a realm, prompting her to invite her colleages. #}
{% block for_you %}for {{company_name}} {% endblock %}
{% block customhead %}
{{ block.super }}
{% minified_js 'initial_invite' %}
{{ super() }}
{{ minified_js('initial_invite')|safe }}
<script type="text/javascript">
var invite_suffix = "{{invite_suffix}}";
@ -18,18 +16,18 @@
{% block portico_content %}
<h1 style="margin-top:30px;">{% trans "You're the first one here!" %}</h1>
<h1 style="margin-top:30px;">{{ _("You're the first one here!")|safe }}</h1>
<p>
{% trans "Let's invite some folks for you to chat with" %}:
{{ _("Let's invite some folks for you to chat with") }}:
</p>
<div id="invite_rows">
<form id="invite_form">
{% csrf_token %}
{{ csrf_input }}
<div class="invite_row"><input name="email_1" class="invite_email" type={% if not invite_suffix %}"email"{% else %}"text"{% endif %} /> {% if invite_suffix %}@{{invite_suffix}}{% endif %}</div>
<p id="invite_blurb">({% trans "We'll email invitations to them" %})</p>
<p id="invite_blurb">({{ _("We'll email invitations to them") }})</p>
<div class="alert" id="invite_error" style="display: none;">
</div>
<button id="submit_invitation" class="btn btn-primary" data-loading-text="Next">{% trans 'Next' %} »</button>
<button id="submit_invitation" class="btn btn-primary" data-loading-text="Next">{{ _('Next') }} »</button>
</form>
</div>
{% endblock %}

View File

@ -635,14 +635,14 @@
<p>Let's say you want a notification each time a case is updated. Put
in a descriptive name like "Announce case update", and copy-paste
this to the "Appended URL path":</p>
{% verbatim %}
{% raw %}
<p><code>?stream=desk&amp;topic={{case.id}}:+{{case.subject}}</code></p>
{% endverbatim %}
{% endraw %}
<p>The "appended URL path" will be the same for every notification —
it makes sure the notification goes to the appropriate stream and topic
within Zulip. Next, copy this template Zulip message into "Message to
POST":</p>
{% verbatim %}
{% raw %}
<pre><code
>Case [{{case.id}}, {{case.subject}}]({{case.direct_url}}), was updated.
@ -655,7 +655,7 @@
<code>{{</code> and <code>}}</code>
will be filled in by Desk.com for each event. The dialog should look
like this:</p>
{% endverbatim %}
{% endraw %}
<img src="/static/images/integrations/desk/004.png" />
<p>Save it, and then click "On" next to the action to enable it. This
@ -1370,7 +1370,7 @@ key = NAGIOS_BOT_API_KEY
there, click "Add a webhook". Fill in the form like this:</p>
<ul>
<li><b>Name</b>: Zulip</li>
<li><b>Endpoint URL</b>: <code>{{ external_api_uri }}{% verbatim %}/v1/external/pagerduty?api_key=abcdefgh&amp;stream=pagerduty{% endverbatim %}</code></li>
<li><b>Endpoint URL</b>: <code>{{ external_api_uri }}/v1/external/pagerduty?api_key=abcdefgh&amp;stream=pagerduty</code></li>
</ul>
<img class="screenshot" src="/static/images/integrations/pagerduty/002.png" />
@ -2077,7 +2077,7 @@ access_token_secret =</pre>
<p>From there, click "URL target". Fill in the form like this:</p>
<ul>
<li><b>Title</b>: Zulip</li>
<li><b>URL</b>: <code>{{ external_api_uri }}{% verbatim %}/v1/external/zendesk?ticket_title={{ticket.title}}&amp;ticket_id={{ticket.id}}&amp;stream=zendesk{% endverbatim %}</code></li>
<li><b>URL</b>: <code>{{ external_api_uri }}{% raw %}/v1/external/zendesk?ticket_title={{ticket.title}}&amp;ticket_id={{ticket.id}}&amp;stream=zendesk{% endraw %}</code></li>
<li><b>Method</b>: POST</li>
<li><b>Attribute Name</b>: message</li>
<li><b>Username</b>: <em>your bot's user name, e.g.</em> <code>zendesk-bot@yourdomain.com</code></li>
@ -2105,7 +2105,7 @@ access_token_secret =</pre>
<p>Next we need need to enter the message body into Message. You can use
Zulip markdown and the Zendesk placeholders when creating your message.
You can copy this example template:</p>
{% verbatim %}
{% raw %}
<pre><code>Ticket [#{{ticket.id}}: {{ticket.title}}]({{ticket.link}}), was updated by {{current_user.name}}
* Status: {{ticket.status}}
@ -2117,7 +2117,7 @@ access_token_secret =</pre>
``` quote
{{ticket.description}}
``` </code></pre>
{% endverbatim %}
{% endraw %}
<img src="/static/images/integrations/zendesk/006.png" />
@ -2136,7 +2136,7 @@ access_token_secret =</pre>
{% endblock %}
{% block customhead %}
{{ block.super }}
{{ super() }}
<script type="text/javascript">
$(function() {
$("a.title").addClass("show-integral");

View File

@ -1,16 +1,15 @@
{% load i18n %}
<div class="modal hide" id="invite-user" tabindex="-1" role="dialog"
aria-labelledby="invite-user-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="invite-user-label">{% trans 'Invite coworkers to' %} {{product_name}}</h3>
<h3 id="invite-user-label">{{ _('Invite coworkers to') }} {{product_name}}</h3>
</div>
<form id="invite_user_form" class="form-horizontal"
action="/json/invite_users" method="POST">{% csrf_token %}
action="/json/invite_users" method="POST">{{ csrf_input }}
<div class="modal-body">
<div class="control-group">
<div id="invite-result"></div>
<label class="control-label" for="invitee_emails">{% trans 'Emails (one on each line or comma-separated)' %}</label>
<label class="control-label" for="invitee_emails">{{ _('Emails (one on each line or comma-separated)') }}</label>
<div class="controls">
<textarea rows="2" id="invitee_emails"
name="invitee_emails"
@ -19,13 +18,13 @@
</div>
<div class="alert" id="invite_status"></div>
<div class="control-group">
<label class="control-label" for="streams_to_add">{% trans 'Streams they should join' %}</label>
<label class="control-label" for="streams_to_add">{{ _('Streams they should join') }}</label>
<div class="controls" id="streams_to_add"></div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">{% trans 'Cancel' %}</button>
<button id="submit-invitation" class="btn btn-primary" data-loading-text="Inviting..." type="submit">{% trans 'Invite' %}</button>
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">{{ _('Cancel') }}</button>
<button id="submit-invitation" class="btn btn-primary" data-loading-text="Inviting..." type="submit">{{ _('Invite') }}</button>
</div>
</form>
</div>

View File

@ -1,77 +1,76 @@
{% load i18n %}
<div class="modal hide" id="keyboard-shortcuts" tabindex="-1" role="dialog"
aria-labelledby="keyboard-shortcuts-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="keyboard-shortcuts-label">{% blocktrans %}Keyboard shortcuts{% endblocktrans %}</h3>
<h3 id="keyboard-shortcuts-label">{% trans %}Keyboard shortcuts{% endtrans %}</h3>
</div>
<div class="modal-body">
<div>
<table class="hotkeys_table table table-striped table-bordered table-condensed">
<thead>
<tr>
<th colspan="2">{% trans "Navigation" %}</th>
<th colspan="2">{{ _("Navigation") }}</th>
</tr>
</thead>
<tr>
<td class="hotkey">/</td>
<td class="definition">{% blocktrans %}Initiate a search{% endblocktrans %}</td>
<td class="definition">{% trans %}Initiate a search{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">q</td>
<td class="definition">{% blocktrans %}Search people{% endblocktrans %}</td>
<td class="definition">{% trans %}Search people{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">Up or k</td>
<td class="definition">{% blocktrans %}Previous message{% endblocktrans %}</td>
<td class="definition">{% trans %}Previous message{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">Down or j</td>
<td class="definition">{% blocktrans %}Next message{% endblocktrans %}</td>
<td class="definition">{% trans %}Next message{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">PgUp, K</td>
<td class="definition">{% blocktrans %}Scroll up{% endblocktrans %}</td>
<td class="definition">{% trans %}Scroll up{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">PgDn, J, Spacebar</td>
<td class="definition">{% blocktrans %}Scroll down{% endblocktrans %}</td>
<td class="definition">{% trans %}Scroll down{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">End</td>
<td class="definition">{% blocktrans %}Last message{% endblocktrans %}</td>
<td class="definition">{% trans %}Last message{% endtrans %}</td>
</tr>
</table>
<table class="hotkeys_table table table-striped table-bordered table-condensed">
<thead>
<tr>
<th colspan="2">{% blocktrans %}Composing messages{% endblocktrans %}</th>
<th colspan="2">{% trans %}Composing messages{% endtrans %}</th>
</tr>
</thead>
<tr>
<td class="hotkey">Enter or r</td>
<td class="definition">{% blocktrans %}Reply to message{% endblocktrans %}</td>
<td class="definition">{% trans %}Reply to message{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">R</td>
<td class="definition">{% blocktrans %}Reply to author{% endblocktrans %}</td>
<td class="definition">{% trans %}Reply to author{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">c</td>
<td class="definition">{% blocktrans %}New stream message{% endblocktrans %}</td>
<td class="definition">{% trans %}New stream message{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">C</td>
<td class="definition">{% blocktrans %}New private message{% endblocktrans %}</td>
<td class="definition">{% trans %}New private message{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">Tab then Enter</td>
<td class="definition">{% blocktrans %}Send message{% endblocktrans %}</td>
<td class="definition">{% trans %}Send message{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">Esc</td>
<td class="definition">{% blocktrans %}Cancel compose{% endblocktrans %}</td>
<td class="definition">{% trans %}Cancel compose{% endtrans %}</td>
</tr>
</table>
</div>
@ -80,53 +79,53 @@
<table class="hotkeys_table table table-striped table-bordered table-condensed">
<thead>
<tr>
<th colspan="2">{% trans "Narrowing" %}</th>
<th colspan="2">{{ _("Narrowing") }}</th>
</tr>
</thead>
<tr>
<td class="hotkey">s</td>
<td class="definition">{% blocktrans %}Narrow by stream{% endblocktrans %}</td>
<td class="definition">{% trans %}Narrow by stream{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">S</td>
<td class="definition">{% blocktrans %}Narrow by topic{% endblocktrans %}</td>
<td class="definition">{% trans %}Narrow by topic{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">v</td>
<td class="definition">{% blocktrans %}Narrow to all private messages{% endblocktrans %}</td>
<td class="definition">{% trans %}Narrow to all private messages{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">A or D</td>
<td class="definition">{% blocktrans %}Cycle between stream narrows{% endblocktrans %}</td>
<td class="definition">{% trans %}Cycle between stream narrows{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">Esc</td>
<td class="definition">{% blocktrans %}Return to home view{% endblocktrans %}</td>
<td class="definition">{% trans %}Return to home view{% endtrans %}</td>
</tr>
</table>
<table class="hotkeys_table table table-striped table-bordered table-condensed">
<thead>
<tr>
<th colspan="2">{% trans "Menus" %}</th>
<th colspan="2">{{ _("Menus") }}</th>
</tr>
</thead>
<tr>
<td class="hotkey">i</td>
<td class="definition">{% blocktrans %}Open message actions menu{% endblocktrans %}</td>
<td class="definition">{% trans %}Open message actions menu{% endtrans %}</td>
</tr>
<tr id="edit-message-hotkey-help">
<td class="hotkey">i then Enter</td>
<td class="definition">{% blocktrans %}Edit a message you sent{% endblocktrans %}</td>
<td class="definition">{% trans %}Edit a message you sent{% endtrans %}</td>
</tr>
<tr>
<td class="hotkey">?</td>
<td class="definition">{% blocktrans %}Show these keyboard shortcuts{% endblocktrans %}</td>
<td class="definition">{% trans %}Show these keyboard shortcuts{% endtrans %}</td>
</tr>
</table>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">{% trans "Close" %}</button>
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">{{ _("Close") }}</button>
</div>
</div>

View File

@ -1,23 +1,22 @@
{% load i18n %}
<div class="left-sidebar" id="left-sidebar">
<div class="bottom_sidebar">
<ul id="global_filters" class="filters">
{# Special-case this link so we don't actually go to page top. #}
<li data-name="home"
class="global-filter active-filter"><span class="filter-icon"><i class="icon-vector-home"></i></span><a href="#">{% trans 'Home' %} <span class="count"><span class="value"></span></span></a></li>
<li data-name="private" class="global-filter"><span class="filter-icon"><i class="icon-vector-user"></i></span><a href="#narrow/is/private">{% trans 'Private messages' %} <span class="count"><span class="value"></span></span></a></li>
<li data-name="starred" class="global-filter"><span class="filter-icon"><i class="icon-vector-star"></i></span><a href="#narrow/is/starred">{% trans 'Starred messages' %}</a></li>
<li data-name="mentioned" class="global-filter"><span class="filter-icon"><i class="icon-vector-tag"></i></span><a href="#narrow/is/mentioned">{% trans '@-mentions' %}<span class="count"><span class="value"></span></span></a></li>
class="global-filter active-filter"><span class="filter-icon"><i class="icon-vector-home"></i></span><a href="#">{{ _('Home') }} <span class="count"><span class="value"></span></span></a></li>
<li data-name="private" class="global-filter"><span class="filter-icon"><i class="icon-vector-user"></i></span><a href="#narrow/is/private">{{ _('Private messages') }} <span class="count"><span class="value"></span></span></a></li>
<li data-name="starred" class="global-filter"><span class="filter-icon"><i class="icon-vector-star"></i></span><a href="#narrow/is/starred">{{ _('Starred messages') }}</a></li>
<li data-name="mentioned" class="global-filter"><span class="filter-icon"><i class="icon-vector-tag"></i></span><a href="#narrow/is/mentioned">{{ _('@-mentions') }}<span class="count"><span class="value"></span></span></a></li>
</ul>
<div id="streams_list" class="zoom-out">
<div id="streams_header" class="zoom-in-hide"><h4 class="sidebar-title">{% trans 'STREAMS' %}</h4>
<div id="streams_header" class="zoom-in-hide"><h4 class="sidebar-title">{{ _('STREAMS') }}</h4>
<a href=""><i id="streams_inline_cog" class='icon-vector-cog' data-toggle="tooltip" title="Subscribe, add, or configure streams"></i></a>
</div>
<div id="topics_header">
<div class="all-streams-padding">
<ul class="filters">
<li data-name="all-streams">
<i class="icon-vector-chevron-left"></i> <a href="" class="show-all-streams">{% trans 'All streams' %}</a>
<i class="icon-vector-chevron-left"></i> <a href="" class="show-all-streams">{{ _('All streams') }}</a>
</li>
</ul>
</div>
@ -28,24 +27,24 @@
</div>
<div id="share-the-love">
<div id="share-the-love-expand-collapse">
<i class="toggle icon-vector-caret-right"></i><div id="sharethelove-header"><h4 class="share-the-love-title">{% trans 'SHARE THE LOVE' %}<span class="still-have-invites"> (<span class="invite-count">0</span>)</span></h4></div>
<i class="toggle icon-vector-caret-right"></i><div id="sharethelove-header"><h4 class="share-the-love-title">{{ _('SHARE THE LOVE') }}<span class="still-have-invites"> (<span class="invite-count">0</span>)</span></h4></div>
</div>
<div id="share-the-love-contents">
<div id="tell-a-friend-success" class="alert alert-success">
<strong>{% trans 'Thanks!' %}</strong> {% trans 'A hand-crafted, artisanal invite is on the way' %}.
<strong>{{ _('Thanks!') }}</strong> {{ _('A hand-crafted, artisanal invite is on the way') }}.
</div>
<div class="still-have-invites" id="encouraging-invite-message">
<p>
{% trans "Know someone who would love Zulip for their company or group? Invite 'em!" %}
{{ _("Know someone who would love Zulip for their company or group? Invite 'em!") }}
</p>
</div>
<div class="no-more-invites">
<p>
{% blocktrans %}We'll have more invites for you soon, but
{% trans %}We'll have more invites for you soon, but
for now, enjoy this <a target="_blank"
href="http://www.youtube.com/watch?v=PW71En5Pa5s#t=2m01s">song
that expresses how we feel when you're
logged out</a>.{% endblocktrans %}
logged out</a>.{% endtrans %}
</p>
</div>
<div class="still-have-invites">
@ -57,7 +56,7 @@
</div>
<div class="invite-count-area">
<span id="invite-hearts"></span>
<small class="pull-right"><span class="invite-count">0</span> {% trans 'invite' %}<span class="invite-count-is-plural">s</span> {% trans 'remaining' %}</small>
<small class="pull-right"><span class="invite-count">0</span> {{ _('invite') }}<span class="invite-count-is-plural">s</span> {{ _('remaining') }}</small>
</div>
</div>
</div>

View File

@ -2,12 +2,9 @@
{# Login page. #}
{% load i18n %}
{% load minified_js %}
{% block customhead %}
{{ block.super }}
{% minified_js 'signup' %}
{{ super() }}
{{ minified_js('signup')|safe }}
{% endblock %}
{% block os_announcement %}
@ -16,10 +13,10 @@
<img src="/static/images/logo/zballoon.png" class="os-illustration" alt="Zulip balloon" />
<div class="main-headline-text">
<span class="tagline os-tagline">
{% trans 'Zulip has been released as open source software!' %}
{{ _('Zulip has been released as open source software!') }}
</span>
<span class="footnote os-footnote">
{% trans 'Read the' %} <a href="https://blogs.dropbox.com/tech/2015/09/open-sourcing-zulip-a-dropbox-hack-week-project" target="_blank">{% trans 'announcement' %}</a> {% trans 'or go to' %} <a href="https://www.zulip.org" target="_blank">{% trans 'the Zulip open source project website' %}</a>.
{{ _('Read the') }} <a href="https://blogs.dropbox.com/tech/2015/09/open-sourcing-zulip-a-dropbox-hack-week-project" target="_blank">{{ _('announcement') }}</a> {{ _('or go to') }} <a href="https://www.zulip.org" target="_blank">{{ _('the Zulip open source project website') }}</a>.
</span>
</div>
</div>
@ -45,30 +42,30 @@ autofocus('#id_username');
<div class="app-main login-page-container">
{% if dev_auth_enabled %}
<h3 class="login-page-header">{% trans 'Zulip Dev Login' %}</h3>
<h3 class="login-page-header">{{ _('Zulip Dev Login') }}</h3>
{% if not password_auth_enabled %}
<h4 class="login-page-subheader">{% trans 'Choose a user' %}:</h4>
<h4 class="login-page-subheader">{{ _('Choose a user') }}:</h4>
{% endif %}
{% else %}
<h3 class="login-page-header">{% trans 'You look familiar' %}.</h3>
<h3 class="login-page-header">{{ _('You look familiar') }}.</h3>
{% endif %}
{% if only_sso %}
{% comment %}SSO users don't have a password.{% endcomment %}
{# SSO users don't have a password. #}
<div class="login-sso">
<a href="/accounts/login/sso" class="btn btn-large btn-primary">{% trans 'Sign in with SSO' %}</a>
<a href="/accounts/login/sso" class="btn btn-large btn-primary">{{ _('Sign in with SSO') }}</a>
</div>
{% else %}
{% comment %}Non-SSO users.{% endcomment %}
{# Non-SSO users. #}
{% if form.errors or desktop_sso_unknown_email %}
<div class="alert alert-error">
{% if desktop_sso_unknown_email %}
{% trans 'Zulip is not currently available for your domain' %}. <br />
{{ _('Zulip is not currently available for your domain') }}. <br />
{% else %}
{% for error in form.errors.values %}
{% for error in form.errors.values() %}
<div>{{ error | striptags }}</div>
{% endfor %}
{% endif %}
@ -77,7 +74,7 @@ autofocus('#id_username');
{% if email %}
<div class="alert">
{% trans "You've already registered with this email address. Please log in below" %}.
{{ _("You've already registered with this email address. Please log in below") }}.
</div>
{% endif %}
@ -85,14 +82,14 @@ autofocus('#id_username');
<form name="login_form" id="login_form" method="post" class="login-form"
{% if desktop_sso_dispatch %}
{# desktop_sso_dispatch is only set when this template is invoked by zilencer.views #}
action="{% url 'zilencer.views.account_deployment_dispatch' %}"
action="{{ url('zilencer.views.account_deployment_dispatch') }}"
{% else %}
action="{% url 'django.contrib.auth.views.login' %}?next={{ next }}"
action="{{ url('django.contrib.auth.views.login') }}?next={{ next }}"
{% endif %}
>
{% csrf_token %}
{{ csrf_input }}
<div class="control-group">
<label for="id_username" class="control-label">{% trans 'Email' %}</label>
<label for="id_username" class="control-label">{{ _('Email') }}</label>
<div class="controls">
<input id="id_username" type="email" name="username" class="email required" value="{{ email }}" maxlength="72" />
</div>
@ -100,7 +97,7 @@ autofocus('#id_username');
{% if not desktop_sso_dispatch %}
<div class="control-group">
<label for="id_password" class="control-label">{% trans 'Password' %}</label>
<label for="id_password" class="control-label">{{ _('Password') }}</label>
<div class="controls">
<input id="id_password" name="password" class="required" type="password" />
</div>
@ -111,7 +108,7 @@ autofocus('#id_username');
<input type="submit" class="btn btn-large btn-primary" value="Log in" />
{% if not desktop_sso_dispatch %}
<span class="login-forgot-password">
<a href="{% url 'django.contrib.auth.views.password_reset' %}">{% trans 'Forgot password?' %}</a>
<a href="{{ url('django.contrib.auth.views.password_reset') }}">{{ _('Forgot password?') }}</a>
</span>
{% endif %}
</div>
@ -120,18 +117,18 @@ autofocus('#id_username');
{% endif %}
{% if dev_auth_enabled %}
<form name="direct_login_form" id="direct_login_form" method="post" class="login-form"
action="{% url 'zerver.views.dev_direct_login' %}">
{% csrf_token %}
action="{{ url('zerver.views.dev_direct_login') }}">
{{ csrf_input }}
<div class="control-group">
{% if password_auth_enabled %}
<label for="direct_email" class="direct-label">{% trans 'or Choose a user' %}:</label>
<label for="direct_email" class="direct-label">{{ _('or Choose a user') }}:</label>
{% endif %}
<div class="controls">
<p>({% trans 'Administrators' %})</p>
<p>({{ _('Administrators') }})</p>
{% for user_email in direct_admins %}
<p><input type="submit" name="direct_email" class="btn-direct btn-admin" value="{{ user_email }}" /></p>
{% endfor %}
<p>({% trans 'Normal users' %})</p>
<p>({{ _('Normal users') }})</p>
{% for user_email in direct_users %}
<p><input type="submit" name="direct_email" class="btn-direct btn-user" value="{{ user_email }}" /></p>
{% endfor %}
@ -142,7 +139,7 @@ autofocus('#id_username');
{% if google_auth_enabled %}
<div class="login-google">
or <a href="{% url 'zerver.views.start_google_oauth2' %}" class="login-google-button zocial google">{% trans 'Sign in with Google' %}</a>
or <a href="{{ url('zerver.views.start_google_oauth2') }}" class="login-google-button zocial google">{{ _('Sign in with Google') }}</a>
</div>
{% endif %}

View File

@ -1,4 +1,4 @@
<div class="hidden">
<form id="logout_form" action="/accounts/logout/" method="POST">{% csrf_token %}
<form id="logout_form" action="/accounts/logout/" method="POST">{{ csrf_input }}
</form>
</div>

View File

@ -1,16 +1,15 @@
{% load i18n %}
<div class="modal hide" id="markdown-help" tabindex="-1" role="dialog"
aria-labelledby="markdown-help-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="markdown-help-label">{% blocktrans %}Message formatting{% endblocktrans %}</h3>
<h3 id="markdown-help-label">{% trans %}Message formatting{% endtrans %}</h3>
</div>
<div class="modal-body">
<div id="markdown-instructions">
<table class="table table-striped table-condensed table-rounded table-bordered" id="fmt_help_table">
<thead><tr>
<th>{% blocktrans %}You type{% endblocktrans %}</th>
<th>{% blocktrans %}You get{% endblocktrans %}</th>
<th>{% trans %}You type{% endtrans %}</th>
<th>{% trans %}You get{% endtrans %}</th>
</tr></thead>
<tbody>
@ -71,7 +70,7 @@ def zulip():
</td>
</tr>
<tr>
<td colspan="2">{% blocktrans %}You can also make a code block by indenting each line with 4 spaces.{% endblocktrans %}</td>
<td colspan="2">{% trans %}You can also make a code block by indenting each line with 4 spaces.{% endtrans %}</td>
</tr>
<tr>
<td>&gt; Quoted</td>
@ -85,17 +84,17 @@ Quoted block
<td><blockquote><p>Quoted block</p></blockquote></td>
</tr>
<tr>
<td colspan="2">{% blocktrans %}You can also make <a target="_blank"
<td colspan="2">{% trans %}You can also make <a target="_blank"
href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables">tables</a>
with this <a target="_blank"
href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables">Markdown-ish
table syntax</a>{% endblocktrans %}.</td>
table syntax</a>{% endtrans %}.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">{% trans "Close" %}</button>
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">{{ _("Close") }}</button>
</div>
</div>

View File

@ -1,6 +1,6 @@
{% comment %}
{#
Mail sent to user when she was not logged in and received a PM or @-mention
{% endcomment %}
#}
Hello {{ name }},

View File

@ -1,6 +1,6 @@
{% comment %}
{#
Mail sent to user when she was not logged in and received a PM or @-mention
{% endcomment %}
#}
Hello {{ name }},

View File

@ -1,4 +1,3 @@
{% load i18n %}
<div class="header">
<div class="header-main rightside-userlist" id="top_navbar">
<div class="column-left">
@ -17,7 +16,7 @@
<form id="searchbox_form" class="form-search navbar-search">
<div id="search_arrows" class="input-append">
<i class="icon-vector-search"></i>
<input class="search-query input-block-level" id="search_query" type="text" placeholder="{% trans 'Search' %}"
<input class="search-query input-block-level" id="search_query" type="text" placeholder="{{ _('Search') }}"
autocomplete="off" />
{# Start the button off disabled since there is no active search #}
<button class="btn search_button" type="button" id="search_exit" disabled="disabled"><i class="icon-vector-remove"></i></button>
@ -39,70 +38,70 @@
<i class="icon-vector-cog"></i><i class="icon-vector-caret-down settings-dropdown-caret"></i>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="settings-dropdown">
{% comment %}
{#
It is quite ingrained in our frontend code that your Home
view is a Bootstrap Nav tab, even though we don't show the tab
anymore
{% endcomment %}
#}
<li style="display:none;"><a href="#home" data-toggle="tab"></a></li>
<li title="Manage Streams">
<a href="#subscriptions" data-toggle="tab">
<i class="icon-vector-exchange"></i> {% trans 'Manage Streams' %}
<i class="icon-vector-exchange"></i> {{ _('Manage Streams') }}
</a>
</li>
<li title="Settings">
<a href="#settings" data-toggle="tab">
<i class="icon-vector-wrench"></i> {% trans 'Settings' %}
<i class="icon-vector-wrench"></i> {{ _('Settings') }}
</a>
</li>
<li title="Keyboard shortcuts">
<a href="#keyboard-shortcuts" role="button" data-toggle="modal">
<i class="icon-vector-question-sign"></i> {% trans 'Keyboard shortcuts' %}
<i class="icon-vector-question-sign"></i> {{ _('Keyboard shortcuts') }}
</a>
</li>
<li title="Message formatting">
<a href="#markdown-help" role="button" data-toggle="modal">
<i class="icon-vector-pencil"></i> {% trans 'Message formatting' %}
<i class="icon-vector-pencil"></i> {{ _('Message formatting') }}
</a>
</li>
<li title="Search help">
<a href="#search-operators" role="button" data-toggle="modal">
<i class="icon-vector-search"></i> {% trans 'Search help' %}
<i class="icon-vector-search"></i> {{ _('Search help') }}
</a>
</li>
<li class="divider"></li>
<li title="Desktop & mobile apps">
<a href="/apps" target="_blank" role="button">
<i class="icon-vector-desktop"></i> {% trans 'Desktop & mobile apps' %}
<i class="icon-vector-desktop"></i> {{ _('Desktop & mobile apps') }}
</a>
</li>
<li title="Integrations">
<a href="/integrations" target="_blank" role="button">
<i class="icon-vector-github"></i> {% trans 'Integrations' %}
<i class="icon-vector-github"></i> {{ _('Integrations') }}
</a>
</li>
<li title="API documentation">
<a href="/api" target="_blank" role="button">
<i class="icon-vector-sitemap"></i> {% trans 'API documentation' %}
<i class="icon-vector-sitemap"></i> {{ _('API documentation') }}
</a>
</li>
<li class="divider"></li>
<li title="Administration" class="admin-menu-item">
<a href="#administration" role="button" data-toggle="tab">
<i class="icon-vector-bolt"></i> {% trans 'Administration' %}
<i class="icon-vector-bolt"></i> {{ _('Administration') }}
</a>
</li>
{% if show_invites %}
<li title="Invite coworkers to {{product_name}}">
<a href="#invite-user" role="button" data-toggle="modal">
<i class="icon-vector-plus-sign"></i> {% trans 'Invite coworkers' %}
<i class="icon-vector-plus-sign"></i> {{ _('Invite coworkers') }}
</a>
</li>
{% endif %}
{% if enable_feedback %}
<li title="Feedback">
<a href="#feedback" class="feedback">
<i class="icon-vector-comment"></i> {% trans 'Feedback' %}
<i class="icon-vector-comment"></i> {{ _('Feedback') }}
</a>
</li>
{% endif %}
@ -110,19 +109,19 @@
{% if show_webathena %}
<li title="Grant {{product_name}} the Kerberos tickets needed to run your Zephyr mirror via Webathena" id="webathena_login_menu">
<a href="#webathena" class="webathena_login">
<i class="icon-vector-bolt"></i>{% trans 'Link with Webathena' %}
<i class="icon-vector-bolt"></i>{{ _('Link with Webathena') }}
</a>
</li>
{% endif %}
<li title="Log out">
<a href="#logout" class="logout_button">
<i class="icon-vector-off"></i> {% trans 'Log out' %}
<i class="icon-vector-off"></i> {{ _('Log out') }}
</a>
</li>
{% if show_debug %}
<li title="Debug">
<a href="#debug" data-toggle="tab">
<i class="icon-vector-barcode"></i> {% trans 'Debug' %}
<i class="icon-vector-barcode"></i> {{ _('Debug') }}
</a>
</li>
{% endif %}

View File

@ -1,16 +1,13 @@
{% extends "zerver/base.html" %}
{% load i18n %}
{% load compressed %}
{% comment %}
A base template for stuff like login, register, etc.
{# A base template for stuff like login, register, etc.
Not inside the app itself, but covered by the same structure,
hence the name.
{% endcomment %}
#}
{% block customhead %}
{% compressed_css 'portico' %}
{{ compressed_css('portico')|safe }}
{% endblock %}
{% block content %}
@ -28,13 +25,13 @@ hence the name.
<div class="column-right top-links">
{% if not only_sso %}
<a href="{{login_url}}">{% trans 'Log in' %}</a>
<a href="{{login_url}}">{{ _('Log in') }}</a>
{% endif %}
{% if only_sso %}
<a href="{% url 'login-sso' %}">{% trans 'Log In' %}</a>
<a href="{{ url('login-sso') }}">{{ _('Log In') }}</a>
{% else %}
<a href="{% url 'register' %}">{% trans 'Register' %}</a>
<a href="{{ url('register') }}">{{ _('Register') }}</a>
{% endif %}
</div>
</div>
@ -55,19 +52,19 @@ hence the name.
<div class="footer">
<div class="footer-main">
<ul class="footer-navigation">
<li><a href="/hello">{% trans 'About' %}</a></li>
<li><a href="/hello">{{ _('About') }}</a></li>
{% if zulip_com %}
<li><span class="little-bullet">·</span></li>
<li><a href="/terms">{% trans 'Legal' %}</a></li>
<li><a href="/terms">{{ _('Legal') }}</a></li>
{% endif %}
<li><span class="little-bullet">·</span></li>
<li><a href="{{login_url}}">{% trans 'Log in' %}</a></li>
<li><a href="{{login_url}}">{{ _('Log in') }}</a></li>
{% if not only_sso %}
<li><span class="little-bullet">·</span></li>
<li>
{% if zulip_com %}
{% else %}
<a href="{% url 'register' %}">{% trans 'Register' %}</a>
<a href="{{ url('register') }}">{{ _('Register') }}</a>
{% endif %}
</li>
{% endif %}

View File

@ -1,10 +1,8 @@
{% extends "zerver/portico.html" %}
{% load minified_js %}
{# Portico page with signup code #}
{% block customhead %}
{{ block.super }}
{% minified_js 'signup' %}
{{ super() }}
{{ minified_js('signup')|safe }}
{% endblock %}

View File

@ -1,14 +1,13 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{% comment %}
{#
Gather other user information, after having confirmed
their email address.
Form is validated both client-side using jquery-validate (see signup.js) and server-side.
{% endcomment %}
#}
{% block customhead %}
{{ block.super }}
{{ super() }}
<script type="text/javascript" src="/static/third/zxcvbn/zxcvbn.js"></script>
{% endblock %}
@ -17,27 +16,27 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
<div class="pitch">
<p style="margin-top:30px;">{% trans "You're almost there. We just need you to do one last thing" %}.</p>
<h3>{% trans 'Tell us a bit about yourself' %}.</h3>
<p style="margin-top:30px;">{{ _("You're almost there. We just need you to do one last thing") }}.</p>
<h3>{{ _('Tell us a bit about yourself') }}.</h3>
</div>
<form method="post" class="form-horizontal" id="registration" action="{% url 'zerver.views.accounts_register' %}">
{% csrf_token %}
<form method="post" class="form-horizontal" id="registration" action="{{ url('zerver.views.accounts_register') }}">
{{ csrf_input }}
<div class="control-group">
<label for="id_email" class="control-label">{% trans 'Email' %}</label>
<label for="id_email" class="control-label">{{ _('Email') }}</label>
<div class="controls fakecontrol">
<input type='hidden' name='key' value='{{ key }}' />
<p>{{ email }}</p>
</div>
</div>
<div class="control-group">
<label for="id_full_name" class="control-label">{% trans 'Full name' %}</label>
<label for="id_full_name" class="control-label">{{ _('Full name') }}</label>
<div class="controls">
{% if lock_name %}
<p class="fakecontrol">{{ full_name }}</p>
{% else %}
<input id="id_full_name" class="required" type="text" name="full_name"
value="{% if full_name %}{{ full_name }}{% elif form.full_name.value %}{{ form.full_name.value }}{% endif %}"
value="{% if full_name %}{{ full_name }}{% elif form.full_name.value() %}{{ form.full_name.value() }}{% endif %}"
maxlength="100" />
{% if form.full_name.errors %}
{% for error in form.full_name.errors %}
@ -49,13 +48,13 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
</div>
{% if password_auth_enabled %}
<div class="control-group">
<label for="id_password" class="control-label">{% trans 'Password' %}</label>
<label for="id_password" class="control-label">{{ _('Password') }}</label>
<div class="controls">
<input id="id_password" class="required" type="password" name="password"
value="{% if form.password.value %}{{ form.password.value }}{% endif %}"
value="{% if form.password.value() %}{{ form.password.value() }}{% endif %}"
maxlength="100" />
{% if full_name %}
<span class="help-inline">{% trans 'This is used for mobile applications and other tools that require a password' %}.</span>
<span class="help-inline">{{ _('This is used for mobile applications and other tools that require a password') }}.</span>
{% endif %}
{% if form.password.errors %}
{% for error in form.password.errors %}
@ -65,7 +64,7 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'Password strength' %}</label>
<label class="control-label">{{ _('Password strength') }}</label>
<div class="controls">
<div class="progress" id="pw_strength">
<div class="bar bar-danger" style="width: 10%;"></div>
@ -79,17 +78,17 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
<div class="control-group">
<div class="controls">
<label class="checkbox">
{% comment %}
{#
This is somewhat subtle.
Checkboxes have a name and value, and when the checkbox is ticked, the form posts
with name=value. If the checkbox is unticked, the field just isn't present at all.
This is distinct from 'checked', which determines whether the checkbox appears
at all. (So, it's not symmetric to the code above.)
{% endcomment %}
#}
<input id="id_terms" class="required" type="checkbox" name="terms"
{% if form.terms.value %}checked="checked"{% endif %} />
{% trans 'I agree to the' %} <a href="/terms" target="_blank">{% trans 'Terms of Service' %}</a>.
{% if form.terms.value() %}checked="checked"{% endif %} />
{{ _('I agree to the') }} <a href="/terms" target="_blank">{{ _('Terms of Service') }}</a>.
</label>
{% if form.terms.errors %}
{% for error in form.terms.errors %}

View File

@ -1,18 +1,17 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{% block portico_content %}
<div class="pitch">
<h3>{% trans 'Reset your password' %}.</h3>
<h3>{{ _('Reset your password') }}.</h3>
</div>
<form method="post" class="form-horizontal" action="{% url 'django.contrib.auth.views.password_reset' %}">
{% csrf_token %}
<form method="post" class="form-horizontal" action="{{ url('django.contrib.auth.views.password_reset') }}">
{{ csrf_input }}
<div class="control-group">
<label for="id_email" class="control-label">{% trans 'Email' %}</label>
<label for="id_email" class="control-label">{{ _('Email') }}</label>
<div class="controls">
<input id="id_email" class="required" type="text" name="email"
value="{% if form.email.value %}{{ form.email.value }}{% endif %}"
value="{% if form.email.value() %}{{ form.email.value() }}{% endif %}"
maxlength="100" />
{% if form.email.errors %}
{% for error in form.email.errors %}

View File

@ -1,7 +1,6 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{% block customhead %}
{{ block.super }}
{{ super() }}
<script type="text/javascript" src="/static/third/zxcvbn/zxcvbn.js"></script>
{% endblock %}
@ -9,17 +8,17 @@
<div class="pitch">
<hr/>
<h3>{% trans 'Reset your password' %}.</h3>
<h3>{{ _('Reset your password') }}.</h3>
</div>
{% if validlink %}
<form method="post" id="password_reset" class="form-horizontal">
{% csrf_token %}
{{ csrf_input }}
<div class="control-group">
<label for="id_new_password1" class="control-label">{% trans 'Password' %}</label>
<label for="id_new_password1" class="control-label">{{ _('Password') }}</label>
<div class="controls">
<input id="id_new_password1" class="required" type="password" name="new_password1"
value="{% if form.new_password1.value %}{{ form.new_password1.value }}{% endif %}"
value="{% if form.new_password1.value() %}{{ form.new_password1.value() }}{% endif %}"
maxlength="100" />
{% if form.new_password1.errors %}
{% for error in form.new_password1.errors %}
@ -29,7 +28,7 @@
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'Password strength' %}</label>
<label class="control-label">{{ _('Password strength') }}</label>
<div class="controls">
<div class="progress" id="pw_strength">
<div class="bar bar-danger" style="width: 10%;"></div>
@ -37,10 +36,10 @@
</div>
</div>
<div class="control-group">
<label for="id_new_password2" class="control-label">{% trans 'Confirm password' %}</label>
<label for="id_new_password2" class="control-label">{{ _('Confirm password') }}</label>
<div class="controls">
<input id="id_new_password2" class="required" type="password" name="new_password2"
value="{% if form.new_password2.value %}{{ form.new_password2.value }}{% endif %}"
value="{% if form.new_password2.value() %}{{ form.new_password2.value() }}{% endif %}"
maxlength="100" />
{% if form.new_password2.errors %}
{% for error in form.new_password2.errors %}
@ -61,7 +60,7 @@
autofocus('#id_new_password1');
</script>
{% else %}
<p>{% trans 'Sorry, the link you provided is invalid or has already been used' %}.</p>
<p>{{ _('Sorry, the link you provided is invalid or has already been used') }}.</p>
{% endif %}
{% endblock %}

View File

@ -1,7 +1,6 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{% block portico_content %}
<h1 style="margin-top: 20px">{% trans "We've reset your password!" %}</h1>
<p>{% trans 'Please' %} <a href="{% url 'django.contrib.auth.views.login' %}">{% trans 'log in' %}</a>.</p>
<h1 style="margin-top: 20px">{{ _("We've reset your password!") }}</h1>
<p>{{ _('Please') }} <a href="{{ url('django.contrib.auth.views.login') }}">{{ _('log in') }}</a>.</p>
{% endblock %}

View File

@ -1,7 +1,6 @@
{% extends "zerver/portico_signup.html" %}
{% load i18n %}
{% block portico_content %}
<h1 style="margin-top: 20px">{% trans 'We just sent you a password reset!' %}</h1>
<h1>{% trans 'Check your email to finish the process' %}.</h1>
<p>({% trans "Or don't, but then why did you fill out this form?" %})</p>
<h1 style="margin-top: 20px">{{ _('We just sent you a password reset!') }}</h1>
<h1>{{ _('Check your email to finish the process') }}.</h1>
<p>({{ _("Or don't, but then why did you fill out this form?") }})</p>
{% endblock %}

View File

@ -1,47 +1,46 @@
{% load i18n %}
<div class="right-sidebar" id="right-sidebar">
<div class="alert alert_sidebar alert-error home-error-bar" id="connection-error">
<strong>{% trans 'Unable to connect to' %} {{product_name}}.</strong> {% trans 'Updates may be delayed' %}.
<br /><br /> {% trans 'Retrying soon' %}... <br /><br /> <a class="restart_get_updates_button">{% trans 'Try now' %}</a>.
<strong>{{ _('Unable to connect to') }} {{product_name}}.</strong> {{ _('Updates may be delayed') }}.
<br /><br /> {{ _('Retrying soon') }}... <br /><br /> <a class="restart_get_updates_button">{{ _('Try now') }}</a>.
</div>
<div class="alert alert_sidebar alert-error home-error-bar" id="get_old_messages_error">
<strong>{% trans 'Unable to connect to' %} {{product_name}}.</strong> {% trans 'Could not fetch messages' %}.
<br /><br /> {% trans 'Retrying soon' %}... <br /><br />
<strong>{{ _('Unable to connect to') }} {{product_name}}.</strong> {{ _('Could not fetch messages') }}.
<br /><br /> {{ _('Retrying soon') }}... <br /><br />
</div>
<div class="alert alert_sidebar alert-error home-error-bar" id="zephyr-mirror-error">
<strong>{% trans 'Your Zephyr mirror is not working' %}.</strong>
<span id="normal-zephyr-mirror-error-text">{% blocktrans %}We
<strong>{{ _('Your Zephyr mirror is not working') }}.</strong>
<span id="normal-zephyr-mirror-error-text">{% trans %}We
recommend that you <a class="webathena_login">give
{{product_name}} the ability to mirror the messages for you via
WebAthena</a>. If you'd prefer, you can instead
<a href="/zephyr-mirror" target="_blank">run the Zephyr mirror script yourself</a>
in a screen session{% endblocktrans %}.</span>
<span id="desktop-zephyr-mirror-error-text" class="notdisplayed">{% blocktrans %}To fix
in a screen session{% endtrans %}.</span>
<span id="desktop-zephyr-mirror-error-text" class="notdisplayed">{% trans %}To fix
this, you'll need
to use <a href="https://zephyr.zulip.com">the web interface</a>{% endblocktrans %}</span>
to use <a href="https://zephyr.zulip.com">the web interface</a>{% endtrans %}</span>
</div>
<div class="alert alert_sidebar alert-error home-error-bar" id="home-error"></div>
<div class="alert alert_sidebar alert-error home-error-bar" id="reloading-application"></div>
{% if enable_feedback %}
<div id="feedback_section">
<button type="button" class="btn btn-default btn-large" id="feedback_button">
<i class="icon-vector-comment"></i>&nbsp;&nbsp;{% trans 'Send feedback' %}
<i class="icon-vector-comment"></i>&nbsp;&nbsp;{{ _('Send feedback') }}
</button>
</div>
{% endif %}
<div id="user-list">
<div id="userlist-header">
<h4 class='sidebar-title' id='userlist-title'>{% trans 'USERS' %}</h4>
<h4 class='sidebar-title' id='userlist-title'>{{ _('USERS') }}</h4>
</div>
<input class="user-list-filter" type="text" placeholder="Search people" />
<ul id="user_presences" class="filters scrolling_list"></ul>
{% if show_invites %}
<a id="invite-user-link" href="#invite-user" data-toggle="modal"><i class="icon-vector-plus-sign"></i>{% trans 'Invite coworkers' %}</a>
<a id="invite-user-link" href="#invite-user" data-toggle="modal"><i class="icon-vector-plus-sign"></i>{{ _('Invite coworkers') }}</a>
{% endif %}
</div>
<div id="group-pm-list">
<div id="group-pm-header">
<h4 class='sidebar-title' id='group-pm-title'>{% trans 'GROUP PMs' %}</h4>
<h4 class='sidebar-title' id='group-pm-title'>{{ _('GROUP PMs') }}</h4>
</div>
<ul id="group-pms" class="filters scrolling_list">
</ul>

View File

@ -1,82 +1,81 @@
{% load i18n %}
<div class="modal hide" id="search-operators" tabindex="-1" role="dialog"
aria-labelledby="search-operators-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="search-operators-label">{% trans 'Search help' %}</h3>
<h3 id="search-operators-label">{{ _('Search help') }}</h3>
</div>
<div class="modal-body">
<table class="table table-striped table-condensed table-rounded table-bordered" id="fmt_help_table">
<thead>
<tr>
<th>{% trans 'Operator' %}</th>
<th>{% trans 'Effect' %}</th>
<th>{{ _('Operator') }}</th>
<th>{{ _('Effect') }}</th>
</tr>
</thead>
<tr>
<td class="operator">stream:<span class="operator_value">stream</span></td>
<td class="definition">{% trans 'Narrow to messages on stream' %} <span class="operator_value">stream</span></td>
<td class="definition">{{ _('Narrow to messages on stream') }} <span class="operator_value">stream</span></td>
</tr>
<tr>
<td class="operator">topic:<span class="operator_value">topic</span></td>
<td class="definition">{% trans 'Narrow to messages with topic' %} <span class="operator_value">topic</span></td>
<td class="definition">{{ _('Narrow to messages with topic') }} <span class="operator_value">topic</span></td>
</tr>
<tr>
<td class="operator">pm-with:<span class="operator_value">email</span></td>
<td class="definition">{% trans 'Narrow to private messages with' %} <span class="operator_value">email</span></td>
<td class="definition">{{ _('Narrow to private messages with') }} <span class="operator_value">email</span></td>
</tr>
<tr>
<td class="operator">sender:<span class="operator_value">email</span></td>
<td class="definition">{% trans 'Narrow to messages sent by' %} <span class="operator_value">email</span></td>
<td class="definition">{{ _('Narrow to messages sent by') }} <span class="operator_value">email</span></td>
</tr>
<tr>
<td class="operator">sender:me</td>
<td class="definition">{% trans 'Narrow to messages sent by you' %}.</td>
<td class="definition">{{ _('Narrow to messages sent by you') }}.</td>
</tr>
<tr>
<td class="operator">near:<span class="operator_value">id</span></td>
<td class="definition">{% trans 'Center the view around message ID' %} <span class="operator_value">id</span></td>
<td class="definition">{{ _('Center the view around message ID') }} <span class="operator_value">id</span></td>
</tr>
<tr>
<td class="operator">id:<span class="operator_value">id</span></td>
<td class="definition">{% trans 'Narrow to just message ID' %} <span class="operator_value">id</span></td>
<td class="definition">{{ _('Narrow to just message ID') }} <span class="operator_value">id</span></td>
</tr>
<tr>
<tr>
<td class="operator">is:alerted</td>
<td class="definition">{% trans 'Narrow to messages with alert words' %}.</td>
<td class="definition">{{ _('Narrow to messages with alert words') }}.</td>
</tr>
<td class="operator">is:mentioned</td>
<td class="definition">{% trans 'Narrow to messages that mention you' %}.</td>
<td class="definition">{{ _('Narrow to messages that mention you') }}.</td>
</tr>
<tr>
<td class="operator">is:private</td>
<td class="definition">{% trans 'Narrow to private messages' %}.</td>
<td class="definition">{{ _('Narrow to private messages') }}.</td>
</tr>
<tr>
<td class="operator">is:starred</td>
<td class="definition">{% trans 'Narrow to starred messages' %}.</td>
<td class="definition">{{ _('Narrow to starred messages') }}.</td>
</tr>
<tr>
<td class="operator"><span class="operator_value">keyword</span></td>
<td class="definition">{% trans 'Search for' %} <span class="operator_value">{% trans 'keyword' %}</span> {% trans 'in the topic or message content' %}</td>
<td class="definition">{{ _('Search for') }} <span class="operator_value">{{ _('keyword') }}</span> {{ _('in the topic or message content') }}</td>
</tr>
<tr>
<td class="operator">-topic:<span class="operator_value">topic</span></td>
<td class="definition">{% trans 'Exclude messages with topic' %} <span class="operator_value">topic</span></td>
<td class="definition">{{ _('Exclude messages with topic') }} <span class="operator_value">topic</span></td>
</tr>
</table>
<p>{% trans 'You can use any combination of these search operators in a single query' %}. {% trans 'For example' %}:</p>
<p>{{ _('You can use any combination of these search operators in a single query') }}. {{ _('For example') }}:</p>
<p>&nbsp; <span class="operator">stream:<span class="operator_value">streamname</span>
sender:<span class="operator_value">user@example.com</span>
<span class="operator_value">keyword</span></span></p>
<p>{% trans 'would search for messages sent by' %} <span class="operator_value">user@example.com</span> {% trans 'to stream' %}
<p>{{ _('would search for messages sent by') }} <span class="operator_value">user@example.com</span> {{ _('to stream') }}
<span class="operator_value">streamname</span>
{% trans 'containing the keyword' %} <span class="operator_value">keyword</span>.</p>
{{ _('containing the keyword') }} <span class="operator_value">keyword</span>.</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">{% trans 'Close' %}</button>
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">{{ _('Close') }}</button>
</div>
</div>

View File

@ -1,42 +1,41 @@
{% load i18n %}
<div class="modal hide" id="stream-creation" tabindex="-1" role="dialog"
aria-labelledby="stream-creation-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="stream-creation-label">{% blocktrans %}Create stream{% endblocktrans %} <span id="stream_name"></span></h3>
<h3 id="stream-creation-label">{% trans %}Create stream{% endtrans %} <span id="stream_name"></span></h3>
</div>
<form id="stream_creation_form" class="form-inline">
<div class="modal-body">
<div id="make-invite-only">
<b>{% blocktrans %}Stream accessibility{% endblocktrans %}</b><br />
<b>{% trans %}Stream accessibility{% endtrans %}</b><br />
<label class="radio">
<input type="radio" name="privacy" value="public" checked />
<span class="icon-vector-globe"></span>
{% blocktrans %}Anyone can join{% endblocktrans %}
{% trans %}Anyone can join{% endtrans %}
</label><br />
<label class="radio">
<input type="radio" name="privacy" value="invite-only" />
<span class="icon-vector-lock"></span>
{% blocktrans %}People must be invited{% endblocktrans %}
{% trans %}People must be invited{% endtrans %}
</label>
</div>
<div id="announce-new-stream">
<br />
<label class="checkbox">
<input type="checkbox" name="announce" value="announce" checked />
{% blocktrans %}Announce stream{% endblocktrans %}
{% trans %}Announce stream{% endtrans %}
</label>
<span class="icon-vector-question-sign" id="announce-stream-docs"></span>
</div>
<br />
<div class="control-group">
<label class="control-label" for="people_to_add"><b>{% blocktrans %}People to add{% endblocktrans %}</b></label><br />
<label class="control-label" for="people_to_add"><b>{% trans %}People to add{% endtrans %}</b></label><br />
<div class="controls" id="people_to_add"></div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">{% trans "Cancel" %}</button>
<button class="btn btn-primary" type="submit">{% trans "Create" %}</button>
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">{{ _("Cancel") }}</button>
<button class="btn btn-primary" type="submit">{{ _("Create") }}</button>
</div>
</form>
</div>

View File

@ -1,8 +1,7 @@
{% load i18n %}
{# Subscriptions management tab of the app. #}
<div class="subscriptions">
<h1><i class="icon-vector-exchange streams-icon"></i>{% trans "Streams" %}</h1>
<h1><i class="icon-vector-exchange streams-icon"></i>{{ _("Streams") }}</h1>
<div class="alert" id="subscriptions-status">
<span id="response"></span>
<span id="close-subscriptions-status"><i class="icon-vector-remove"></i></span>

View File

@ -1,6 +1,6 @@
{% comment %}
{#
Mail sent to us when a user accepts the ToS
{% endcomment %}
#}
Hello,

View File

@ -1,16 +1,15 @@
{% load i18n %}
<div class="modal hide" id="tutorial-finale" tabindex="-1" role="dialog"
aria-labelledby="tutorial-finale-label" aria-hidden="true">
<div class="modal-header">
<h3 id="tutorial-finale-label">{% blocktrans %}Welcome to {{ product_name }}{% endblocktrans %}</h3>
<h3 id="tutorial-finale-label">{% trans %}Welcome to {{ product_name }}{% endtrans %}</h3>
</div>
<div class="modal-body">
<p>{% blocktrans %}Streams, topics, and narrowing make {{ product_name }} conversations
efficient and productive.{% endblocktrans %}</p>
<p>{% trans %}Streams, topics, and narrowing make {{ product_name }} conversations
efficient and productive.{% endtrans %}</p>
<p>{% blocktrans %}That's all there is to it, so let's get started!{% endblocktrans %}</p>
<p>{% trans %}That's all there is to it, so let's get started!{% endtrans %}</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="submit" id="tutorial-get-started">{% blocktrans %}Get started{% endblocktrans %}</button>
<button class="btn btn-primary" type="submit" id="tutorial-get-started">{% trans %}Get started{% endtrans %}</button>
</div>
</div>

View File

@ -1,13 +1,12 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% block portico_content %}
<h1>{% blocktrans %}Unknown email unsubscribe request{% endblocktrans %}</h1>
<h1>{% trans %}Unknown email unsubscribe request{% endtrans %}</h1>
<p>{% blocktrans %}Hi there! It looks like you tried to unsubscribe from something, but we don't
recognize the URL.{% endblocktrans %}</p>
<p>{% trans %}Hi there! It looks like you tried to unsubscribe from something, but we don't
recognize the URL.{% endtrans %}</p>
<p>{% blocktrans %}Please double-check that you have the full URL and try again, or <a href="mailto:{{ zulip_admin }}?Subject=Unsubscribe%20me%2C%20please!&Body=Hi%20there!%0A%0AI%20clicked%20this%20unsubscribe%20link%20in%20a%20Zulip%20e-mail%2C%20but%20it%20took%20me%20to%20an%20error%20page%3A%0A%0A_____________%0A%0APlease%20unsubscribe%20me.%0A%0AThanks%2C%0A_____________%0A">email us</a> and we'll get this squared away!{% endblocktrans %}</p>
<p>{% trans %}Please double-check that you have the full URL and try again, or <a href="mailto:{{ zulip_admin }}?Subject=Unsubscribe%20me%2C%20please!&Body=Hi%20there!%0A%0AI%20clicked%20this%20unsubscribe%20link%20in%20a%20Zulip%20e-mail%2C%20but%20it%20took%20me%20to%20an%20error%20page%3A%0A%0A_____________%0A%0APlease%20unsubscribe%20me.%0A%0AThanks%2C%0A_____________%0A">email us</a> and we'll get this squared away!{% endtrans %}</p>
{% endblock %}

View File

@ -1,12 +1,11 @@
{% extends "zerver/portico.html" %}
{% load i18n %}
{% block portico_content %}
<h1>{% blocktrans %}Email settings updated{% endblocktrans %}</h1>
<h1>{% trans %}Email settings updated{% endtrans %}</h1>
<p>{% blocktrans %}We've updated your email subscription settings, and you won't get {{ subscription_type }} emails anymore.{% endblocktrans %}</p>
<p>{% trans %}We've updated your email subscription settings, and you won't get {{ subscription_type }} emails anymore.{% endtrans %}</p>
<p>{% blocktrans %}To undo this change or review your other subscription settings, please visit your <a href="https://{{ external_host }}/#settings">Zulip Settings page</a>{% endblocktrans %}.</p>
<p>{% trans %}To undo this change or review your other subscription settings, please visit your <a href="https://{{ external_host }}/#settings">Zulip Settings page</a>{% endtrans %}.</p>
{% endblock %}

View File

@ -1,7 +1,7 @@
{% comment %}
{#
Mail sent to us when a company accepts the ToS for Zulip Enterprise
edition.
{% endcomment %}
#}
Hello,

View File

@ -136,6 +136,8 @@ def is_django_block_tag(tag):
'ifequal',
'verbatim',
'blocktrans',
'trans',
'raw',
]
def get_handlebars_tag(text, i):

View File

@ -2,10 +2,10 @@ from __future__ import absolute_import
from django import forms
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
from django.contrib.auth.forms import SetPasswordForm, AuthenticationForm, \
PasswordResetForm
from django.conf import settings
from jinja2 import Markup as mark_safe
import logging

View File

@ -3,7 +3,7 @@ from __future__ import absolute_import
from django.conf import settings
from django.template.defaultfilters import slugify
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe
from jinja2 import Markup as mark_safe
import unicodedata
from zerver.lib.avatar import user_avatar_hash

View File

@ -0,0 +1,75 @@
"""
The contents of this file are taken from
[Django-admin](https://github.com/niwinz/django-jinja/blob/master/django_jinja/management/commands/makemessages.py)
Jinja2's i18n functionality is not exactly the same as Django's.
In particular, the tags names and their syntax are different:
1. The Django ``trans`` tag is replaced by a _() global.
2. The Django ``blocktrans`` tag is called ``trans``.
(1) isn't an issue, since the whole ``makemessages`` process is based on
converting the template tags to ``_()`` calls. However, (2) means that
those Jinja2 ``trans`` tags will not be picked up by Django's
``makemessages`` command.
There aren't any nice solutions here. While Jinja2's i18n extension does
come with extraction capabilities built in, the code behind ``makemessages``
unfortunately isn't extensible, so we can:
* Duplicate the command + code behind it.
* Offer a separate command for Jinja2 extraction.
* Try to get Django to offer hooks into makemessages().
* Monkey-patch.
We are currently doing that last thing. It turns out there we are lucky
for once: It's simply a matter of extending two regular expressions.
Credit for the approach goes to:
http://stackoverflow.com/questions/2090717/getting-translation-strings-for-jinja2-templates-integrated-with-django-1-x
"""
import re
from django.core.management.commands import makemessages
from django.utils.translation import trans_real
from django.template.base import BLOCK_TAG_START, BLOCK_TAG_END
strip_whitespace_right = re.compile(r"(%s-?\s*(trans|pluralize).*?-%s)\s+" % (BLOCK_TAG_START, BLOCK_TAG_END), re.U)
strip_whitespace_left = re.compile(r"\s+(%s-\s*(endtrans|pluralize).*?-?%s)" % (BLOCK_TAG_START, BLOCK_TAG_END), re.U)
def strip_whitespaces(src):
src = strip_whitespace_left.sub(r'\1', src)
src = strip_whitespace_right.sub(r'\1', src)
return src
class Command(makemessages.Command):
def handle(self, *args, **options):
old_endblock_re = trans_real.endblock_re
old_block_re = trans_real.block_re
old_constant_re = trans_real.constant_re
old_templatize = trans_real.templatize
# Extend the regular expressions that are used to detect
# translation blocks with an "OR jinja-syntax" clause.
trans_real.endblock_re = re.compile(
trans_real.endblock_re.pattern + '|' + r"""^-?\s*endtrans\s*-?$""")
trans_real.block_re = re.compile(
trans_real.block_re.pattern + '|' + r"""^-?\s*trans(?:\s+(?!'|")(?=.*?=.*?)|\s*-?$)""")
trans_real.plural_re = re.compile(
trans_real.plural_re.pattern + '|' + r"""^-?\s*pluralize(?:\s+.+|-?$)""")
trans_real.constant_re = re.compile(r"""_\(((?:".*?")|(?:'.*?')).*\)""")
def my_templatize(src, origin=None):
new_src = strip_whitespaces(src)
return old_templatize(new_src, origin)
trans_real.templatize = my_templatize
try:
super(Command, self).handle(*args, **options)
finally:
trans_real.endblock_re = old_endblock_re
trans_real.block_re = old_block_re
trans_real.templatize = old_templatize
trans_real.constant_re = old_constant_re

View File

@ -5,7 +5,7 @@ from django.conf import settings
from django.contrib.auth import authenticate, login, get_backends
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, HttpResponseForbidden, HttpResponse
from django.shortcuts import render_to_response, redirect
from django.shortcuts import redirect
from django.template import RequestContext, loader
from django.utils.timezone import now
from django.utils.cache import patch_cache_control
@ -67,6 +67,7 @@ import jwt
import hashlib
import hmac
from zproject.jinja2 import render_to_response
from zerver.lib.rest import rest_dispatch as _rest_dispatch
rest_dispatch = csrf_exempt((lambda request, *args, **kwargs: _rest_dispatch(request, globals(), *args, **kwargs)))
@ -231,7 +232,7 @@ def accounts_register(request):
# we have to set it here.
'password_auth_enabled': password_auth_enabled(realm),
},
context_instance=RequestContext(request))
request=request)
@zulip_login_required
def accounts_accept_terms(request):
@ -256,7 +257,7 @@ def accounts_accept_terms(request):
form = ToSForm()
return render_to_response('zerver/accounts_accept_terms.html',
{ 'form': form, 'company_name': domain, 'email': email },
context_instance=RequestContext(request))
request=request)
from zerver.lib.ccache import make_ccache
@ -316,7 +317,7 @@ def api_endpoint_docs(request):
'content': calls,
'langs': langs,
},
context_instance=RequestContext(request))
request=request)
@authenticated_json_post_view
@has_request_variables
@ -384,7 +385,7 @@ def maybe_send_to_registration(request, email, full_name=''):
urllib.parse.quote_plus(full_name.encode('utf8')))))
else:
return render_to_response('zerver/accounts_home.html', {'form': form},
context_instance=RequestContext(request))
request=request)
def login_or_register_remote_user(request, remote_username, user_profile, full_name=''):
if user_profile is None or user_profile.is_mirror_dummy:
@ -601,7 +602,7 @@ def initial_invite_page(request):
params['invite_suffix'] = user.realm.domain
return render_to_response('zerver/initial_invite_page.html', params,
context_instance=RequestContext(request))
request=request)
@require_post
def logout_then_login(request, **kwargs):
@ -665,7 +666,7 @@ def accounts_home(request):
form = create_homepage_form(request)
return render_to_response('zerver/accounts_home.html',
{'form': form, 'current_url': request.get_full_path},
context_instance=RequestContext(request))
request=request)
def approximate_unread_count(user_profile):
not_in_home_view_recipients = [sub.recipient.id for sub in \
@ -880,7 +881,7 @@ def home(request):
'embedded': narrow_stream is not None,
'product_name': product_name
},
context_instance=RequestContext(request))
request=request)
patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True)
return response
@ -1280,4 +1281,4 @@ def email_unsubscribe(request, type, token):
return process_unsubscribe(token, display_name, unsubscribe_function)
return render_to_response('zerver/unsubscribe_link_error.html', {},
context_instance=RequestContext(request))
request=request)

View File

@ -0,0 +1,33 @@
from __future__ import absolute_import # Python 2 only
from django.contrib.staticfiles.storage import staticfiles_storage
from django.template.defaultfilters import slugify, pluralize
from django.core.urlresolvers import reverse
from django.template.loader import render_to_string
from django.utils import translation
from django.http import HttpResponse
from jinja2 import Environment
from .compressors import compressed_css, minified_js
def render_to_response(*args, **kwargs):
response = render_to_string(*args, **kwargs)
return HttpResponse(response)
def environment(**options):
env = Environment(**options)
env.globals.update({
'static': staticfiles_storage.url,
'url': reverse,
'compressed_css': compressed_css,
'minified_js': minified_js,
})
env.install_gettext_translations(translation)
env.filters['slugify'] = slugify
env.filters['pluralize'] = pluralize
return env

View File

@ -0,0 +1,66 @@
from __future__ import absolute_import
import sys
import jinja2
from django.utils import six
from django.template.backends import jinja2 as django_jinja2
from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context
from django.utils.module_loading import import_string
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy
class Jinja2(django_jinja2.Jinja2):
"""Context processors aware Jinja2 backend.
The default Jinja2 backend in Django is not aware of context
processors so we just derive from the default Jinja2 backend
and add the functionality to pass the context processors to
the `Template` object.
"""
def __init__(self, params, *args, **kwargs):
# We need to remove `context_processors` from `OPTIONS` because
# `Environment` doesn't expect it
self.context_processors = params['OPTIONS'].pop('context_processors', [])
super(Jinja2, self).__init__(params, *args, **kwargs)
def get_template(self, template_name):
try:
return Template(self.env.get_template(template_name),
self.context_processors)
except jinja2.TemplateNotFound as exc:
six.reraise(TemplateDoesNotExist, TemplateDoesNotExist(exc.args),
sys.exc_info()[2])
except jinja2.TemplateSyntaxError as exc:
six.reraise(TemplateSyntaxError, TemplateSyntaxError(exc.args),
sys.exc_info()[2])
class Template(django_jinja2.Template):
"""Context processors aware Template.
This class upgrades the default `Template` to apply context
processors to the context before passing it to the `render`
function.
"""
def __init__(self, template, context_processors, *args, **kwargs):
self.context_processors = context_processors
super(Template, self).__init__(template, *args, **kwargs)
def render(self, context=None, request=None):
if context is None:
context = {}
if isinstance(context, Context):
context = context.flatten() # Jinja2 expects a dictionary
if request is not None:
context['request'] = request
context['csrf_input'] = csrf_input_lazy(request)
context['csrf_token'] = csrf_token_lazy(request)
for context_processor in self.context_processors:
cp = import_string(context_processor)
context.update(cp(request))
return self.template.render(context)

View File

@ -0,0 +1,22 @@
"""
`minified_js` is taken from `zerver.templatetags.minified_js.py`
"""
from __future__ import absolute_import # Python 2 only
from django.conf import settings
from django.template import TemplateSyntaxError
from pipeline.templatetags.compressed import CompressedCSSNode
from zerver.templatetags.minified_js import MinifiedJSNode
def compressed_css(package_name):
return CompressedCSSNode(package_name).render({package_name: package_name})
def minified_js(sourcefile):
if sourcefile not in settings.JS_SPECS:
raise TemplateSyntaxError(
"Invalid argument: no JS file %s".format(sourcefile))
return MinifiedJSNode(sourcefile).render({})

View File

@ -245,11 +245,29 @@ if PRODUCTION:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'BACKEND': 'zproject.jinja2.backends.Jinja2',
'DIRS': [
os.path.join(DEPLOY_ROOT, 'templates'),
],
'APP_DIRS': False,
'OPTIONS': {
'environment': 'zproject.jinja2.environment',
'extensions': [
'jinja2.ext.i18n',
'jinja2.ext.autoescape',
],
'context_processors': [
'zerver.context_processors.add_settings',
'zerver.context_processors.add_metrics',
],
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(DEPLOY_ROOT, 'django_templates'),
],
'APP_DIRS': False,
'OPTIONS': {
'debug': DEBUG,
'loaders': LOADERS,