Chapter 14: Ajax (v0.14)
This commit is contained in:
parent
0509b1267a
commit
3db55e4bac
|
@ -86,6 +86,7 @@ class Post(db.Model):
|
|||
body = db.Column(db.String(140))
|
||||
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||
language = db.Column(db.String(5))
|
||||
|
||||
def __repr__(self):
|
||||
return '<Post {}>'.format(self.body)
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
from datetime import datetime
|
||||
from flask import render_template, flash, redirect, url_for, request, g
|
||||
from flask import render_template, flash, redirect, url_for, request, g, \
|
||||
jsonify
|
||||
from flask_login import login_user, logout_user, current_user, login_required
|
||||
from werkzeug.urls import url_parse
|
||||
from flask_babel import _, get_locale
|
||||
from guess_language import guess_language
|
||||
from app import app, db
|
||||
from app.forms import LoginForm, RegistrationForm, EditProfileForm, PostForm, \
|
||||
ResetPasswordRequestForm, ResetPasswordForm
|
||||
from app.models import User, Post
|
||||
from app.email import send_password_reset_email
|
||||
from app.translate import translate
|
||||
|
||||
|
||||
@app.before_request
|
||||
|
@ -24,7 +27,11 @@ def before_request():
|
|||
def index():
|
||||
form = PostForm()
|
||||
if form.validate_on_submit():
|
||||
post = Post(body=form.post.data, author=current_user)
|
||||
language = guess_language(form.post.data)
|
||||
if language == 'UNKNOWN' or len(language) > 5:
|
||||
language = ''
|
||||
post = Post(body=form.post.data, author=current_user,
|
||||
language=language)
|
||||
db.session.add(post)
|
||||
db.session.commit()
|
||||
flash(_('Your post is now live!'))
|
||||
|
@ -189,3 +196,11 @@ def unfollow(username):
|
|||
db.session.commit()
|
||||
flash(_('You are not following %(username)s.', username=username))
|
||||
return redirect(url_for('user', username=username))
|
||||
|
||||
|
||||
@app.route('/translate', methods=['POST'])
|
||||
@login_required
|
||||
def translate_text():
|
||||
return jsonify({'text': translate(request.form['text'],
|
||||
request.form['source_language'],
|
||||
request.form['dest_language'])})
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 673 B |
|
@ -14,7 +14,17 @@
|
|||
{{ _('%(username)s said %(when)s',
|
||||
username=user_link, when=moment(post.timestamp).fromNow()) }}
|
||||
<br>
|
||||
{{ post.body }}
|
||||
<span id="post{{ post.id }}">{{ post.body }}</span>
|
||||
{% if post.language and post.language != g.locale %}
|
||||
<br><br>
|
||||
<span id="translation{{ post.id }}">
|
||||
<a href="javascript:translate(
|
||||
'#post{{ post.id }}',
|
||||
'#translation{{ post.id }}',
|
||||
'{{ post.language }}',
|
||||
'{{ g.locale }}');">{{ _('Translate') }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -53,4 +53,18 @@
|
|||
{{ super() }}
|
||||
{{ moment.include_moment() }}
|
||||
{{ moment.lang(g.locale) }}
|
||||
<script>
|
||||
function translate(sourceElem, destElem, sourceLang, destLang) {
|
||||
$(destElem).html('<img src="{{ url_for('static', filename='loading.gif') }}">');
|
||||
$.post('/translate', {
|
||||
text: $(sourceElem).text(),
|
||||
source_language: sourceLang,
|
||||
dest_language: destLang
|
||||
}).done(function(response) {
|
||||
$(destElem).text(response['text'])
|
||||
}).fail(function() {
|
||||
$(destElem).text("{{ _('Error: Could not contact server.') }}");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import json
|
||||
import requests
|
||||
from flask_babel import _
|
||||
from app import app
|
||||
|
||||
|
||||
def translate(text, source_language, dest_language):
|
||||
if 'MS_TRANSLATOR_KEY' not in app.config or \
|
||||
not app.config['MS_TRANSLATOR_KEY']:
|
||||
return _('Error: the translation service is not configured.')
|
||||
auth = {'Ocp-Apim-Subscription-Key': app.config['MS_TRANSLATOR_KEY']}
|
||||
r = requests.get('https://api.microsofttranslator.com/v2/Ajax.svc'
|
||||
'/Translate?text={}&from={}&to={}'.format(
|
||||
text, source_language, dest_language),
|
||||
headers=auth)
|
||||
if r.status_code != 200:
|
||||
return _('Error: the translation service failed.')
|
||||
return json.loads(r.content.decode('utf-8-sig'))
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2017-10-03 15:49-0700\n"
|
||||
"POT-Creation-Date: 2017-10-05 15:32-0700\n"
|
||||
"PO-Revision-Date: 2017-09-29 23:25-0700\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: es\n"
|
||||
|
@ -82,57 +82,65 @@ msgstr "Dí algo"
|
|||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: app/routes.py:30
|
||||
#: app/routes.py:37
|
||||
msgid "Your post is now live!"
|
||||
msgstr "¡Tu artículo ha sido publicado!"
|
||||
|
||||
#: app/routes.py:66
|
||||
#: app/routes.py:73
|
||||
msgid "Invalid username or password"
|
||||
msgstr "Nombre de usuario o contraseña inválidos"
|
||||
|
||||
#: app/routes.py:92
|
||||
#: app/routes.py:99
|
||||
msgid "Congratulations, you are now a registered user!"
|
||||
msgstr "¡Felicitaciones, ya eres un usuario registrado!"
|
||||
|
||||
#: app/routes.py:107
|
||||
#: app/routes.py:114
|
||||
msgid "Check your email for the instructions to reset your password"
|
||||
msgstr "Busca en tu email las instrucciones para crear una nueva contraseña"
|
||||
|
||||
#: app/routes.py:124
|
||||
#: app/routes.py:131
|
||||
msgid "Your password has been reset."
|
||||
msgstr "Tu contraseña ha sido cambiada."
|
||||
|
||||
#: app/routes.py:152
|
||||
#: app/routes.py:159
|
||||
msgid "Your changes have been saved."
|
||||
msgstr "Tus cambios han sido salvados."
|
||||
|
||||
#: app/routes.py:157 app/templates/edit_profile.html:5
|
||||
#: app/routes.py:164 app/templates/edit_profile.html:5
|
||||
msgid "Edit Profile"
|
||||
msgstr "Editar Perfil"
|
||||
|
||||
#: app/routes.py:166 app/routes.py:182
|
||||
#: app/routes.py:173 app/routes.py:189
|
||||
#, python-format
|
||||
msgid "User %(username)s not found."
|
||||
msgstr "El usuario %(username)s no ha sido encontrado."
|
||||
|
||||
#: app/routes.py:169
|
||||
#: app/routes.py:176
|
||||
msgid "You cannot follow yourself!"
|
||||
msgstr "¡No te puedes seguir a tí mismo!"
|
||||
|
||||
#: app/routes.py:173
|
||||
#: app/routes.py:180
|
||||
#, python-format
|
||||
msgid "You are following %(username)s!"
|
||||
msgstr "¡Ahora estás siguiendo a %(username)s!"
|
||||
|
||||
#: app/routes.py:185
|
||||
#: app/routes.py:192
|
||||
msgid "You cannot unfollow yourself!"
|
||||
msgstr "¡No te puedes dejar de seguir a tí mismo!"
|
||||
|
||||
#: app/routes.py:189
|
||||
#: app/routes.py:196
|
||||
#, python-format
|
||||
msgid "You are not following %(username)s."
|
||||
msgstr "No estás siguiendo a %(username)s."
|
||||
|
||||
#: app/translate.py:10
|
||||
msgid "Error: the translation service is not configured."
|
||||
msgstr "Error: el servicio de traducciones no está configurado."
|
||||
|
||||
#: app/translate.py:17
|
||||
msgid "Error: the translation service failed."
|
||||
msgstr "Error el servicio de traducciones ha fallado."
|
||||
|
||||
#: app/templates/404.html:4
|
||||
msgid "Not Found"
|
||||
msgstr "Página No Encontrada"
|
||||
|
@ -154,6 +162,10 @@ msgstr "El administrador ha sido notificado. ¡Lamentamos la inconveniencia!"
|
|||
msgid "%(username)s said %(when)s"
|
||||
msgstr "%(username)s dijo %(when)s"
|
||||
|
||||
#: app/templates/_post.html:19
|
||||
msgid "Translate"
|
||||
msgstr "Traducir"
|
||||
|
||||
#: app/templates/base.html:4
|
||||
msgid "Welcome to Microblog"
|
||||
msgstr "Bienvenido a Microblog"
|
||||
|
@ -178,6 +190,10 @@ msgstr "Perfil"
|
|||
msgid "Logout"
|
||||
msgstr "Salir"
|
||||
|
||||
#: app/templates/base.html:73
|
||||
msgid "Error: Could not contact server."
|
||||
msgstr "Error: el servidor no pudo ser contactado."
|
||||
|
||||
#: app/templates/index.html:5
|
||||
#, python-format
|
||||
msgid "Hi, %(username)s!"
|
||||
|
|
|
@ -14,4 +14,5 @@ class Config(object):
|
|||
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
|
||||
ADMINS = ['your-email@example.com']
|
||||
LANGUAGES = ['en', 'es']
|
||||
MS_TRANSLATOR_KEY = os.environ.get('MS_TRANSLATOR_KEY')
|
||||
POSTS_PER_PAGE = 25
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
"""add language to posts
|
||||
|
||||
Revision ID: 2b017edaa91f
|
||||
Revises: ae346256b650
|
||||
Create Date: 2017-10-04 22:48:34.494465
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2b017edaa91f'
|
||||
down_revision = 'ae346256b650'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('post', sa.Column('language', sa.String(length=5), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('post', 'language')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in New Issue