Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Pootle-2.0.0
diff options
context:
space:
mode:
authorSayamindu Dasgupta <sayamindu@gmail.com>2010-01-08 22:45:07 (GMT)
committer Sayamindu Dasgupta <sayamindu@gmail.com>2010-01-08 22:45:07 (GMT)
commit1790e434a8a1e32132443ad5868598cb3a619c4e (patch)
treee5f2ef6f7e82a721a0c0466532be62368c529451 /Pootle-2.0.0
parent291467c06268c79f4ae7750060f572b6a2ce5f1e (diff)
Add syntax check via libgettextpo
Diffstat (limited to 'Pootle-2.0.0')
-rw-r--r--Pootle-2.0.0/html/style.css13
-rw-r--r--Pootle-2.0.0/local_apps/pootle_app/templates/language/translatepage.html3
-rw-r--r--Pootle-2.0.0/local_apps/pootle_app/views/language/translate_page.py48
-rw-r--r--Pootle-2.0.0/local_apps/pootle_store/fields.py25
4 files changed, 76 insertions, 13 deletions
diff --git a/Pootle-2.0.0/html/style.css b/Pootle-2.0.0/html/style.css
index 7c43572..fda9338 100644
--- a/Pootle-2.0.0/html/style.css
+++ b/Pootle-2.0.0/html/style.css
@@ -478,6 +478,19 @@ html[dir="rtl"] #nav-main ul li
padding: 10px 25px;
}
+#validate-message
+{
+ background-image: url('images/error.png');
+ background-repeat: no-repeat;
+ line-height: 3;
+ background-position: left center;
+ font-weight: bold;
+ background-color: #ffe;
+ border: 1px solid #fc9;
+ margin-bottom: 2em;
+ padding: 10px 25px;
+}
+
#site-message .success
{
color: #3f3;
diff --git a/Pootle-2.0.0/local_apps/pootle_app/templates/language/translatepage.html b/Pootle-2.0.0/local_apps/pootle_app/templates/language/translatepage.html
index 32da92c..3e87385 100644
--- a/Pootle-2.0.0/local_apps/pootle_app/templates/language/translatepage.html
+++ b/Pootle-2.0.0/local_apps/pootle_app/templates/language/translatepage.html
@@ -58,6 +58,9 @@
</ul>
{% endif %}
<div class="translate-form">
+ {% if validationerror %}
+ <div id="validate-message" class="error" dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}">{{ validationerror }}</div>
+ {% endif %}
{% if notice %}
<div id="site-message" dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}">{{ notice }}</div>
{% else %}
diff --git a/Pootle-2.0.0/local_apps/pootle_app/views/language/translate_page.py b/Pootle-2.0.0/local_apps/pootle_app/views/language/translate_page.py
index da4d70d..1168335 100644
--- a/Pootle-2.0.0/local_apps/pootle_app/views/language/translate_page.py
+++ b/Pootle-2.0.0/local_apps/pootle_app/views/language/translate_page.py
@@ -23,6 +23,9 @@
import re
import difflib
import os
+import sys
+
+import gettextpo
from django.conf import settings
from django.core.exceptions import PermissionDenied
@@ -724,6 +727,7 @@ def handle_suggestions(last_item, request, store, submitsuggests, skips, transla
return last_item
def handle_submits(last_item, request, store, submits, skips, translations, comments, fuzzies):
+ validation_error = {}
for item in submits:
if item in skips or item not in translations:
continue
@@ -741,9 +745,14 @@ def handle_submits(last_item, request, store, submits, skips, translations, comm
if translator_comments:
newvalues["translator_comments"] = translator_comments
- unit_update.update_translation(store, item, newvalues, request)
+ try:
+ unit_update.update_translation(store, item, newvalues, request)
+ except gettextpo.error:
+ validation_error = _("Gettext validation error: %s") % (sys.exc_info()[1])
+
last_item = item
- return last_item
+
+ return last_item, validation_error
def process_post(request, store):
@@ -801,33 +810,45 @@ def process_post(request, store):
prev_last_item = handle_backs(-1, backs)
last_item = handle_skips(-1, skips)
last_item = handle_suggestions(last_item, request, store, submitsuggests, skips, translations)
- last_item = handle_submits(last_item, request, store, submits, skips, translations, comments, fuzzies)
- return prev_last_item, last_item
+ last_item, validation_error = handle_submits(last_item, request, store, submits, skips, translations, comments, fuzzies)
+ return prev_last_item, last_item, validation_error
def process_post_main(store_name, item, request, next_store_item, prev_store_item):
store = Store.objects.get(pootle_path=store_name)
request.translation_project.indexer # Force initialization of the indexer
- prev_item, next_item = process_post(request, store)
+ prev_item, next_item, validation_error = process_post(request, store)
+
+ if len(validation_error) > 0:
+ if prev_item > -1:
+ prev_item = prev_item - 1
+ if next_item > -1:
+ next_item = next_item - 1
search = search_forms.search_from_request(request)
if next_item > -1:
- return next_store_item(search, store_name, next_item + 1)
+ ret = next_store_item(search, store_name, next_item + 1)
+ return ret[0], ret[1], validation_error
elif prev_item > -1:
- return prev_store_item(search, store_name, prev_item - 1)
+ ret = prev_store_item(search, store_name, prev_item - 1)
+ return ret[0], ret[1], validation_error
else:
- return store, item
+ return store, item, validation_error
def get_position(request, next_store_item, prev_store_item):
state = dispatch.TranslatePageState(request.GET)
store_name = dispatch.get_store(request)
item = state.item
+ validation_error = {}
if request.method == 'POST':
if 'new_search' in request.POST:
- return next_store_item(search_forms.search_from_request(request), store_name, item)
+ ret = next_store_item(search_forms.search_from_request(request), store_name, item)
+ return ret[0], ret[1], validation_error
else:
return process_post_main(store_name, item, request, next_store_item, prev_store_item)
else:
- return next_store_item(search_forms.search_from_request(request), store_name, item)
+ ret = next_store_item(search_forms.search_from_request(request), store_name, item)
+ return ret[0], ret[1], validation_error
+
def get_failure_message(request):
# We are reviewing a check
@@ -843,12 +864,12 @@ def get_failure_message(request):
def find_and_display(request, directory, next_store_item, prev_store_item):
try:
- store, item = get_position(request, next_store_item, prev_store_item)
- return view(request, directory, store, item)
+ store, item, validation_error = get_position(request, next_store_item, prev_store_item)
+ return view(request, directory, store, item, validation_error = validation_error)
except StopIteration:
return view(request, directory, None, 0, get_failure_message(request))
-def view(request, directory, store, item, stopped_by=None):
+def view(request, directory, store, item, stopped_by=None, validation_error={}):
"""the page which lets people edit translations"""
state = dispatch.TranslatePageState(request.GET)
if not check_permission("view", request):
@@ -900,6 +921,7 @@ def view(request, directory, store, item, stopped_by=None):
# translation form
"actionurl": formaction,
"notice": notice,
+ "validationerror": validation_error,
# l10n: Heading above the table column with the source language
"original_title": _("Original"),
# l10n: Heading above the table column with the target language
diff --git a/Pootle-2.0.0/local_apps/pootle_store/fields.py b/Pootle-2.0.0/local_apps/pootle_store/fields.py
index 76ab93d..91a6a8b 100644
--- a/Pootle-2.0.0/local_apps/pootle_store/fields.py
+++ b/Pootle-2.0.0/local_apps/pootle_store/fields.py
@@ -26,6 +26,8 @@ import os
import shutil
import tempfile
+import gettextpo
+
from django.conf import settings
from django.core.files import File
from django.db.models.fields.files import FieldFile, FileField
@@ -40,6 +42,27 @@ from pootle.__version__ import sver as pootle_version
x_generator = "Pootle %s" % pootle_version
+
+def validate_gettext_translation(unit):
+ '''
+ Uses libgettextpo to validate translation.
+ Raises exception if validation fails
+ '''
+ #TODO: Add plural support
+ if not isinstance(unit, po.pounit):
+ # We can only handle po files
+ return
+
+ pomessage = gettextpo.PoMessage()
+ pomessage.set_msgid(unit.msgid[0])
+ pomessage.set_msgstr(unit.msgstr[0])
+
+ for tc in ['python-format', 'c-format', 'php-format']:
+ if unit.hastypecomment(tc):
+ pomessage.set_format(tc, True)
+
+ pomessage.check_format()
+
class StatsTuple(object):
"""Encapsulates stats in the in memory cache, needed
since LRUCachingDict is based on a weakref.WeakValueDictionary
@@ -171,6 +194,8 @@ class TranslationStoreFile(File):
unit.target = newvalues['target'][0]
else:
unit.target = newvalues['target']
+ if not unit.hasplural():
+ validate_gettext_translation(unit)
if newvalues.has_key('fuzzy'):
unit.markfuzzy(newvalues['fuzzy'])
if newvalues.has_key('translator_comments'):