Commit b30ced3d authored by Michal Čihař's avatar Michal Čihař

Merge remote-tracking branch 'origin/master'

parents 09a60d8e 2ebb6623
......@@ -22,6 +22,10 @@ class Command(BaseCommand):
Permission.objects.get(codename = 'accept_suggestion'),
Permission.objects.get(codename = 'delete_suggestion'),
Permission.objects.get(codename = 'ignore_check'),
Permission.objects.get(codename = 'upload_dictionary'),
Permission.objects.get(codename = 'add_dictionary'),
Permission.objects.get(codename = 'change_dictionary'),
Permission.objects.get(codename = 'delete_dictionary'),
)
group, created = Group.objects.get_or_create(name = 'Managers')
group.permissions.add(
......@@ -35,6 +39,10 @@ class Command(BaseCommand):
Permission.objects.get(codename = 'accept_suggestion'),
Permission.objects.get(codename = 'delete_suggestion'),
Permission.objects.get(codename = 'ignore_check'),
Permission.objects.get(codename = 'upload_dictionary'),
Permission.objects.get(codename = 'add_dictionary'),
Permission.objects.get(codename = 'change_dictionary'),
Permission.objects.get(codename = 'delete_dictionary'),
)
if options['move']:
for u in User.objects.all():
......
......@@ -111,6 +111,10 @@ Weblate uses privileges system based on Django. It defines following extra privi
* Can save translation [Users, Managers]
* Can accept suggestion [Users, Managers]
* Can accept suggestion [Users, Managers]
* Can import dictionary [Users, Managers]
* Can add dictionary [Users, Managers]
* Can change dictionary [Users, Managers]
* Can delete dictionary [Users, Managers]
The default setup (after you run :program:`./manage.py setupgroups`) consists
of two groups `Users` and `Managers` which have privileges as descibed above.
......
......@@ -13,12 +13,14 @@
{% if words.object_list %}
<h2>{% trans "Dictionary" %}</h2>
<table>
<thead>
<tr>
<th>{% trans "Source" %}</th>
<th>{% trans "Translation" %}</th>
<th>{% trans "Actions" %}</th>
<th colspan="2">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
......@@ -26,7 +28,24 @@
<tr>
<td class="translatetext">{{ word.source }}</td>
<td class="translatetext">{{ word.target }}</td>
<td></td>
<td>
{% if perms.trans.change_dictionary %}
<form action="{% url 'trans.views.edit_dictionary' project=project.slug lang=language.code %}" method="get">
{% csrf_token %}
<input type="hidden" name="id" value="{{ word.id }}" />
<input type="submit" class="button" value="{% trans "Edit" %}" />
</form>
{% endif %}
</td>
<td>
{% if perms.trans.delete_dictionary %}
<form action="{% url 'trans.views.delete_dictionary' project=project.slug lang=language.code %}" method="post">
{% csrf_token %}
<input type="hidden" name="id" value="{{ word.id }}" />
<input type="submit" class="button" value="{% trans "Delete" %}" />
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
......@@ -49,5 +68,30 @@
</ul>
{% endif %}
{% if perms.trans.add_dictionary %}
<h2>{% trans "Add new word" %}</h2>
<form method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="{% trans "Add" %}" />
</form>
{% endif %}
{% if perms.trans.upload_dictionary %}
<h2>{% trans "Import dictionary" %}</h2>
<p>{% trans "You can upload any format which is understood by Translate Toolkit for example csv or po file." %}</p>
<form action="{% url 'trans.views.upload_dictionary' project=project.slug lang=language.code %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ uploadform.as_table }}
</table>
<input type="submit" value="{% trans "Import" %}" />
</form>
{% endif %}
{% endblock %}
{% extends "base.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcums %}
<li><a href="{{ project.get_absolute_url }}">{{ project }}</a></li>
<li><a href="{% url 'trans.views.show_dictionaries' project=project.slug %}">{% trans "dictionaries" %}</a></li>
<li><a href="{% url 'trans.views.show_dictionary' project=project.slug lang=language.code %}">{{ language }}</a></li>
{% endblock %}
{% block content %}
{% if perms.trans.add_dictionary %}
<h2>{% trans "Change word" %}</h2>
<form method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="{% trans "Save" %}" />
</form>
{% endif %}
{% endblock %}
......@@ -42,7 +42,7 @@
{% for dict in dicts %}
<li><a href="{% url 'trans.views.show_dictionary' project=object.slug lang=dict.code %}">{{ dict }}</a></li>
{% endfor %}
<li><a href="{% url 'trans.views.show_dictionaries' project=object.slug %}">Manage all dictionaries</a></li>
<li><a href="{% url 'trans.views.show_dictionaries' project=object.slug %}">{% trans "Manage all dictionaries" %}</a></li>
</ul>
</div>
{% include "git-tools.html" %}
......
......@@ -113,3 +113,11 @@ class AutoForm(forms.Form):
choices = [(s.slug, s.name) for s in obj.subproject.project.subproject_set.exclude(id = obj.subproject.id)]
super(AutoForm, self).__init__(*args, **kwargs)
self.fields['subproject'].choices = [('', _('All subprojects'))] + choices
class WordForm(forms.Form):
source = forms.CharField(label = _('Source'))
target = forms.CharField(label = _('Translation'))
class DictUploadForm(forms.Form):
file = forms.FileField(label = _('File'))
overwrite = forms.BooleanField(label = _('Overwrite existing'), required = False)
......@@ -9,6 +9,7 @@ from whoosh import qparser
from util import is_plural, split_plural, join_plural, msg_checksum
import trans.search
from translate.storage import factory
IGNORE_WORDS = set([
'a',
......@@ -231,3 +232,39 @@ class UnitManager(models.Manager):
translation__subproject__project = unit.translation.subproject.project,
translation__language = unit.translation.language
)
class DictionaryManager(models.Manager):
def upload(self, project, language, fileobj, overwrite):
# Needed to behave like something what translate toolkit expects
fileobj.mode = "r"
ret = 0
store = factory.getobject(fileobj)
for unit in store.units:
# We care only about translated things
if not unit.istranslatable() or not unit.istranslated():
continue
# Ignore too long words
if len(unit.source) > 200 or len(unit.target) > 200:
continue
# Get object
word, created = self.get_or_create(
project = project,
language = language,
source = unit.source
)
# Should we write translation
if not created and not overwrite:
continue
# Store word
word.target = unit.target
word.save()
ret += 1
return ret
......@@ -22,7 +22,7 @@ from datetime import datetime
import trans
import trans.checks
from trans.managers import TranslationManager, UnitManager
from trans.managers import TranslationManager, UnitManager, DictionaryManager
from util import is_plural, split_plural, join_plural
logger = logging.getLogger('weblate')
......@@ -937,6 +937,14 @@ class Dictionary(models.Model):
source = models.CharField(max_length = 200, db_index = True)
target = models.CharField(max_length = 200)
objects = DictionaryManager()
class Meta:
ordering = ['source']
permissions = (
('upload_dictionary', "Can import dictionary"),
)
def __unicode__(self):
return '%s/%s: %s -> %s' % (
self.project,
......
......@@ -10,10 +10,11 @@ from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.models import AnonymousUser
from django.db.models import Q, Count
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.urlresolvers import reverse
from trans.models import Project, SubProject, Translation, Unit, Suggestion, Check, Dictionary, Change
from lang.models import Language
from trans.forms import TranslationForm, UploadForm, SimpleUploadForm, ExtraUploadForm, SearchForm, MergeForm, AutoForm
from trans.forms import TranslationForm, UploadForm, SimpleUploadForm, ExtraUploadForm, SearchForm, MergeForm, AutoForm, WordForm, DictUploadForm
from util import is_plural, split_plural, join_plural
from accounts.models import Profile
from whoosh.analysis import StandardAnalyzer, StemmingAnalyzer
......@@ -133,10 +134,80 @@ def show_dictionaries(request, project):
'project': obj,
}))
@login_required
@permission_required('trans.change_dictionary')
def edit_dictionary(request, project, lang):
prj = get_object_or_404(Project, slug = project)
lang = get_object_or_404(Language, code = lang)
word = get_object_or_404(Dictionary, project = prj, language = lang, id = request.GET.get('id'))
if request.method == 'POST':
form = WordForm(request.POST)
if form.is_valid():
word.source = form.cleaned_data['source']
word.target = form.cleaned_data['target']
word.save()
return HttpResponseRedirect(reverse('trans.views.show_dictionary', kwargs = {'project': prj.slug, 'lang': lang.code}))
else:
form = WordForm(initial = {'source': word.source, 'target': word.target })
return render_to_response('edit_dictionary.html', RequestContext(request, {
'title': _('%(language)s dictionary for %(project)s') % {'language': lang, 'project': prj},
'project': prj,
'language': lang,
'form': form,
}))
@login_required
@permission_required('trans.delete_dictionary')
def delete_dictionary(request, project, lang):
prj = get_object_or_404(Project, slug = project)
lang = get_object_or_404(Language, code = lang)
word = get_object_or_404(Dictionary, project = prj, language = lang, id = request.POST.get('id'))
word.delete()
return HttpResponseRedirect(reverse('trans.views.show_dictionary', kwargs = {'project': prj.slug, 'lang': lang.code}))
@login_required
@permission_required('trans.upload_dictionary')
def upload_dictionary(request, project, lang):
prj = get_object_or_404(Project, slug = project)
lang = get_object_or_404(Language, code = lang)
if request.method == 'POST':
form = DictUploadForm(request.POST, request.FILES)
if form.is_valid():
count = Dictionary.objects.upload(prj, lang, request.FILES['file'], form.cleaned_data['overwrite'])
if count == 0:
messages.add_message(request, messages.WARNING, _('No words to import found in file.'))
else:
messages.add_message(request, messages.INFO, _('Imported %d words from file.') % count)
else:
messages.add_message(request, messages.ERROR, _('Failed to process form!'))
else:
messages.add_message(request, messages.ERROR, _('Failed to process form!'))
return HttpResponseRedirect(reverse('trans.views.show_dictionary', kwargs = {'project': prj.slug, 'lang': lang.code}))
def show_dictionary(request, project, lang):
prj = get_object_or_404(Project, slug = project)
lang = get_object_or_404(Language, code = lang)
if request.method == 'POST' and request.user.has_perm('trans.add_dictionary'):
form = WordForm(request.POST)
if form.is_valid():
Dictionary.objects.create(
project = prj,
language = lang,
source = form.cleaned_data['source'],
target = form.cleaned_data['target']
)
return HttpResponseRedirect(request.get_full_path())
else:
form = WordForm()
uploadform = DictUploadForm()
words = Dictionary.objects.filter(project = prj, language = lang).order_by('source')
limit = request.GET.get('limit', 25)
......@@ -158,6 +229,8 @@ def show_dictionary(request, project, lang):
'project': prj,
'language': lang,
'words': words,
'form': form,
'uploadform': uploadform,
}))
def show_project(request, project):
......
......@@ -24,8 +24,11 @@ urlpatterns = patterns('',
url(r'^projects/$', 'django.views.generic.simple.redirect_to', {'url': '/'}),
url(r'^projects/(?P<project>[^/]*)/$', 'trans.views.show_project'),
url(r'^projects/(?P<project>[^/]*)/dictionary/$', 'trans.views.show_dictionaries'),
url(r'^projects/(?P<project>[^/]*)/dictionary/(?P<lang>[^/]*)/$', 'trans.views.show_dictionary'),
url(r'^dictionaries/(?P<project>[^/]*)/$', 'trans.views.show_dictionaries'),
url(r'^dictionaries/(?P<project>[^/]*)/(?P<lang>[^/]*)/$', 'trans.views.show_dictionary'),
url(r'^dictionaries/(?P<project>[^/]*)/(?P<lang>[^/]*)/upload/$', 'trans.views.upload_dictionary'),
url(r'^dictionaries/(?P<project>[^/]*)/(?P<lang>[^/]*)/delete/$', 'trans.views.delete_dictionary'),
url(r'^dictionaries/(?P<project>[^/]*)/(?P<lang>[^/]*)/edit/$', 'trans.views.edit_dictionary'),
url(r'^projects/(?P<project>[^/]*)/(?P<subproject>[^/]*)/$', 'trans.views.show_subproject'),
url(r'^projects/(?P<project>[^/]*)/(?P<subproject>[^/]*)/(?P<lang>[^/]*)/$', 'trans.views.show_translation'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment