Wiktionary carries pronunciation for 45,000 of these headwords and the build
was throwing it away. It is now kept: 101,306 entries of IPA, each tagged with
the variety it belongs to, which matters here because a word in a 14th-century
ghazal was not said the way Tehran says it now — عشق is /ˈʔiʃq/ in Classical
Persian and [ʔeʃɢ̥] in Iran today, and the app leads with the former.
The IPA's dots and stress marks are the syllable breakdown. Urdu Wiktionary
adds its own, in Urdu script: the fully vowelled spelling عِشْق and the split
عِش + قوں, both pulled out of its wikitext.
Costs 7.7 MB of database, taking it to 94 MB.
Verified on an API 36 emulator: tapping عشق shows the Classical Persian IPA,
the Urdu syllable split, the vowelled spelling and two modern variants above
the definitions.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two Urdu sources join the Persian ones. Wiktionary's Urdu extract gives Urdu
headwords glossed in English, and Urdu Wiktionary itself gives definitions
written in Urdu — the only source here that does. The latter is thin, about
3,100 usable entries out of 31,000 pages since many are stubs, but for a word
it carries an Urdu reader is better served by it than by a translation into
English: عشق comes back as شدید جذبۂ محبت، گہری چاہت، محبت، پریم، پیار.
Every definition now names the dictionary and its language pair, and lays out
in the direction its own script reads, so an Urdu definition is right-aligned
beside a left-aligned English one.
When nothing matches, the sheet offers near words ranked by how many letters
they share with what was looked up, drawn from an index range scan on the
leading letters rather than a scan of the whole table. خودکامی, which has no
entry, offers خودکامه — the lemma it wants.
Measured honestly: the Urdu sources add little coverage over Persian — nine
words from the English-glossed extract, two from Urdu Wiktionary, against
1,285 from thirteen poems. They are here because an Urdu reader wants Urdu,
not because they widen the net.
The suggestion ranking is verified against the built database rather than only
on device: خودکامی → خودکامه, شیرازی → شیراز, مشکلها → مشکل. On an API 36
emulator all four sources answer عشق with their labels.
Known rough edge: affix stripping across four languages can mislead. ناولها
reaches ناول, the Urdu for "novel", which is not what Hafez meant. The matched
headword is always shown, so it is visible rather than silent.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Search: full-text across the poems, scoped to all poets, a few, or one. The
static data set has no index, so this is ganjoor.net's own search endpoint,
which scopes to one poet at a time — several picked poets run as several
queries and merge. Entry is the poets filter box, which now sits in the bottom
bar within thumb reach and offers its own words to the poem search one tap
further. Snippets show the line the term is actually on.
Themes: a sixth, true black, for OLED panels where an unlit pixel costs no
power. Surfaces step up in near-blacks so cards stay distinguishable.
Licences: every component is now credited in-app under Reading settings >
About & licences, with the full text bundled in assets/licenses — the OFL
requires the licence to travel with the software, so linking to it wasn't
enough. licenses/README.md indexes the same thing for the repo. The credits
list and the licence texts lay out left-to-right in English, since the rest of
the app is right-to-left for the poetry's sake and English prose is unreadable
right-aligned.
Fixes a crash: the settings sheet was composed outside the provider supplying
LocalOpenAbout, so opening it threw.
Search decoding is covered by a unit test against a real API response; the
rest verified on an API 36 emulator.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reading
- Naskh is now the default face, and both Arabic-script fonts are registered
at four weights so the text can be thickened for a lit screen.
- Category listings show each poem's opening line, fetched best-effort from
api.ganjoor.net since the data set doesn't carry excerpts.
- Tap a couplet to save that passage or copy it; a saved passage keeps a
tappable link back to its poem. Poem text is selectable for plain copying.
Languages
- Persian, Urdu and English, Persian by default whatever the phone's locale,
applied in attachBaseContext and switchable from the top bar or the sheet.
- English chrome uses Libron (OFL); poems stay naskh or nastaliq throughout.
- Each language gets its own values-* folder: with Farsi only in values/,
Android was resolving it to the Urdu strings, since a same-script locale
outranks the default.
Offline
- Downloaded poets mirror the data set's layout under filesDir, so offline
mode is one lookup rather than a parallel path. Downloads run one poet at
a time, skip what's on disk, and resume by restarting.
- Downloads screen lists every poet with their portrait and tick boxes for
picking several, plus storage used, delete, and download-everything behind
a size warning.
- Offline mode refuses the network and says what's missing rather than
blaming the connection.
Also: poet sort (Ganjoor's order or alphabetical, via a Persian collator),
RTL nav transitions, an original shamsa launcher icon with a monochrome layer
for themed icons, and preferences written with commit so they survive the
process being killed.
F-Droid: dependenciesInfo off, optional signing so the build works with no
keystore, fastlane metadata in three languages, cleartext traffic disabled.
Verified on an API 36 emulator: downloaded a poet, pulled the emulator's
network, read them offline, and confirmed an undownloaded poet reports being
missing rather than erroring.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>