Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplye 210 #22

Merged
merged 21 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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