Skip to content

feat(library): name and filter by the languages of a deck's cards - #286

Merged
ixuz merged 1 commit into
mainfrom
library-card-languages
Oct 24, 2026
Merged

ixuz merged 1 commit into
mainfrom
library-card-languages

Conversation

@ixuz

@ixuz ixuz commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

What and why

The library shows a deck's title, description and keywords in the learner's language, but not the languages its cards are in. A German or Korean learner who adds a deck finds out only afterward that its cards are in English and Swedish. The index already says which languages each release is in (dcterms:language, IRIs from the EU's language table), but the app never read them.

  • Domain: LibraryDeck.languages holds the current release's EU language IRIs, in the order the release gives them. The list is empty when a release states none, since the shape does not require them. languageTagOf (domain/euLanguages.ts) maps each IRI to a language tag ("KOR" to "ko"), and a test covers every entry of EU_LANGUAGES. An IRI that is not on the list is left out.
  • Mapper: toLibraryDecks and toStandaloneLibraryDeck read dcterms:language, so a deck added from a link has its languages too. The Studio's listing preview takes them from the draft.
  • Shown: each language is named in the app's language through Intl.DisplayNames. The names appear on each library row next to the card count, on the deck's page ("Card languages") and in the preview ("Cards in English, Swedish."). A long list wraps on narrow screens.
  • Filter: a "Card languages" group of checkboxes sits next to Topics. It lists the languages the decks state, sorted by name. A deck is shown when its cards are in every checked language, and the choice is remembered like the topics. filterLibraryDecks takes languages next to topics and query.
  • Docs and journey: the library screen's description in docs/deck-library.md and the user guide are updated. A new journey, library-languages.journey.ts, checks Japanese as a guest, finds only Basic Japanese, opens its page and finds the filter still set when it comes back.

Nothing the app writes to a pod changes, and ns/ is untouched.

Closes: #282

Checklist

  • One issue. This pull request addresses one issue, linked above.
  • One step. This pull request does not finish its issue, so it says Refs:, not Closes:. Leave this unchecked otherwise.
  • Done, as AGENTS.md defines it: npm run check passes (lint, Markdown and spelling included), npm run lint:reuse too if a file was added, and npm run crosscheck too if ns/ or decks/ changed. (crosscheck n/a: neither ns/ nor decks/ changed)
  • Tests. New and changed code has its tests, and every package stays at 100% coverage (docs/testing.md).
  • Docs. The docs say what changed, and a new page in docs/ is listed in docs/docs.ttl. (no new page)
  • Languages. A new or changed message is in every locale: en, sv, ko, de, es and fr (packages/ui/src/i18n/).
  • Vocabulary and shapes. Any change to ns/ was agreed in an issue first; no published ns/shapes/*/vN.ttl or decks/*/vN.ttl was edited; generated files were regenerated, not edited. (n/a: ns/ and generated files unchanged)
  • Breaking? Nothing in the public API breaks, or a commit says so (! and a BREAKING CHANGE: footer). npm run check:breaking sees a line of api/ that goes, but not a feature removed, nor a reader that reads less than before.
  • Pod data. Any change to what the app writes to a pod comes with its migration (docs/migrations.md). (n/a: nothing written to a pod changes)
  • Policy. Any change to an external rule the code follows (SM-2, the plural rules, a specification) is cited. (the tags are the ISO 639-1 codes of the EU language table's entries, as the issue describes)
  • Licenses. New content is MIT, or a deck states its own license; a new file has its SPDX header (npm run lint:reuse), or a new deck its line in REUSE.toml; third-party content is credited.
  • Architecture. Imports follow docs/boundaries.md and the layers of docs/architecture.md.
  • Run. I ran the app (npm run dev) and tried the change, and considered the user journeys.
  • Authorship. I read and understand every line of this pull request, and answer for it, whatever tools helped write it (CONTRIBUTING.md).
  • Commits. Each commit is one logical change, in Conventional Commits form (type(scope): subject, ! and a BREAKING CHANGE: footer if it breaks something), with an imperative subject and a body that explains why (CONTRIBUTING.md).

The library showed a deck's title, description and keywords in the
learner's language, but not the languages its cards are in, so a German
or Korean learner found out only after adding a deck that its cards are
in English and Swedish. The index already states them as
dcterms:language; the app never read them.

LibraryDeck now carries its current release's languages, read from the
index and from a release added from a link. Each EU language IRI is
mapped to a language tag in the domain (a test covers every entry of
EU_LANGUAGES) and named in the app's language; one not on the list is
left out. The library row, the deck's page and its preview name them,
and a "Card languages" group of checkboxes keeps the decks whose cards
are in every checked language, remembered like the topics. A new
journey filters the library by Japanese.

Closes: #282
@ixuz ixuz added enhancement New feature or request i18n labels Oct 24, 2026
@ixuz
ixuz enabled auto-merge October 24, 2026 15:21
@ixuz
ixuz added this pull request to the merge queue Oct 24, 2026
Merged via the queue into main with commit 530d439 Oct 24, 2026
35 checks passed
@ixuz
ixuz deleted the library-card-languages branch October 24, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request i18n

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The library does not say which languages a deck's cards are in

1 participant