From: Radek Czajka Date: Tue, 19 Nov 2013 12:09:12 +0000 (+0100) Subject: Allow books with internationalized metadata. X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/c7c0b88f1f628f0498c8c53c76a061ec128a228a?ds=sidebyside Allow books with internationalized metadata. --- diff --git a/apps/catalogue/constants.py b/apps/catalogue/constants.py index bfad4b075..36f4f5dd3 100644 --- a/apps/catalogue/constants.py +++ b/apps/catalogue/constants.py @@ -21,3 +21,18 @@ EBOOK_FORMATS_WITH_CHILDREN = ['pdf', 'epub', 'mobi'] EBOOK_FORMATS_WITH_COVERS = ['pdf', 'epub', 'mobi'] EBOOK_FORMATS = EBOOK_FORMATS_WITHOUT_CHILDREN + EBOOK_FORMATS_WITH_CHILDREN + +LANGUAGES_3TO2 = { + 'deu': 'de', + 'ger': 'de', + 'eng': 'en', + 'spa': 'es', + 'fra': 'fr', + 'fre': 'fr', + 'ita': 'it', + 'jpn': 'jp', + 'lit': 'lt', + 'pol': 'pl', + 'rus': 'ru', + 'ukr': 'uk', +} diff --git a/apps/catalogue/fields.py b/apps/catalogue/fields.py index bb9f26efe..e2978e877 100644 --- a/apps/catalogue/fields.py +++ b/apps/catalogue/fields.py @@ -7,6 +7,7 @@ from django.core.files import File from django.db import models from django.db.models.fields.files import FieldFile from catalogue import app_settings +from catalogue.constants import LANGUAGES_3TO2 from catalogue.utils import remove_zip, truncate_html_words from celery.task import Task, task from waiter.utils import clear_cache @@ -140,6 +141,11 @@ class BuildHtml(BuildEbook): html_output = self.transform( book.wldocument(parse_dublincore=False), fieldfile) + lang = book.language + lang = LANGUAGES_3TO2.get(lang, lang) + if lang not in [ln[0] for ln in settings.LANGUAGES]: + lang = None + if html_output: fieldfile.save(None, ContentFile(html_output.get_string()), save=False) @@ -167,14 +173,26 @@ class BuildHtml(BuildEbook): for theme_name in theme_names: if not theme_name: continue - tag, created = Tag.objects.get_or_create( - slug=slughifi(theme_name), - category='theme') - if created: - tag.name = theme_name - tag.sort_key = sortify(theme_name.lower()) - tag.save() - themes.append(tag) + if lang == settings.LANGUAGE_CODE: + # Allow creating themes if book in default language. + tag, created = Tag.objects.get_or_create( + slug=slughifi(theme_name), + category='theme') + if created: + tag.name = theme_name + setattr(tag, "name_%s" % lang, theme_name) + tag.sort_key = sortify(theme_name.lower()) + tag.save() + themes.append(tag) + elif lang is not None: + # Don't create unknown themes in non-default languages. + try: + tag = Tag.objects.get(category='theme', + **{"name_%s" % lang: theme_name}) + except Tag.DoesNotExist: + pass + else: + themes.append(tag) if not themes: continue diff --git a/apps/catalogue/models/book.py b/apps/catalogue/models/book.py index 0438afa21..c865d1d87 100644 --- a/apps/catalogue/models/book.py +++ b/apps/catalogue/models/book.py @@ -495,7 +495,7 @@ class Book(models.Model): book = self rel_info = book.related_info() names = [(related_tag_name(tag), Tag.create_url('author', tag['slug'])) - for tag in rel_info['tags']['author']] + for tag in rel_info['tags'].get('author', ())] if 'parents' in rel_info: books = [(name, Book.create_url(slug)) for name, slug in rel_info['parents']] diff --git a/apps/catalogue/models/tag.py b/apps/catalogue/models/tag.py index b0c75fbb4..1309cbbd2 100644 --- a/apps/catalogue/models/tag.py +++ b/apps/catalogue/models/tag.py @@ -2,6 +2,7 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +from django.conf import settings from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db import models @@ -166,14 +167,26 @@ class Tag(TagBase): # For instance, Pictures do not have 'genre' field. continue for tag_name in tag_names: + lang = getattr(tag_name, 'lang', settings.LANGUAGE_CODE) tag_sort_key = tag_name if category == 'author': tag_sort_key = tag_name.last_name tag_name = tag_name.readable() - tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category) - if created: - tag.name = tag_name - tag.sort_key = sortify(tag_sort_key.lower()) - tag.save() - meta_tags.append(tag) + if lang == settings.LANGUAGE_CODE: + # Allow creating new tag, if it's in default language. + tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category) + if created: + tag.name = tag_name + setattr(tag, "name_%s" % lang, tag_name) + tag.sort_key = sortify(tag_sort_key.lower()) + tag.save() + meta_tags.append(tag) + else: + # Ignore unknown tags in non-default languages. + try: + tag = Tag.objects.get(category=category, **{"name_%s" % lang: tag_name}) + except Tag.DoesNotExist: + pass + else: + meta_tags.append(tag) return meta_tags diff --git a/apps/catalogue/templatetags/catalogue_tags.py b/apps/catalogue/templatetags/catalogue_tags.py index 8c073c137..d6a795fb4 100644 --- a/apps/catalogue/templatetags/catalogue_tags.py +++ b/apps/catalogue/templatetags/catalogue_tags.py @@ -351,7 +351,7 @@ def book_short(context, book): @register.inclusion_tag('catalogue/book_mini_box.html') def book_mini(book): author_str = ", ".join(related_tag_name(tag) - for tag in book.related_info()['tags']['author']) + for tag in book.related_info()['tags'].get('author', ())) return { 'book': book, 'author_str': author_str, diff --git a/apps/catalogue/tests/tags.py b/apps/catalogue/tests/tags.py index 17f9a7782..99edebbe7 100644 --- a/apps/catalogue/tests/tags.py +++ b/apps/catalogue/tests/tags.py @@ -271,9 +271,9 @@ class BookTagsTests(WLTestCase): related_themes = book.related_themes() self.assertEqual(related_info['tags']['author'], - [{'pl': 'Common Man', 'slug': 'common-man'}]) + [{'name_pl': 'Common Man', 'slug': 'common-man'}]) self.assertEqual(related_info['tags']['kind'], - [{'pl': 'Kind', 'slug': 'kind'}]) + [{'name_pl': 'Kind', 'slug': 'kind'}]) self.assertEqual([(tag.name, tag.count) for tag in related_themes], [('ChildTheme', 1), ('ParentTheme', 1), ('Theme', 2)]) diff --git a/apps/catalogue/utils.py b/apps/catalogue/utils.py index b023f1a2f..edc287f98 100644 --- a/apps/catalogue/utils.py +++ b/apps/catalogue/utils.py @@ -317,7 +317,7 @@ This can sometimes occupy lots of memory, so trim it here a bit. def related_tag_name(tag_info, language=None): return tag_info.get("name_%s" % (language or get_language()), - tag_info.get("name_%s" % settings.LANGUAGE_CODE)) + tag_info.get("name_%s" % settings.LANGUAGE_CODE, "")) def delete_from_cache_by_language(cache, key_template): diff --git a/apps/funding/static/funding/funding.css b/apps/funding/static/funding/funding.css index 89dd7aa79..a3e6546c0 100755 --- a/apps/funding/static/funding/funding.css +++ b/apps/funding/static/funding/funding.css @@ -1 +1 @@ -.funding,.funding-top-header{background:orange;margin:auto;padding:5px 0;position:relative}.funding a.call,.funding-top-header a.call{height:1.2em;width:9em;padding:.35em .5em;margin:.5em;display:inline-block;vertical-align:top;text-align:center;background:rgb(.465%, 59.936%, 63.653%)}.funding .description,.funding-top-header .description{display:inline-block;padding-left:.6em}.funding .description a,.funding-top-header .description a{display:block;color:#000;padding:0 3px}.funding strong,.funding-top-header strong{font-size:1.5em;padding:.2em 0 0}.funding .progress,.funding-top-header .progress{width:95.7em;margin:.3em 0 .4em;border-radius:2em;background-image:url(/static/img/progress-pixel.png);background-repeat:repeat-y;background-color:#f68900;box-shadow:.1em .1em .1em #888}.funding .progress .piece,.funding-top-header .progress .piece{font-size:1.3em;padding:.3em .5em}.funding .with-button .progress,.funding-top-header .with-button .progress{width:78em}.funding .funding .funding-title-strong,.funding .funding-title,.funding-top-header .funding-title,.funding-top-header .funding-top-header .funding-title-strong{font-size:1.1em}.funding .funding-title-strong,.funding-top-header .funding-title-strong{font-weight:bold;font-size:1.5em}.funding .close,.funding-top-header .close{position:absolute;top:0;right:5px}.funding-top-header{width:97.5em}.wlfund{width:100%;border-spacing:0}.wlfund td{padding:1em .5em 1em;text-align:center;border-top:1em solid rgba(255, 255, 255, 0);border-bottom:2px solid #DDD;background-clip:padding-box;-moz-background-clip:padding;-webkit-background-clip:padding}.wlfund td.oneline{white-space:nowrap}.wlfund td:last-child{text-align:right}.wlfund .funding-plus td{background-color:#cfe5e7}.wlfund .funding-minus td{background-color:#fff}.honking{background:#018189;font-size:1.5em;padding:.5em;color:#fff;border:0;box-shadow:.2em .2em .3em #888;position:relative}.honking:hover{box-shadow:none;top:.1em;left:.1em}.share a{margin-right:1.5em}.share a img{vertical-align:middle}.funding-handle{position:absolute;top:0;right:0;z-index:2;background:orange;cursor:pointer;padding:.2em 1em;border-radius:0 0 0 1em;font-size:13px}.funding-cover{float:left;margin-right:10px}.funding-details-intro{padding-top:1em}.funding-details-intro h3:first-of-type{margin-top:0} \ No newline at end of file +.funding,.funding-top-header{background:orange;margin:auto;padding:5px 0;position:relative}.funding a.call,.funding-top-header a.call{height:1.2em;width:9em;padding:.35em .5em;margin:.5em;display:inline-block;vertical-align:top;text-align:center;background:#018189}.funding .description,.funding-top-header .description{display:inline-block;padding-left:.6em}.funding .description a,.funding-top-header .description a{display:block;color:#000;padding:0 3px}.funding strong,.funding-top-header strong{font-size:1.5em;padding:.2em 0 0}.funding .progress,.funding-top-header .progress{width:95.7em;margin:.3em 0 .4em;border-radius:2em;background-image:url(/static/img/progress-pixel.png);background-repeat:repeat-y;background-color:#f68900;box-shadow:.1em .1em .1em #888}.funding .progress .piece,.funding-top-header .progress .piece{font-size:1.3em;padding:.3em .5em}.funding .with-button .progress,.funding-top-header .with-button .progress{width:78em}.funding .funding-title,.funding .funding-title-strong,.funding-top-header .funding-title,.funding-top-header .funding-title-strong{font-size:1.1em}.funding .funding-title-strong,.funding-top-header .funding-title-strong{font-weight:bold;font-size:1.5em}.funding .close,.funding-top-header .close{position:absolute;top:0;right:5px}.funding-top-header{width:97.5em}.wlfund{width:100%;border-spacing:0}.wlfund td{padding:1em .5em 1em;text-align:center;border-top:1em solid rgba(255,255,255,0);border-bottom:2px solid #ddd;background-clip:padding-box;-moz-background-clip:padding;-webkit-background-clip:padding}.wlfund td.oneline{white-space:nowrap}.wlfund td:last-child{text-align:right}.wlfund .funding-plus td{background-color:#cfe5e7}.wlfund .funding-minus td{background-color:#fff}.honking{background:#018189;font-size:1.5em;padding:.5em;color:#fff;border:0;box-shadow:.2em .2em .3em #888;position:relative}.honking:hover{box-shadow:none;top:.1em;left:.1em}.share a{margin-right:1.5em}.share a img{vertical-align:middle}.funding-handle{position:absolute;top:0;right:0;z-index:2;background:orange;cursor:pointer;padding:.2em 1em;border-radius:0 0 0 1em;font-size:13px}.funding-cover{float:left;margin-right:10px}.funding-details-intro{padding-top:1em}.funding-details-intro h3:first-of-type{margin-top:0} \ No newline at end of file diff --git a/lib/librarian b/lib/librarian index a7d898e7b..6b327e1a3 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit a7d898e7b37b773ec111aa395f9591d61b7a1d46 +Subproject commit 6b327e1a303fa8512cd5c56684bab2869198c01e diff --git a/requirements.txt b/requirements.txt index cd319e24e..3ed01b3dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ # django Django>=1.5,<1.6 -fnpdjango>=0.1.6,<0.2 +fnpdjango>=0.1.8,<0.2 South>=0.7 # migrations for django django-pipeline>=1.2.24,<1.3 django-pagination>=1.0