mirror of https://github.com/zulip/zulip.git
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:
parent
cec0530fd8
commit
5359e6b0d4
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 |
|
||||
+--------------------------+--------------------------------------------------------+
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 won’t 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>
|
||||
|
|
|
@ -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"/>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -19,7 +18,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
{{ block.super }}
|
||||
{{ super() }}
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$("#resend_email_link").click(function () {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
|
||||
{# API information page #}
|
||||
|
||||
{% load minified_js %}
|
||||
|
||||
{% block customhead %}
|
||||
{{ block.super }}
|
||||
{% minified_js 'api' %}
|
||||
{{ super() }}
|
||||
{{ minified_js('api')|safe }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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"> {% trans 'New stream message' %}</span>
|
||||
<i class="icon-vector-bullhorn"></i><span class="compose_stream_button_label"> {{ _('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"> {% trans 'New private message' %}</span>
|
||||
<i class="icon-vector-user"></i><span class="compose_private_button_label"> {{ _('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' %} </label>
|
||||
<label id="enter-sends-label" class="compose_checkbox_label" for="enter_sends">{{ _('Press Enter to send') }} </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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% load app_filters %}
|
||||
{% comment %}
|
||||
{#
|
||||
Mail sent to a user who hasn't logged in for 24 hours.
|
||||
{% endcomment %}
|
||||
#}
|
||||
|
||||
Hello {{ name }},
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% load app_filters %}
|
||||
{% comment %}
|
||||
{#
|
||||
Mail sent to a user who hasn't logged in for 24 hours.
|
||||
{% endcomment %}
|
||||
#}
|
||||
|
||||
Hello {{ name }},
|
||||
|
||||
|
|
|
@ -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—both sending and
|
||||
receiving—a snap!{% endblocktrans %}</p>
|
||||
receiving—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 %}
|
||||
|
|
|
@ -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’s
|
||||
<p>{% trans %}Every conversation in Zulip has a <em>topic</em>, so it’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 wouldn’t tolerate email without subject lines or threading, so why do you for chat?" %}</p>
|
||||
<p>{{ _("You wouldn’t 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’re not
|
||||
around. Unfortunately, so do a lot of unimportant things.{% endblocktrans %}</p>
|
||||
<p>{% trans %}Sometimes, important things get discussed when you’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’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’s
|
||||
{% trans %}An impressive amount of knowledge lives in your chat system. Zulip’s
|
||||
powerful and fast search will delight you with how quickly you can find
|
||||
exactly what you’re looking for.{% endblocktrans %}
|
||||
exactly what you’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’s
|
||||
where it gets interesting: thanks to how Zulip categorizes messages,
|
||||
automated messages never overwhelm you. As with any topic in Zulip,
|
||||
they’re easy to focus on, skim, defer to later, or ignore—as appropriate.{% endblocktrans %}</p>
|
||||
they’re easy to focus on, skim, defer to later, or ignore—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">
|
||||
… {% trans 'and all the obvious stuff, too.' %}
|
||||
… {{ _('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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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&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&stream=pagerduty{% endverbatim %}</code></li>
|
||||
<li><b>Endpoint URL</b>: <code>{{ external_api_uri }}/v1/external/pagerduty?api_key=abcdefgh&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}}&ticket_id={{ticket.id}}&stream=zendesk{% endverbatim %}</code></li>
|
||||
<li><b>URL</b>: <code>{{ external_api_uri }}{% raw %}/v1/external/zendesk?ticket_title={{ticket.title}}&ticket_id={{ticket.id}}&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");
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>> 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>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% comment %}
|
||||
{#
|
||||
Mail sent to user when she was not logged in and received a PM or @-mention
|
||||
{% endcomment %}
|
||||
#}
|
||||
|
||||
Hello {{ name }},
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% comment %}
|
||||
{#
|
||||
Mail sent to user when she was not logged in and received a PM or @-mention
|
||||
{% endcomment %}
|
||||
#}
|
||||
|
||||
Hello {{ name }},
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
Not inside the app itself, but covered by the same structure,
|
||||
hence the name.
|
||||
#}
|
||||
|
||||
{% 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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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> {% trans 'Send feedback' %}
|
||||
<i class="icon-vector-comment"></i> {{ _('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>
|
||||
|
|
|
@ -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> <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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% comment %}
|
||||
{#
|
||||
Mail sent to us when a user accepts the ToS
|
||||
{% endcomment %}
|
||||
#}
|
||||
|
||||
Hello,
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% comment %}
|
||||
{#
|
||||
Mail sent to us when a company accepts the ToS for Zulip Enterprise
|
||||
edition.
|
||||
{% endcomment %}
|
||||
#}
|
||||
|
||||
Hello,
|
||||
|
||||
|
|
|
@ -136,6 +136,8 @@ def is_django_block_tag(tag):
|
|||
'ifequal',
|
||||
'verbatim',
|
||||
'blocktrans',
|
||||
'trans',
|
||||
'raw',
|
||||
]
|
||||
|
||||
def get_handlebars_tag(text, i):
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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({})
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue