feat: dictionaries hold words or characters, and are asked by their source
A dictionary source now says what it holds (`kind`: `words`, the default for files from before, or `characters`), a string so that an app older than a new kind leaves it out. Search, countLabelled and labelled take the dictionary by its source and meaning language, as the unique index names it, rather than by the language: with KANJIDIC2 beside JMdict, a search for words would otherwise bring kanji, and JLPT N5 would hold both. The search reads the language for its query variants from the source's row; a dictionary the instance doesn't hold finds nothing. The rank index goes by source too. Migration: drops and recreates dictionary_entry_rank_idx on (source, glossLanguage, rank), and adds dictionary_source.kind, text NOT NULL DEFAULT 'words', so a JMdict loaded before is a dictionary of words. Both tables are reference data, never synced; the old server keeps working until the switch (its queries by language just lose the index). In the app, a studyset's dictionary is one of words unless a kind is asked for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
e42cdfbfcb
commit
a6699b30cb
2 changed files with 11756 additions and 84 deletions
|
|
@ -225,8 +225,9 @@ class EndpointGitHubUpgrade extends _isc.EndpointRef {
|
|||
}
|
||||
|
||||
/// The dictionaries the instance holds, to look words up in and to take
|
||||
/// words from by a label (all JLPT N5 words). Reference data: any signed-in
|
||||
/// person may read all of it.
|
||||
/// words from by a label (all JLPT N5 words). A dictionary is one source
|
||||
/// in one meaning language (`jmdict` in `en`). Reference data: any
|
||||
/// signed-in person may read all of it.
|
||||
/// {@category Endpoint}
|
||||
class EndpointDictionary extends _isc.EndpointRef {
|
||||
EndpointDictionary(_isc.EndpointCaller caller) : super(caller);
|
||||
|
|
@ -242,13 +243,14 @@ class EndpointDictionary extends _isc.EndpointRef {
|
|||
{},
|
||||
);
|
||||
|
||||
/// The entries of the dictionary of [language] with meanings in
|
||||
/// The entries of the dictionary of [source] with meanings in
|
||||
/// [glossLanguage] that [query] finds, best first: those with a key that
|
||||
/// is the query, then a loose key that is (`sushi` for すうし), then a key
|
||||
/// starting with it, then a loose key; each in the dictionary's order. At
|
||||
/// most [limit] (30 unless given).
|
||||
/// most [limit] (30 unless given). None for a dictionary the instance
|
||||
/// doesn't hold.
|
||||
_ida.Future<List<_iqbqiphu.DictionaryHit>> search(
|
||||
String language,
|
||||
String source,
|
||||
String glossLanguage,
|
||||
String query, {
|
||||
int? limit,
|
||||
|
|
@ -256,24 +258,24 @@ class EndpointDictionary extends _isc.EndpointRef {
|
|||
'dictionary',
|
||||
'search',
|
||||
{
|
||||
'language': language,
|
||||
'source': source,
|
||||
'glossLanguage': glossLanguage,
|
||||
'query': query,
|
||||
'limit': limit,
|
||||
},
|
||||
);
|
||||
|
||||
/// How many entries of the dictionary of [language] with meanings in
|
||||
/// How many entries of the dictionary of [source] with meanings in
|
||||
/// [glossLanguage] carry [label].
|
||||
_ida.Future<int> countLabelled(
|
||||
String language,
|
||||
String source,
|
||||
String glossLanguage,
|
||||
String label,
|
||||
) => caller.callServerEndpoint<int>(
|
||||
'dictionary',
|
||||
'countLabelled',
|
||||
{
|
||||
'language': language,
|
||||
'source': source,
|
||||
'glossLanguage': glossLanguage,
|
||||
'label': label,
|
||||
},
|
||||
|
|
@ -282,7 +284,7 @@ class EndpointDictionary extends _isc.EndpointRef {
|
|||
/// The entries that carry [label], in the dictionary's order: [limit] of
|
||||
/// them (100 unless given, at most [maxPage]) after the first [offset].
|
||||
_ida.Future<List<_iqbqiphu.DictionaryHit>> labelled(
|
||||
String language,
|
||||
String source,
|
||||
String glossLanguage,
|
||||
String label, {
|
||||
int? offset,
|
||||
|
|
@ -291,7 +293,7 @@ class EndpointDictionary extends _isc.EndpointRef {
|
|||
'dictionary',
|
||||
'labelled',
|
||||
{
|
||||
'language': language,
|
||||
'source': source,
|
||||
'glossLanguage': glossLanguage,
|
||||
'label': label,
|
||||
'offset': offset,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ abstract class DictionarySource
|
|||
this.id,
|
||||
required this.source,
|
||||
required this.sourceVersion,
|
||||
String? kind,
|
||||
required this.language,
|
||||
required this.glossLanguage,
|
||||
required this.license,
|
||||
|
|
@ -31,12 +32,13 @@ abstract class DictionarySource
|
|||
required this.fileName,
|
||||
required this.fileHash,
|
||||
required this.loadedAt,
|
||||
});
|
||||
}) : kind = kind ?? 'words';
|
||||
|
||||
factory DictionarySource({
|
||||
int? id,
|
||||
required String source,
|
||||
required String sourceVersion,
|
||||
String? kind,
|
||||
required String language,
|
||||
required String glossLanguage,
|
||||
required String license,
|
||||
|
|
@ -52,6 +54,7 @@ abstract class DictionarySource
|
|||
id: jsonSerialization['id'] as int?,
|
||||
source: jsonSerialization['source'] as String,
|
||||
sourceVersion: jsonSerialization['sourceVersion'] as String,
|
||||
kind: jsonSerialization['kind'] as String?,
|
||||
language: jsonSerialization['language'] as String,
|
||||
glossLanguage: jsonSerialization['glossLanguage'] as String,
|
||||
license: jsonSerialization['license'] as String,
|
||||
|
|
@ -79,6 +82,11 @@ abstract class DictionarySource
|
|||
/// Its version (`3.6.2 (2026-10-05)`).
|
||||
String sourceVersion;
|
||||
|
||||
/// What it holds: `words` (JMdict) or `characters` (KANJIDIC2). A string
|
||||
/// rather than an enum, so an app older than a new kind can leave out
|
||||
/// what it doesn't know.
|
||||
String kind;
|
||||
|
||||
/// The words' language (`ja`).
|
||||
String language;
|
||||
|
||||
|
|
@ -109,6 +117,7 @@ abstract class DictionarySource
|
|||
int? id,
|
||||
String? source,
|
||||
String? sourceVersion,
|
||||
String? kind,
|
||||
String? language,
|
||||
String? glossLanguage,
|
||||
String? license,
|
||||
|
|
@ -125,6 +134,7 @@ abstract class DictionarySource
|
|||
if (id != null) 'id': id,
|
||||
'source': source,
|
||||
'sourceVersion': sourceVersion,
|
||||
'kind': kind,
|
||||
'language': language,
|
||||
'glossLanguage': glossLanguage,
|
||||
'license': license,
|
||||
|
|
@ -143,6 +153,7 @@ abstract class DictionarySource
|
|||
if (id != null) 'id': id,
|
||||
'source': source,
|
||||
'sourceVersion': sourceVersion,
|
||||
'kind': kind,
|
||||
'language': language,
|
||||
'glossLanguage': glossLanguage,
|
||||
'license': license,
|
||||
|
|
@ -167,6 +178,7 @@ class _DictionarySourceImpl extends DictionarySource {
|
|||
int? id,
|
||||
required String source,
|
||||
required String sourceVersion,
|
||||
String? kind,
|
||||
required String language,
|
||||
required String glossLanguage,
|
||||
required String license,
|
||||
|
|
@ -179,6 +191,7 @@ class _DictionarySourceImpl extends DictionarySource {
|
|||
id: id,
|
||||
source: source,
|
||||
sourceVersion: sourceVersion,
|
||||
kind: kind,
|
||||
language: language,
|
||||
glossLanguage: glossLanguage,
|
||||
license: license,
|
||||
|
|
@ -197,6 +210,7 @@ class _DictionarySourceImpl extends DictionarySource {
|
|||
Object? id = _Undefined,
|
||||
String? source,
|
||||
String? sourceVersion,
|
||||
String? kind,
|
||||
String? language,
|
||||
String? glossLanguage,
|
||||
String? license,
|
||||
|
|
@ -210,6 +224,7 @@ class _DictionarySourceImpl extends DictionarySource {
|
|||
id: id is int? ? id : this.id,
|
||||
source: source ?? this.source,
|
||||
sourceVersion: sourceVersion ?? this.sourceVersion,
|
||||
kind: kind ?? this.kind,
|
||||
language: language ?? this.language,
|
||||
glossLanguage: glossLanguage ?? this.glossLanguage,
|
||||
license: license ?? this.license,
|
||||
|
|
|
|||
Loading…
Reference in a new issue