Skip to content

Commit

Permalink
[#1808] Handle fallback language in dataset view translations
Browse files Browse the repository at this point in the history
term_translation_show() logic action function now accepts a list of lang codes
instead of just one lang code.

MultilingualDataset.before_view() looks for translations in the fallback
language if they are not found in the desired language.

test_multilingual_plugin.py: Add some fallback language stuff into the test.
  • Loading branch information
Sean Hammond committed Feb 23, 2012
1 parent c6b4192 commit 5cb3bcb
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
4 changes: 2 additions & 2 deletions ckan/logic/action/get.py
Expand Up @@ -891,8 +891,8 @@ def term_translation_show(context, data_dict):

q = q.where(trans_table.c.term.in_(data_dict['terms']))

if 'lang_code' in data_dict:
q = q.where(trans_table.c.lang_code == data_dict['lang_code'])
if 'lang_codes' in data_dict:
q = q.where(trans_table.c.lang_code.in_(data_dict['lang_codes']))

conn = model.Session.connection()
cursor = conn.execute(q)
Expand Down
30 changes: 23 additions & 7 deletions ckanext/multilingual/plugin.py
Expand Up @@ -14,7 +14,8 @@ def before_search(self, search_params):
# FIXME: Look for translation in fallback language when none found in
# desired language.
def before_view(self, data_dict):
lang_code = pylons.request.environ['CKAN_LANG']
desired_lang_code = pylons.request.environ['CKAN_LANG']
fallback_lang_code = pylons.config.get('ckan.locale_default', 'en')

# Get a flattened copy of data_dict to do the translation on.
flattened = ckan.lib.navl.dictization_functions.flatten_dict(
Expand All @@ -36,13 +37,20 @@ def before_view(self, data_dict):
# Get the translations of all the terms (as a list of dictionaries).
translations = ckan.logic.action.get.term_translation_show(
{'model': ckan.model},
{'terms': terms, 'lang_code': lang_code})
{'terms': terms,
'lang_codes': (desired_lang_code, fallback_lang_code)})

# Transform the translations into a more convenient structure.
translations_dict = {}
desired_translations = {}
fallback_translations = {}
for translation in translations:
translations_dict[translation['term']] = (
translation['term_translation'])
if translation['lang_code'] == desired_lang_code:
desired_translations[translation['term']] = (
translation['term_translation'])
else:
assert translation['lang_code'] == fallback_lang_code
fallback_translations[translation['term']] = (
translation['term_translation'])

# Make a copy of the flattened data dict with all the terms replaced by
# their translations, where available.
Expand All @@ -51,11 +59,19 @@ def before_view(self, data_dict):
if value in (None, True, False):
translated_flattened[key] = value
elif isinstance(value, basestring):
translated_flattened[key] = translations_dict.get(value, value)
if desired_translations.has_key(value):
translated_flattened[key] = desired_translations[value]
else:
translated_flattened[key] = fallback_translations.get(
value, value)
else:
translated_value = []
for item in value:
translated_value.append(translations_dict.get(item, item))
if desired_translations.has_key(value):
translated_flattened[key] = desired_translations[value]
else:
translated_flattened[key] = fallback_translations.get(
value, value)
translated_flattened[key] = translated_value

# Finally unflatten and return the translated data dict.
Expand Down
47 changes: 45 additions & 2 deletions ckanext/multilingual/tests/test_multilingual_plugin.py
@@ -1,17 +1,20 @@
import ckan.plugins
import ckan.lib.helpers
import ckan.logic.action.update
import ckan.tests.html_check
import routes
import paste.fixture
import pylons.test


class TestDatasetTermTranslation(ckan.tests.html_check.HtmlCheckMethods):
'''Test the translation of datasets by the multilingual_dataset plugin.
'''
@classmethod
def setup(cls):
ckan.tests.CreateTestData.create()
cls.normal_user = ckan.model.User.get('annafan')
cls.sysadmin_user = ckan.model.User.get('testsysadmin')
cls.app = paste.fixture.TestApp(pylons.test.pylonsapp)
ckan.plugins.load('multilingual_dataset')
Expand All @@ -25,6 +28,31 @@ def test_dataset_view_translation(self):
multilingual_dataset plugin.
'''
# Get a package.
context = {
'model': ckan.model,
'session': ckan.model.Session,
'user': self.normal_user.name,
'allow_partial_update': True
}
package = ckan.logic.action.get.package_show(context,
{'id': "annakarenina"})

# Add some new tags to the package.
# These tags are codes that are meant to be always translated before
# display, if not into the user's current language then into the
# fallback language.
new_tag_list = package['tags'] + [
{'name': '123'},
{'name': '456'},
{'name': '789'},
]
data_dict = {
'id': package['id'],
'tags': new_tag_list
}
package = ckan.logic.action.update.package_update(context, data_dict)

# Test translations for some of the package's fields.
terms = ('A Novel By Tolstoy',
'Index of the novel',
Expand All @@ -34,7 +62,16 @@ def test_dataset_view_translation(self):
"Roger's books",
'Other (Open)',
'romantic novel',
'book',)
'book',
'123',
'456',
'789',
)
english_translations = {
'123': 'jealousy',
'456': 'realism',
'789': 'hypocrisy',
}
german_translations = {
'A Novel By Tolstoy': 'Roman von Tolstoi',
'Index of the novel': 'Index des Romans',
Expand All @@ -45,19 +82,23 @@ def test_dataset_view_translation(self):
'Other (Open)': 'Andere (Open)',
'romantic novel': 'Liebesroman',
'book': 'Buch',
'456': 'Realismus',
'789': 'Heuchelei',
}
french_translations = {
'A Novel By Tolstoy': 'A Novel par Tolstoi',
'Index of the novel': 'Indice du roman',
'russian': 'russe',
'romantic novel': 'roman romantique',
'book': 'livre',
'123': 'jalousie',
'789': 'hypocrisie',
}

# Use the term_translation_update API to add the above translations to
# CKAN.
for (lang_code, translations) in (('de', german_translations),
('fr', french_translations)):
('fr', french_translations), ('en', english_translations)):
for term in terms:
if term in translations:
paramd = {
Expand Down Expand Up @@ -86,5 +127,7 @@ def test_dataset_view_translation(self):
for term in terms:
if term in translations:
response.mustcontain(translations[term])
elif term in english_translations:
response.mustcontain(english_translations[term])
else:
response.mustcontain(term)

0 comments on commit 5cb3bcb

Please sign in to comment.