Skip to content

Commit

Permalink
Merge pull request #22 from NatLibFi/SIMPLYE-210
Browse files Browse the repository at this point in the history
Simplye 210
  • Loading branch information
jompu authored Mar 14, 2024
2 parents 9bb2479 + 6fe2e37 commit 9823333
Show file tree
Hide file tree
Showing 31 changed files with 18,813 additions and 139 deletions.
7 changes: 6 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,9 @@ repos:
- scan

# Exclude test files, since they may be intentionally malformed
exclude: ^tests/(core|api)/files/
# Exclude transaltions, since they are generated.
exclude: >
(?x)(
^tests/(core|api)/files/|
^translations/
)
26 changes: 26 additions & 0 deletions .tx/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[main]
host = https://app.transifex.com

[o:national-library-of-finland:p:ekirjasto-circulation-admin:r:circulationadminpo]
file_filter = translations/<lang>/LC_MESSAGES/circulation-admin.po
source_file = translations/en/LC_MESSAGES/circulation-admin.po
type = PO
minimum_perc = 0
replace_edited_strings = false
keep_translations = false

[o:national-library-of-finland:p:ekirjasto-circulation:r:circulationpo]
file_filter = translations/<lang>/LC_MESSAGES/circulation.po
source_file = translations/en/LC_MESSAGES/circulation.po
type = PO
minimum_perc = 0
replace_edited_strings = false
keep_translations = false

[o:national-library-of-finland:p:ekirjasto-circulation:r:corepo]
file_filter = translations/<lang>/LC_MESSAGES/core.po
source_file = translations/en/LC_MESSAGES/core.po
type = PO
minimum_perc = 0
replace_edited_strings = false
keep_translations = false
15 changes: 9 additions & 6 deletions api/circulation_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import flask
from dependency_injector.wiring import Provide, inject
from expiringdict import ExpiringDict
from flask_babel import gettext
from flask_babel import lazy_gettext as _
from sqlalchemy import select

Expand Down Expand Up @@ -257,11 +258,13 @@ def get_domain(url):

self.patron_web_domains = patron_web_domains
self.setup_configuration_dependent_controllers()
authentication_document_cache_time = int(
ConfigurationSetting.sitewide(
self._db, Configuration.AUTHENTICATION_DOCUMENT_CACHE_TIME
).value_or_default(3600)
)
# Finland: Disabled cache, because the E-kirjasto authentication provider
# will have links containing a query parameter for user's locale.
authentication_document_cache_time = 0 # int(
# ConfigurationSetting.sitewide(
# self._db, Configuration.AUTHENTICATION_DOCUMENT_CACHE_TIME
# ).value_or_default(3600)
# )
self.authentication_for_opds_documents = ExpiringDict(
max_len=1000, max_age_seconds=authentication_document_cache_time
)
Expand Down Expand Up @@ -372,7 +375,7 @@ def annotator(self, lane, facets=None, *args, **kwargs):
self.circulation_apis[library.id],
lane,
library,
top_level_title="All Books",
top_level_title=gettext("All Books"),
library_identifies_patrons=library_identifies_patrons,
facets=facets,
*args,
Expand Down
3 changes: 2 additions & 1 deletion api/ekirjasto_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from enum import Enum
from typing import Any

