mirror of
https://github.com/Hopiu/django-rosetta.git
synced 2026-05-26 21:14:03 +00:00
Merge branch 'develop' into reflang
This commit is contained in:
commit
31a0427f78
14 changed files with 185 additions and 52 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -5,4 +5,6 @@ dist
|
|||
.svnignore
|
||||
.svnexternals
|
||||
build
|
||||
rosetta/locale/xx/LC_MESSAGES/*.mo
|
||||
rosetta/locale/xx/LC_MESSAGES/*.mo
|
||||
/.settings
|
||||
/.project
|
||||
|
|
|
|||
4
CHANGES
4
CHANGES
|
|
@ -1,3 +1,7 @@
|
|||
* Support timezones on the last modified PO header. Thanks @jmoiron (Issue #43)
|
||||
* Actually move to the next block when submitting a lot of translations (Issue #13)
|
||||
* Add msgctxt to the entry hash to differentiate entries with context. Thanks @metalpriest (Issue #39)
|
||||
|
||||
Version 0.6.8
|
||||
-------------
|
||||
* Switched to a pluggable storage backend model to increase compatibility with Django 1.4. Cache and Session-based storages are provided.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Features
|
|||
Requirements
|
||||
************
|
||||
|
||||
Rosetta requires Django 1.3 or later (it should work with Django 1.1 and 1.2, but it is not supported.)
|
||||
Rosetta requires Django 1.3 or later
|
||||
|
||||
************
|
||||
Installation
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
VERSION = (0, 6, 8)
|
||||
VERSION = (0, 7, 0)
|
||||
|
||||
|
||||
def get_version(svn=False, limit=3):
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@ import django
|
|||
from django.conf import settings
|
||||
from rosetta.conf import settings as rosetta_settings
|
||||
from django.core.cache import cache
|
||||
from datetime import datetime
|
||||
try:
|
||||
from django.utils import timezone
|
||||
except:
|
||||
timezone = None
|
||||
|
||||
|
||||
try:
|
||||
set
|
||||
|
|
@ -10,6 +16,22 @@ except NameError:
|
|||
from sets import Set as set # Python 2.3 fallback
|
||||
|
||||
|
||||
def timestamp_with_timezone(dt=None):
|
||||
"""
|
||||
Return a timestamp with a timezone for the configured locale. If all else
|
||||
fails, consider localtime to be UTC.
|
||||
"""
|
||||
dt = dt or datetime.now()
|
||||
if timezone is None:
|
||||
return dt.strftime('%Y-%m-%d %H:%M%z')
|
||||
if not dt.tzinfo:
|
||||
tz = timezone.get_current_timezone()
|
||||
if not tz:
|
||||
tz = timezone.utc
|
||||
dt = dt.replace(tzinfo=timezone.get_current_timezone())
|
||||
return dt.strftime("%Y-%m-%d %H:%M%z")
|
||||
|
||||
|
||||
def find_pos(lang, project_apps=True, django_apps=False, third_party_apps=False):
|
||||
"""
|
||||
scans a couple possible repositories of gettext catalogs for the given
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
from django.utils import importlib
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
|
|
@ -56,12 +58,28 @@ class CacheRosettaStorage(BaseRosettaStorage):
|
|||
# so we need to per-user key prefix, which we store in the session
|
||||
def __init__(self, request):
|
||||
super(CacheRosettaStorage, self).__init__(request)
|
||||
|
||||
if 'rosetta_cache_storage_key_prefix' in self.request.session:
|
||||
self._key_prefix = self.request.session['rosetta_cache_storage_key_prefix']
|
||||
else:
|
||||
self._key_prefix = hashlib.new('sha1', str(time.time())).hexdigest()
|
||||
self.request.session['rosetta_cache_storage_key_prefix'] = self._key_prefix
|
||||
|
||||
if self.request.session['rosetta_cache_storage_key_prefix'] != self._key_prefix:
|
||||
raise ImproperlyConfigured("You can't use the CacheRosettaStorage because your Django Session storage doesn't seem to be working. The CacheRosettaStorage relies on the Django Session storage to avoid conflicts.")
|
||||
|
||||
# Make sure we're not using DummyCache
|
||||
if 'dummycache' in settings.CACHES['default']['BACKEND'].lower():
|
||||
raise ImproperlyConfigured("You can't use the CacheRosettaStorage if your cache isn't correctly set up (you are use the DummyCache cache backend).")
|
||||
|
||||
# Make sure the actually actually works
|
||||
try:
|
||||
self.set('rosetta_cache_test', 'rosetta')
|
||||
if not self.get('rosetta_cache_test') == 'rosetta':
|
||||
raise ImproperlyConfigured("You can't use the CacheRosettaStorage if your cache isn't correctly set up, please double check your Django DATABASES setting and that the cache server is responding.")
|
||||
finally:
|
||||
self.delete('rosetta_cache_test')
|
||||
|
||||
def get(self, key, default=None):
|
||||
#print ('get', self._key_prefix + key)
|
||||
return cache.get(self._key_prefix + key, default)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>{% load url from future %}
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>{% block pagetitle %}Rosetta{% endblock %}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<link rel="stylesheet" href="{{ADMIN_MEDIA_PREFIX}}css/base.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="{{ADMIN_MEDIA_PREFIX}}css/forms.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="{{ADMIN_MEDIA_PREFIX}}css/changelists.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="{{ADMIN_MEDIA_PREFIX}}css/changelists.css" type="text/css"/>
|
||||
<style type="text/css" media="screen">
|
||||
{% include 'rosetta/css/rosetta.css' %}
|
||||
</style>
|
||||
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
|
||||
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
//<!--
|
||||
google.load("jquery", "1.3");
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<div id="header">
|
||||
{% block header %}
|
||||
<div id="branding">
|
||||
<h1 id="site-name"><a href="{% url rosetta-pick-file %}">Rosetta</a> </h1>
|
||||
<h1 id="site-name"><a href="{% url 'rosetta-pick-file' %}">Rosetta</a> </h1>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
{% extends "rosetta/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block pagetitle %}{{block.super}} - {% trans "Language selection" %}{% endblock %}
|
||||
|
||||
{% block breadcumbs %}
|
||||
<div><a href="{% url rosetta-pick-file %}">{% trans "Home" %}</a> › {% trans "Language selection" %}</div>
|
||||
<div><a href="{% url 'rosetta-pick-file' %}">{% trans "Home" %}</a> › {% trans "Language selection" %}</div>
|
||||
{% if do_session_warn %}<p class="errornote session-warn">{% trans "Couldn't load the specified language file. This usually happens when using the Encrypted Cookies Session Storage backend on Django 1.4 or higher.<br/>Setting ROSETTA_STORAGE_CLASS = 'rosetta.storage.CacheRosettaStorage' in your settings file should fix this." %}</p>{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -22,7 +23,7 @@
|
|||
|
||||
{% for lid,language,pos in languages %}
|
||||
{% if pos %}
|
||||
|
||||
|
||||
<div class="module">
|
||||
<h2>{{language}}</h2>
|
||||
<table cellspacing="0">
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
<tbody>
|
||||
{% for app,path,po in pos %}
|
||||
<tr class="{% cycle row1,row2 %}">
|
||||
<td><a href="{% url rosetta-language-selection lid,forloop.counter0 %}{% if do_django %}?django{% endif %}{% if do_rosetta %}?rosetta{% endif %}">{{ app|title }}</a></td>
|
||||
<td><a href="{% url 'rosetta-language-selection' lid forloop.counter0 %}{% if do_django %}?django{% endif %}{% if do_rosetta %}?rosetta{% endif %}">{{ app|title }}</a></td>
|
||||
<td class="ch-progress r">{{po.percent_translated|floatformat:2}}%</td>
|
||||
{% with po.untranslated_entries|length as len_untranslated_entries %}
|
||||
<td class="ch-messages r">{{po.translated_entries|length|add:len_untranslated_entries}}</td>
|
||||
|
|
@ -55,7 +56,7 @@
|
|||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<h1>{% trans "Nothing to translate!" %}</h1>
|
||||
<p>{% trans "You haven't specified any languages in your settings file, or haven't yet generated a batch of translation catalogs." %}</p>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,27 @@
|
|||
{% extends "rosetta/base.html" %}
|
||||
{% load rosetta i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block header %}
|
||||
{{block.super}}
|
||||
<div id="user-tools">
|
||||
<p>
|
||||
<span><a href="{% url rosetta-pick-file %}">{% trans "Pick another file" %}</a> /
|
||||
<a href="{% url rosetta-download-file %}">{% trans "Download this catalog" %}</a></span>
|
||||
<span><a href="{% url 'rosetta-pick-file' %}">{% trans "Pick another file" %}</a> /
|
||||
<a href="{% url 'rosetta-download-file' %}">{% trans "Download this catalog" %}</a></span>
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block pagetitle %}{{block.super}} - {{MESSAGES_SOURCE_LANGUAGE_NAME}} - {{rosetta_i18n_lang_name}} ({{ rosetta_i18n_pofile.percent_translated|floatformat:0 }}%){% endblock %}
|
||||
|
||||
{% block breadcumbs %}
|
||||
<div>
|
||||
<a href="{% url rosetta-pick-file %}">{% trans "Home" %}</a> ›
|
||||
{{ rosetta_i18n_lang_name }} ›
|
||||
{{ rosetta_i18n_app|title }} ›
|
||||
<a href="{% url 'rosetta-pick-file' %}">{% trans "Home" %}</a> ›
|
||||
{{ rosetta_i18n_lang_name }} ›
|
||||
{{ rosetta_i18n_app|title }} ›
|
||||
{% blocktrans with rosetta_i18n_pofile.percent_translated|floatformat:2 as percent_translated %}Progress: {{ percent_translated }}%{% endblocktrans %}
|
||||
</div>
|
||||
{% if not rosetta_i18n_write %}<p class="errornote read-only">{% trans "File is read-only: download the file when done editing!" %}</p>{% endif %}
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
{% block main %}
|
||||
<h1>{% blocktrans %}Translate into {{rosetta_i18n_lang_name}}{% endblocktrans %}</h1>
|
||||
|
||||
|
||||
<ul class="object-tools">
|
||||
<li class="nobubble">{% trans "Display:" %}</li>
|
||||
<li {% ifequal rosetta_i18n_filter 'untranslated' %}class="active"{% endifequal %}><a href="?filter=untranslated">{% trans "Untranslated only" %}</a></li>
|
||||
|
|
@ -64,7 +65,7 @@
|
|||
{% endif %}
|
||||
{% endcomment %}
|
||||
</div>
|
||||
|
||||
|
||||
<form method="post" action="">
|
||||
<table>
|
||||
<thead>
|
||||
|
|
@ -86,7 +87,7 @@
|
|||
<span class="part">{{message.msgid|format_message|linebreaksbr}}</span>
|
||||
<span class="part">{{message.msgid_plural|format_message|linebreaksbr}}</span>
|
||||
</div>
|
||||
|
||||
|
||||
{% if message.msgctxt %}
|
||||
<span class="context">{% trans "Context hint" %}: {{message.msgctxt|safe}}</span>
|
||||
{% else %}
|
||||
|
|
@ -94,7 +95,7 @@
|
|||
<span class="context">{% trans "Context hint" %}: {{message.comment|safe}}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
</td>
|
||||
<td class="translation">
|
||||
{% for k, msgstr in message.msgstr_plural.items|dictsort:"0" %}
|
||||
|
|
@ -110,7 +111,7 @@
|
|||
{% else %}
|
||||
{% if message.comment %}
|
||||
<span class="context">{% trans "Context hint" %}: {{message.comment|safe}}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if main_language %}<td class="original">{{ message.main_lang|format_message|linebreaksbr }}</td>{% endif %}
|
||||
|
|
@ -124,7 +125,7 @@
|
|||
</td>
|
||||
<td class="location">
|
||||
{% for fn,lineno in message.occurrences %}
|
||||
<code{% if forloop.counter|gt:"3" %} class="hide"{% endif %}>{{ fn }}:{{lineno}}</code>
|
||||
<code{% if forloop.counter|gt:"3" %} class="hide"{% endif %}>{{ fn }}:{{lineno}}</code>
|
||||
{% endfor %}
|
||||
{% if message.occurrences|length|gt:"3" %}
|
||||
<a href="#">… ({% blocktrans count message.occurrences|length|minus:"3" as more_count %}{{more_count}} more{% plural %}{{more_count}} more{% endblocktrans %})</a>
|
||||
|
|
@ -140,8 +141,8 @@
|
|||
<input type="hidden" name="query" value="{{query}}" />
|
||||
{% endif %}
|
||||
<input type="submit" class="default" name="_next" value="{% trans "Save and translate next block" %}" tabindex="{% increment tab_idx %}"/>
|
||||
|
||||
|
||||
|
||||
|
||||
{% if needs_pagination %}
|
||||
{% trans "Skip to page:" %}
|
||||
{% for i in page_range %}
|
||||
|
|
@ -150,7 +151,7 @@
|
|||
{% else %}
|
||||
{% ifequal i page %}
|
||||
<span class="this-page">{{i}}</span>
|
||||
{% else %}
|
||||
{% else %}
|
||||
<a href="?page={{i}}{% if query %}&query={{query}}{% endif %}">{{i}}</a>
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
|
|
@ -158,12 +159,12 @@
|
|||
{% else %}
|
||||
{% trans "Displaying:" %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% with paginator.object_list|length as hits %}
|
||||
<strong>{% blocktrans count rosetta_i18n_pofile|length as message_number %}{{hits}}/{{message_number}} message{% plural %}{{hits}}/{{message_number}} messages{% endblocktrans %}</strong>
|
||||
<strong>{% blocktrans count rosetta_i18n_pofile|length as message_number %}{{hits}}/{{message_number}} message{% plural %}{{hits}}/{{message_number}} messages{% endblocktrans %}</strong>
|
||||
{% endwith %}
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ class RosettaTestCase(TestCase):
|
|||
self.assertTrue('String 1' in r.content)
|
||||
self.assertTrue('String 1' in r2.content)
|
||||
self.assertTrue('m_08e4e11e2243d764fc45a5a4fba5d0f2' in r.content)
|
||||
r = self.client.post(reverse('rosetta-home'), dict(m_08e4e11e2243d764fc45a5a4fba5d0f2='Hello, world', _next='_next'))
|
||||
r = self.client.post(reverse('rosetta-home'), dict(m_08e4e11e2243d764fc45a5a4fba5d0f2='Hello, world', _next='_next'), follow=True)
|
||||
r2 = self.client2.get(reverse('rosetta-home'))
|
||||
|
||||
# Client 2 reloads the home, forces a reload of the catalog,
|
||||
|
|
@ -220,14 +220,19 @@ class RosettaTestCase(TestCase):
|
|||
self.assertTrue('String 2' in r.content and 'm_e48f149a8b2e8baa81b816c0edf93890' in r.content)
|
||||
|
||||
# client 2 posts!
|
||||
r2 = self.client2.post(reverse('rosetta-home'), dict(m_e48f149a8b2e8baa81b816c0edf93890='Hello, world, from client two!', _next='_next'))
|
||||
r2 = self.client2.post(reverse('rosetta-home'), dict(m_e48f149a8b2e8baa81b816c0edf93890='Hello, world, from client two!', _next='_next'), follow=True)
|
||||
|
||||
self.assertTrue('save-conflict' not in r2.content)
|
||||
|
||||
# uh-oh here comes client 1
|
||||
r = self.client.post(reverse('rosetta-home'), dict(m_e48f149a8b2e8baa81b816c0edf93890='Hello, world, from client one!', _next='_next'))
|
||||
r = self.client.post(reverse('rosetta-home'), dict(m_e48f149a8b2e8baa81b816c0edf93890='Hello, world, from client one!', _next='_next'), follow=True)
|
||||
# An error message is displayed
|
||||
self.assertTrue('save-conflict' in r.content)
|
||||
|
||||
# client 2 won
|
||||
pofile_content = open(self.dest_file, 'r').read()
|
||||
self.assertTrue('Hello, world, from client two!' in pofile_content)
|
||||
|
||||
# Both clients show all strings, error messages are gone
|
||||
r = self.client.get(reverse('rosetta-home') + '?filter=translated')
|
||||
self.assertTrue('save-conflict' not in r.content)
|
||||
|
|
@ -472,3 +477,14 @@ class RosettaTestCase(TestCase):
|
|||
self.client2.get(reverse('rosetta-language-selection', args=('xx', 0, ), kwargs=dict()))
|
||||
|
||||
self.assertTrue(self.client.session.get('rosetta_cache_storage_key_prefix') != self.client2.session.get('rosetta_cache_storage_key_prefix'))
|
||||
|
||||
def test_21_Test_Issue_gh39(self):
|
||||
shutil.copy(os.path.normpath(os.path.join(self.curdir, './django.po.issue39gh.template')), self.dest_file)
|
||||
|
||||
self.client.get(reverse('rosetta-pick-file') + '?filter=third-party')
|
||||
r = self.client.get(reverse('rosetta-language-selection', args=('xx', 0), kwargs=dict()))
|
||||
r = self.client.get(reverse('rosetta-home'))
|
||||
# We have distinct hashes, even though the msgid and msgstr are identical
|
||||
self.assertTrue('m_4765f7de94996d3de5975fa797c3451f' in r.content)
|
||||
self.assertTrue('m_08e4e11e2243d764fc45a5a4fba5d0f2' in r.content)
|
||||
|
||||
|
|
|
|||
26
rosetta/tests/django.po.issue39gh.template
Normal file
26
rosetta/tests/django.po.issue39gh.template
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Rosetta\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-21 12:21+0200\n"
|
||||
"PO-Revision-Date: 2008-09-22 11:02\n"
|
||||
"Last-Translator: Admin Admin <admin@admin.com>\n"
|
||||
"Language-Team: French <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Translated-Using: django-rosetta 0.4.RC2\n"
|
||||
|
||||
#: templates/base.html:43
|
||||
msgctxt "Report (by_customer). Parent table: invoices"
|
||||
msgid "String 1"
|
||||
msgstr ""
|
||||
|
||||
#: templates/base.html:44
|
||||
msgid "String 1"
|
||||
msgstr ""
|
||||
|
|
@ -10,7 +10,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django.views.decorators.cache import never_cache
|
||||
from rosetta.conf import settings as rosetta_settings
|
||||
from rosetta.polib import pofile
|
||||
from rosetta.poutil import find_pos, pagination_range
|
||||
from rosetta.poutil import find_pos, pagination_range, timestamp_with_timezone
|
||||
from rosetta.signals import entry_changed, post_save
|
||||
from rosetta.storage import get_storage
|
||||
import re
|
||||
|
|
@ -65,7 +65,11 @@ def home(request):
|
|||
if rosetta_i18n_write:
|
||||
rosetta_i18n_pofile = pofile(rosetta_i18n_fn, wrapwidth=rosetta_settings.POFILE_WRAP_WIDTH)
|
||||
for entry in rosetta_i18n_pofile:
|
||||
entry.md5hash = hashlib.md5(entry.msgid.encode("utf8") + entry.msgstr.encode("utf8")).hexdigest()
|
||||
entry.md5hash = hashlib.md5(
|
||||
entry.msgid.encode("utf8") +
|
||||
entry.msgstr.encode("utf8") +
|
||||
(entry.msgctxt and entry.msgctxt.encode("utf8") or "")
|
||||
).hexdigest()
|
||||
|
||||
else:
|
||||
rosetta_i18n_pofile = storage.get('rosetta_i18n_pofile')
|
||||
|
|
@ -140,7 +144,7 @@ def home(request):
|
|||
|
||||
rosetta_i18n_pofile.metadata['Last-Translator'] = unicodedata.normalize('NFKD', u"%s %s <%s>" % (request.user.first_name, request.user.last_name, request.user.email)).encode('ascii', 'ignore')
|
||||
rosetta_i18n_pofile.metadata['X-Translated-Using'] = u"django-rosetta %s" % rosetta.get_version(False)
|
||||
rosetta_i18n_pofile.metadata['PO-Revision-Date'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M%z')
|
||||
rosetta_i18n_pofile.metadata['PO-Revision-Date'] = timestamp_with_timezone()
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
|
|
@ -176,15 +180,11 @@ def home(request):
|
|||
storage.set('rosetta_i18n_pofile', rosetta_i18n_pofile)
|
||||
|
||||
# Retain query arguments
|
||||
query_arg = ''
|
||||
if 'query' in request.REQUEST:
|
||||
query_arg = '?query=%s' % request.REQUEST.get('query')
|
||||
query_arg = '?_next=1'
|
||||
if 'query' in request.GET or 'query' in request.POST:
|
||||
query_arg += '&query=%s' % request.REQUEST.get('query')
|
||||
if 'page' in request.GET:
|
||||
if query_arg:
|
||||
query_arg = query_arg + '&'
|
||||
else:
|
||||
query_arg = '?'
|
||||
query_arg = query_arg + 'page=%d' % int(request.GET.get('page'))
|
||||
query_arg += '&page=%d&_next=1' % int(request.GET.get('page'))
|
||||
return HttpResponseRedirect(reverse('rosetta-home') + iri_to_uri(query_arg))
|
||||
rosetta_i18n_lang_name = _(storage.get('rosetta_i18n_lang_name'))
|
||||
rosetta_i18n_lang_code = storage.get('rosetta_i18n_lang_code')
|
||||
|
|
@ -215,6 +215,14 @@ def home(request):
|
|||
page = int(request.GET.get('page'))
|
||||
else:
|
||||
page = 1
|
||||
|
||||
if '_next' in request.GET or '_next' in request.POST:
|
||||
page += 1
|
||||
if page > paginator.num_pages:
|
||||
page = 1
|
||||
query_arg = '?page=%d' % page
|
||||
return HttpResponseRedirect(reverse('rosetta-home') + iri_to_uri(query_arg))
|
||||
|
||||
rosetta_messages = paginator.page(page).object_list
|
||||
if rosetta_settings.MAIN_LANGUAGE and rosetta_settings.MAIN_LANGUAGE != rosetta_i18n_lang_code:
|
||||
|
||||
|
|
@ -367,7 +375,11 @@ def lang_sel(request, langid, idx):
|
|||
storage.set('rosetta_i18n_fn', file_)
|
||||
po = pofile(file_)
|
||||
for entry in po:
|
||||
entry.md5hash = hashlib.md5(entry.msgid.encode("utf8") + entry.msgstr.encode("utf8")).hexdigest()
|
||||
entry.md5hash = hashlib.md5(
|
||||
entry.msgid.encode("utf8") +
|
||||
entry.msgstr.encode("utf8") +
|
||||
(entry.msgctxt and entry.msgctxt.encode("utf8") or "")
|
||||
).hexdigest()
|
||||
|
||||
storage.set('rosetta_i18n_pofile', po)
|
||||
try:
|
||||
|
|
|
|||
23
runtests_multi_venv.sh
Normal file
23
runtests_multi_venv.sh
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
. venv_13/bin/activate
|
||||
cd testproject
|
||||
python manage.py --version
|
||||
python manage.py test rosetta
|
||||
cd ..
|
||||
deactivate
|
||||
|
||||
. venv_14/bin/activate
|
||||
cd testproject
|
||||
python manage.py --version
|
||||
python manage.py test rosetta
|
||||
cd ..
|
||||
deactivate
|
||||
|
||||
. venv_15/bin/activate
|
||||
cd testproject
|
||||
python manage.py --version
|
||||
python manage.py test rosetta
|
||||
cd ..
|
||||
deactivate
|
||||
|
||||
|
|
@ -17,6 +17,17 @@ DATABASES = {
|
|||
}
|
||||
}
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': '127.0.0.1:11211',
|
||||
'KEY_PREFIX': 'ROSETTA_TEST'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}
|
||||
|
||||
TEST_DATABASE_CHARSET = "utf8"
|
||||
TEST_DATABASE_COLLATION = "utf8_general_ci"
|
||||
|
||||
|
|
@ -49,12 +60,9 @@ ROOT_URLCONF = 'testproject.urls'
|
|||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = True
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
|
||||
#ROSETTA_STORAGE_CLASS = 'rosetta.storage.SessionRosettaStorage'
|
||||
ROSETTA_STORAGE_CLASS = 'rosetta.storage.CacheRosettaStorage'
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': '127.0.0.1:11212',
|
||||
}
|
||||
}
|
||||
SECRET_KEY = 'empty'
|
||||
|
|
|
|||
Loading…
Reference in a new issue