"""Alphabetical order in the reader's language (E30 S3). Why not the database default: the Postgres image is Alpine, and musl's `en_US.utf8` collation is BYTE order — every accented initial sorted after "Z" ("Zorró < Életrajzi < Ötödik"), in every A→Z list the server orders. Postgres ships the ICU collations on the same image (dev, test, prod alike), so a text sort names one: Hungarian puts "Ö" after "O" and "Cs" after "Cu", English folds the accents in. `collated` wraps an ORDER BY expression — and because a keyset cursor compares with the SAME expression (`feedquery.sort_keys`), the cursor pages in the same order it sorted in. `sorted_words` orders a Python list the same way through the database, so a list built in Python matches one built in SQL exactly.""" from typing import Any from sqlalchemy import SQLColumnExpression, column, func, select, values from sqlalchemy.orm import Session from sqlalchemy.sql.elements import ColumnElement from sqlalchemy.types import String from app.mailtext import normalize ICU: dict[str, str] = {"en": "en-x-icu", "hu": "hu-x-icu"} def collation(lang: str | None) -> str: """The ICU collation for a UI language; anything unknown sorts as English.""" return ICU[normalize(lang)] def collated(expr: SQLColumnExpression[Any], lang: str | None) -> ColumnElement[Any]: """`expr` compared in the reader's alphabet. Case-folded, so "apple" and "Apple" sit together.""" return func.lower(expr).collate(collation(lang)) def sorted_words(db: Session, words: list[str], lang: str | None) -> list[str]: """`words` in the reader's alphabetical order, by the same ICU collation as `collated`.""" if not words: return [] w = values(column("w", String), name="words").data([(x,) for x in words]) return list(db.scalars(select(w.c.w).order_by(collated(w.c.w, lang), w.c.w)))