import flask_babel
import jwt
import requests
from cryptography.fernet import Fernet, InvalidToken
Expand Down Expand Up @@ -193,7 +194,7 @@ def _authentication_flow_document(self, _db: Session) -> dict[str, Any]:
{"rel": "api", "href": self._ekirjasto_api_url},
{
"rel": "tunnistus_start",
"href": f"{self._ekirjasto_api_url}/v1/auth/tunnistus/start?locale=fi",
"href": f"{self._ekirjasto_api_url}/v1/auth/tunnistus/start?locale={flask_babel.get_locale()}",
},
{
"rel": "tunnistus_finish",
Expand Down
7 changes: 7 additions & 0 deletions api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from functools import update_wrapper, wraps

import flask
import flask_babel
from flask import Response, make_response, request
from flask_cors.core import get_cors_options, set_cors_headers
from flask_pydantic_spec import Response as SpecResponse
Expand All @@ -23,6 +24,12 @@ def print_cache(response):
return response


@app.after_request
def set_content_language_header(response):
response.headers["Content-Language"] = flask_babel.get_locale()
return response


@app.teardown_request
def shutdown_session(exception):
if hasattr(app, "manager") and hasattr(app.manager, "_db") and app.manager._db:
Expand Down
12 changes: 12 additions & 0 deletions bin/util/collect_translations
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python
"""Collect translations."""

import os
import sys

bin_dir = os.path.split(__file__)[0]
package_dir = os.path.join(bin_dir, "..", "..")
sys.path.append(os.path.abspath(package_dir))
from scripts import CollectTranslationsScript

CollectTranslationsScript().run()
1 change: 1 addition & 0 deletions bin/util/core.babel.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[python: core/*.py]
[python: core/classifier/*.py]
[python: core/util/*.py]
147 changes: 147 additions & 0 deletions core/classifier/localized_names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from flask_babel import lazy_gettext as _

# DO NOT EDIT THIS FILE MANUALLY!
# This file was generated by the CollectTranslationsScript class.

genres = {
"Adventure": _("Adventure"),
"Classics": _("Classics"),
"Comics & Graphic Novels": _("Comics & Graphic Novels"),
"Drama": _("Drama"),
"Erotica": _("Erotica"),
"Fantasy": _("Fantasy"),
"Epic Fantasy": _("Epic Fantasy"),
"Historical Fantasy": _("Historical Fantasy"),
"Urban Fantasy": _("Urban Fantasy"),
"Folklore": _("Folklore"),
"Historical Fiction": _("Historical Fiction"),
"Horror": _("Horror"),
"Gothic Horror": _("Gothic Horror"),
"Ghost Stories": _("Ghost Stories"),
"Vampires": _("Vampires"),
"Werewolves": _("Werewolves"),
"Occult Horror": _("Occult Horror"),
"Humorous Fiction": _("Humorous Fiction"),
"Literary Fiction": _("Literary Fiction"),
"LGBTQ Fiction": _("LGBTQ Fiction"),
"Mystery": _("Mystery"),
"Crime & Detective Stories": _("Crime & Detective Stories"),
"Hard-Boiled Mystery": _("Hard-Boiled Mystery"),
"Police Procedural": _("Police Procedural"),
"Cozy Mystery": _("Cozy Mystery"),
"Historical Mystery": _("Historical Mystery"),
"Paranormal Mystery": _("Paranormal Mystery"),
"Women Detectives": _("Women Detectives"),
"Poetry": _("Poetry"),
"Religious Fiction": _("Religious Fiction"),
"Romance": _("Romance"),
"Contemporary Romance": _("Contemporary Romance"),
"Gothic Romance": _("Gothic Romance"),
"Historical Romance": _("Historical Romance"),
"Paranormal Romance": _("Paranormal Romance"),
"Western Romance": _("Western Romance"),
"Romantic Suspense": _("Romantic Suspense"),
"Science Fiction": _("Science Fiction"),
"Dystopian SF": _("Dystopian SF"),
"Space Opera": _("Space Opera"),
"Cyberpunk": _("Cyberpunk"),
"Military SF": _("Military SF"),
"Alternative History": _("Alternative History"),
"Steampunk": _("Steampunk"),
"Romantic SF": _("Romantic SF"),
"Media Tie-in SF": _("Media Tie-in SF"),
"Short Stories": _("Short Stories"),
"Suspense/Thriller": _("Suspense/Thriller"),
"Historical Thriller": _("Historical Thriller"),
"Espionage": _("Espionage"),
"Supernatural Thriller": _("Supernatural Thriller"),
"Medical Thriller": _("Medical Thriller"),
"Political Thriller": _("Political Thriller"),
"Psychological Thriller": _("Psychological Thriller"),
"Technothriller": _("Technothriller"),
"Legal Thriller": _("Legal Thriller"),
"Military Thriller": _("Military Thriller"),
"Urban Fiction": _("Urban Fiction"),
"Westerns": _("Westerns"),
"Women's Fiction": _("Women's Fiction"),
"Art & Design": _("Art & Design"),
"Architecture": _("Architecture"),
"Art": _("Art"),
"Art Criticism & Theory": _("Art Criticism & Theory"),
"Art History": _("Art History"),
"Design": _("Design"),
"Fashion": _("Fashion"),
"Photography": _("Photography"),
"Biography & Memoir": _("Biography & Memoir"),
"Education": _("Education"),
"Personal Finance & Business": _("Personal Finance & Business"),
"Business": _("Business"),
"Economics": _("Economics"),
"Management & Leadership": _("Management & Leadership"),
"Personal Finance & Investing": _("Personal Finance & Investing"),
"Real Estate": _("Real Estate"),
"Parenting & Family": _("Parenting & Family"),
"Family & Relationships": _("Family & Relationships"),
"Parenting": _("Parenting"),
"Food & Health": _("Food & Health"),
"Bartending & Cocktails": _("Bartending & Cocktails"),
"Cooking": _("Cooking"),
"Health & Diet": _("Health & Diet"),
"Vegetarian & Vegan": _("Vegetarian & Vegan"),
"History": _("History"),
"African History": _("African History"),
"Ancient History": _("Ancient History"),
"Asian History": _("Asian History"),
"Civil War History": _("Civil War History"),
"European History": _("European History"),
"Latin American History": _("Latin American History"),
"Medieval History": _("Medieval History"),
"Middle East History": _("Middle East History"),
"Military History": _("Military History"),
"Modern History": _("Modern History"),
"Renaissance & Early Modern History": _("Renaissance & Early Modern History"),
"United States History": _("United States History"),
"World History": _("World History"),
"Hobbies & Home": _("Hobbies & Home"),
"Antiques & Collectibles": _("Antiques & Collectibles"),
"Crafts & Hobbies": _("Crafts & Hobbies"),
"Gardening": _("Gardening"),
"Games": _("Games"),
"House & Home": _("House & Home"),
"Pets": _("Pets"),
"Humorous Nonfiction": _("Humorous Nonfiction"),
"Entertainment": _("Entertainment"),
"Film & TV": _("Film & TV"),
"Music": _("Music"),
"Performing Arts": _("Performing Arts"),
"Life Strategies": _("Life Strategies"),
"Literary Criticism": _("Literary Criticism"),
"Periodicals": _("Periodicals"),
"Philosophy": _("Philosophy"),
"Political Science": _("Political Science"),
"Reference & Study Aids": _("Reference & Study Aids"),
"Dictionaries": _("Dictionaries"),
"Foreign Language Study": _("Foreign Language Study"),
"Law": _("Law"),
"Study Aids": _("Study Aids"),
"Religion & Spirituality": _("Religion & Spirituality"),
"Body, Mind & Spirit": _("Body, Mind & Spirit"),
"Buddhism": _("Buddhism"),
"Christianity": _("Christianity"),
"Hinduism": _("Hinduism"),
"Islam": _("Islam"),
"Judaism": _("Judaism"),
"Science & Technology": _("Science & Technology"),
"Computers": _("Computers"),
"Mathematics": _("Mathematics"),
"Medical": _("Medical"),
"Nature": _("Nature"),
"Psychology": _("Psychology"),
"Science": _("Science"),
"Social Sciences": _("Social Sciences"),
"Technology": _("Technology"),
"Self-Help": _("Self-Help"),
"Sports": _("Sports"),
"Travel": _("Travel"),
"True Crime": _("True Crime"),
}
2 changes: 1 addition & 1 deletion core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def quicksight_authorized_arns(cls) -> dict[str, list[str]]:

@classmethod
def localization_languages(cls):
return [LanguageCodes.three_to_two["eng"]]
return [LanguageCodes.three_to_two["eng"], "fi", "sv"]

# The last time the database configuration is known to have changed.
SITE_CONFIGURATION_LAST_UPDATE = None
Expand Down
4 changes: 3 additions & 1 deletion core/configuration/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ class LibrarySettings(BaseSettings):
"audiobook vendors: Bibliotheca, Axis 360",
type=ConfigurationFormItemType.MENU,
options={
entrypoint.INTERNAL_NAME: EntryPoint.DISPLAY_TITLES[entrypoint]
entrypoint.INTERNAL_NAME: str(
EntryPoint.LOCALIZED_DISPLAY_TITLES[entrypoint]
)
for entrypoint in EntryPoint.ENTRY_POINTS
},
category="Lanes & Filters",
Expand Down
12 changes: 12 additions & 0 deletions core/entrypoint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from __future__ import annotations

from flask_babel import LazyString
from flask_babel import lazy_gettext as _


class EntryPoint:

Expand All @@ -23,6 +26,7 @@ class by calling EntryPoint.register.
ENTRY_POINTS: list[type[EntryPoint]] = []
DEFAULT_ENABLED: list[type[EntryPoint]] = []
DISPLAY_TITLES: dict[type[EntryPoint], str] = {}
LOCALIZED_DISPLAY_TITLES: dict[type[EntryPoint], LazyString] = {}
BY_INTERNAL_NAME: dict[str, type[EntryPoint]] = {}

# A distinctive URI designating the sort of thing found through this
Expand All @@ -42,6 +46,9 @@ def register(cls, entrypoint_class, display_title, default_enabled=False):
enabled by default.
"""
value = getattr(entrypoint_class, "INTERNAL_NAME", None)
localized_display_title = getattr(
entrypoint_class, "LOCALIZED_DISPLAY_TITLE", None
)
if not value:
raise ValueError(
"EntryPoint class %s must define INTERNAL_NAME."
Expand All @@ -57,6 +64,7 @@ def register(cls, entrypoint_class, display_title, default_enabled=False):
if default_enabled:
cls.DEFAULT_ENABLED.append(entrypoint_class)
cls.DISPLAY_TITLES[entrypoint_class] = display_title
cls.LOCALIZED_DISPLAY_TITLES[entrypoint_class] = localized_display_title

@classmethod
def unregister(cls, entrypoint_class):
Expand All @@ -67,6 +75,7 @@ def unregister(cls, entrypoint_class):
cls.ENTRY_POINTS.remove(entrypoint_class)
del cls.BY_INTERNAL_NAME[entrypoint_class.INTERNAL_NAME]
del cls.DISPLAY_TITLES[entrypoint_class]
del cls.LOCALIZED_DISPLAY_TITLES[entrypoint_class]
if entrypoint_class in cls.DEFAULT_ENABLED:
cls.DEFAULT_ENABLED.remove(entrypoint_class)

Expand Down Expand Up @@ -95,6 +104,7 @@ class EverythingEntryPoint(EntryPoint):
"""An entry point that has everything."""

INTERNAL_NAME = "All"
LOCALIZED_DISPLAY_TITLE = _("All")
URI = "http://schema.org/CreativeWork"


Expand Down Expand Up @@ -131,6 +141,7 @@ def modify_search_filter(cls, filter):

class EbooksEntryPoint(MediumEntryPoint):
INTERNAL_NAME = "Book"
LOCALIZED_DISPLAY_TITLE = _("eBooks")
URI = "http://schema.org/EBook"


Expand All @@ -139,6 +150,7 @@ class EbooksEntryPoint(MediumEntryPoint):

class AudiobooksEntryPoint(MediumEntryPoint):
INTERNAL_NAME = "Audio"
LOCALIZED_DISPLAY_TITLE = _("Audiobooks")
URI = "http://bib.schema.org/Audiobook"


Expand Down
3 changes: 2 additions & 1 deletion core/feed/acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,11 @@ def _entrypoint_link(
"""Create arguments for add_link_to_feed for a link that navigates
between EntryPoints.
"""
display_title = EntryPoint.DISPLAY_TITLES.get(entrypoint)
display_title = EntryPoint.LOCALIZED_DISPLAY_TITLES.get(entrypoint)
if not display_title:
# Shouldn't happen.
return None
display_title = str(display_title)

url = url_generator(entrypoint)
is_selected = entrypoint is selected_entrypoint
Expand Down
3 changes: 2 additions & 1 deletion core/feed/annotator/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Any
from urllib.parse import quote

from flask_babel import gettext
from sqlalchemy.orm import Session, joinedload

from core.classifier import Classifier
Expand Down Expand Up @@ -180,7 +181,7 @@ def categories(cls, work: Work) -> dict[str, list[dict[str, str]]]:

if simplified_genres:
categories[Subject.SIMPLIFIED_GENRE] = [
dict(term=Subject.SIMPLIFIED_GENRE + quote(x), label=x)
dict(term=Subject.SIMPLIFIED_GENRE + quote(x), label=gettext(x))
for x in simplified_genres
]

Expand Down
Loading

0 comments on commit 9823333

Please sign in to comment.