Skip to content

Commit e47e30e

Browse files
committed
extra tags
1 parent 6502f9a commit e47e30e

File tree

6 files changed

+134
-26
lines changed

6 files changed

+134
-26
lines changed

src/components/dictionary/CombinedWord.tsx

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface Entry {
1313
head: string;
1414
defs: string[];
1515
similarTo?: string;
16+
extraTags?: string[];
1617
}
1718

1819
const toRoman = (n: number): string => {
@@ -38,9 +39,18 @@ interface EntryBlockProps {
3839
index: number;
3940
total: number;
4041
onDefinitionClick: (def: string) => void;
42+
searchWord: string;
4143
}
4244

43-
const EntryBlock: React.FC<EntryBlockProps> = ({ surface, entry, lang, index, total, onDefinitionClick }) => {
45+
const EntryBlock: React.FC<EntryBlockProps> = ({
46+
surface,
47+
entry,
48+
lang,
49+
index,
50+
total,
51+
onDefinitionClick,
52+
searchWord,
53+
}) => {
4454
const apyFetch = useContext(APyContext);
4555
const { t } = useLocalization();
4656
const { locale } = useLocalizationPOS();
@@ -75,6 +85,23 @@ const EntryBlock: React.FC<EntryBlockProps> = ({ surface, entry, lang, index, to
7585
const cleanSurface = surface;
7686
const cleanDefs = entry.defs.map((d) => d.replace(/<[^>]+>/g, ''));
7787

88+
const cleanedSearch = searchWord.replace(/<[^>]+>/g, '');
89+
const nonExact = cleanSurface !== cleanedSearch;
90+
91+
const extraTagsString = entry.extraTags && entry.extraTags.length ? entry.extraTags.join('') : '';
92+
const extraTokens = Array.from(extraTagsString.matchAll(/<([^>]+)>/g)).map((mm) => mm[1]);
93+
94+
const findBestMorphLabel = (tokens: string[]): string | null => {
95+
if (!tokens.length) return null;
96+
const key = tokens.join('.');
97+
const label = getPosTag(locale, key);
98+
if (label && label !== key) return label;
99+
return null;
100+
};
101+
102+
const morphLabel = findBestMorphLabel(extraTokens);
103+
const extraDisplay = morphLabel || extraTagsString;
104+
78105
const handleToggle = () => {
79106
if (!expanded) {
80107
setExpanded(true);
@@ -140,6 +167,11 @@ const EntryBlock: React.FC<EntryBlockProps> = ({ surface, entry, lang, index, to
140167
)}
141168
</div>
142169
)}
170+
{nonExact && extraTagsString && (
171+
<div className="extra-tag-info small text-muted mt-1">
172+
{extraDisplay}: {cleanedSearch}
173+
</div>
174+
)}
143175
{hasParadigms && expanded && (
144176
<div className="word-paradigm">
145177
<Paradigm head={entry.head} lang={lang} mode={mode} onLoaded={() => setLoadingParadigm(false)} />
@@ -154,9 +186,10 @@ interface CombinedWordProps {
154186
entries: Entry[];
155187
lang: string;
156188
onDefinitionClick: (def: string) => void;
189+
searchWord: string;
157190
}
158191

159-
const CombinedWord: React.FC<CombinedWordProps> = ({ surface, entries, lang, onDefinitionClick }) => (
192+
const CombinedWord: React.FC<CombinedWordProps> = ({ surface, entries, lang, onDefinitionClick, searchWord }) => (
160193
<div className="word-card">
161194
{entries.map((e, idx) => (
162195
<React.Fragment key={idx}>
@@ -167,6 +200,7 @@ const CombinedWord: React.FC<CombinedWordProps> = ({ surface, entries, lang, onD
167200
index={idx}
168201
total={entries.length}
169202
onDefinitionClick={onDefinitionClick}
203+
searchWord={searchWord}
170204
/>
171205
{idx < entries.length - 1 && <div className="entry-divider" />}
172206
</React.Fragment>

src/components/dictionary/Dictionary.tsx

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ const Dictionary: React.FC = () => {
138138
modes.push(item);
139139
} else if (item && typeof item === 'object') {
140140
const s = (item as any).sourceLanguage;
141-
const t = (item as any).targetLanguage;
142-
if (typeof s === 'string' && typeof t === 'string') {
143-
modes.push(`${s}|${t}`);
141+
const tLang = (item as any).targetLanguage;
142+
if (typeof s === 'string' && typeof tLang === 'string') {
143+
modes.push(`${s}|${tLang}`);
144144
}
145145
}
146146
});
@@ -152,9 +152,9 @@ const Dictionary: React.FC = () => {
152152
modes.push(item);
153153
} else if (item && typeof item === 'object') {
154154
const s = (item as any).sourceLanguage;
155-
const t = (item as any).targetLanguage;
156-
if (typeof s === 'string' && typeof t === 'string') {
157-
modes.push(`${s}|${t}`);
155+
const tLang = (item as any).targetLanguage;
156+
if (typeof s === 'string' && typeof tLang === 'string') {
157+
modes.push(`${s}|${tLang}`);
158158
}
159159
}
160160
});
@@ -278,9 +278,19 @@ const Dictionary: React.FC = () => {
278278

279279
const parse = (resp: any): Entry[] => {
280280
const raw = resp.data.responseData?.lookupResults ?? resp.data.responseData?.searchResults ?? [];
281-
return (raw as Array<Record<string, string[]>>).flatMap((o) =>
282-
Object.entries(o).map(([head, defs]) => ({ head, defs })),
283-
);
281+
return (raw as Array<Record<string, any>>).flatMap((o) => {
282+
const extraTagsArr: string[] = Array.isArray(o['extra-tags']) ? o['extra-tags'] : [];
283+
return Object.entries(o)
284+
.filter(([head]) => head !== 'extra-tags')
285+
.map(
286+
([head, defs]) =>
287+
({
288+
head,
289+
defs,
290+
extraTags: extraTagsArr,
291+
} as Entry),
292+
);
293+
});
284294
};
285295

286296
try {
@@ -290,7 +300,7 @@ const Dictionary: React.FC = () => {
290300

291301
const reverseRaw = parse(respRev);
292302
revParsed = reverseRaw.flatMap(({ head, defs }) =>
293-
defs.map((d) => ({ head: d.replace(/^\s*\d+\.\s*/, ''), defs: [head] })),
303+
defs.map((d) => ({ head: d.replace(/^\s*\d+\.\s*/, ''), defs: [head] } as Entry)),
294304
);
295305
const uniqueHeads = Array.from(new Set(revParsed.map((r) => r.head)));
296306
const headResponses = await Promise.all(
@@ -306,7 +316,7 @@ const Dictionary: React.FC = () => {
306316
),
307317
);
308318
});
309-
setReverseResults(uniqueHeads.map((h) => ({ head: h, defs: enriched[h] })));
319+
setReverseResults(uniqueHeads.map((h) => ({ head: h, defs: enriched[h] } as Entry)));
310320

311321
const cleanedWord = rawWord
312322
.replace(/<[^>]+>/g, '')
@@ -411,8 +421,17 @@ const Dictionary: React.FC = () => {
411421
try {
412422
const resp = await bsReq;
413423
const raw = resp.data.responseData?.searchResults ?? [];
414-
const parsed = (raw as Array<Record<string, string[]>>).flatMap((o) =>
415-
Object.entries(o).map(([hd, defs]) => ({ head: hd, defs })),
424+
const parsed = (raw as Array<Record<string, any>>).flatMap((o) =>
425+
Object.entries(o)
426+
.filter(([head]) => head !== 'extra-tags')
427+
.map(
428+
([hd, defs]) =>
429+
({
430+
head: hd,
431+
defs,
432+
extraTags: Array.isArray(o['extra-tags']) ? o['extra-tags'] : [],
433+
} as Entry),
434+
),
416435
);
417436
bilsearchParsed[mode][sim] = parsed;
418437
} catch {
@@ -534,8 +553,17 @@ const Dictionary: React.FC = () => {
534553
try {
535554
const resp = await bsReq;
536555
const raw = resp.data.responseData?.searchResults ?? [];
537-
const parsed = (raw as Array<Record<string, string[]>>).flatMap((o) =>
538-
Object.entries(o).map(([hd, defs]) => ({ head: hd, defs })),
556+
const parsed = (raw as Array<Record<string, any>>).flatMap((o) =>
557+
Object.entries(o)
558+
.filter(([head]) => head !== 'extra-tags')
559+
.map(
560+
([hd, defs]) =>
561+
({
562+
head: hd,
563+
defs,
564+
extraTags: Array.isArray(o['extra-tags']) ? o['extra-tags'] : [],
565+
} as Entry),
566+
),
539567
);
540568
bilsearchParsed[mode][sim] = parsed;
541569
} catch {
@@ -596,11 +624,7 @@ const Dictionary: React.FC = () => {
596624
);
597625

598626
const grouped: Record<string, Entry[]> = React.useMemo(() => {
599-
const all: Entry[] = [
600-
...results.map((r) => ({ head: r.head, defs: r.defs })),
601-
...reverseResults.map((r) => ({ head: r.head, defs: r.defs })),
602-
...embeddingResults.map((e) => ({ head: e.head, defs: e.defs, similarTo: (e as any).similarTo })),
603-
];
627+
const all: Entry[] = [...results, ...reverseResults, ...embeddingResults];
604628
const map: Record<string, Entry[]> = {};
605629
all.forEach((e) => {
606630
const surface = e.head.replace(/<[^>]+>/g, '');
@@ -609,6 +633,7 @@ const Dictionary: React.FC = () => {
609633
head: e.head,
610634
defs: e.defs.map((d) => d.replace(/<[^>]+>/g, '')),
611635
...(e.similarTo ? { similarTo: e.similarTo } : {}),
636+
...(e.extraTags ? { extraTags: e.extraTags } : {}),
612637
} as Entry);
613638
});
614639
return map;
@@ -663,6 +688,7 @@ const Dictionary: React.FC = () => {
663688
surface={surface}
664689
entries={entries}
665690
lang={srcLang}
691+
searchWord={searchWord}
666692
onDefinitionClick={(def) => {
667693
setSearchWord(def);
668694
setSrcLang(tgtLang);

src/strings/pos/deu.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,17 @@
99
"n.f.nn": "unbelebtes feminines Substantiv",
1010
"n.f.aa": "belebtes feminines Substantiv",
1111
"n.nt.nn": "unbelebtes neutrales Substantiv",
12-
"n.nt.aa": "belebtes neutrales Substantiv"
12+
"n.nt.aa": "belebtes neutrales Substantiv",
13+
14+
"nom": "Nominativ",
15+
"acc": "Akkusativ",
16+
"dat": "Dativ",
17+
"loc": "Lokativ",
18+
"gen": "Genitiv",
19+
"abl": "Ablativ",
20+
"ins": "Instrumentalis",
21+
"term": "Terminativ",
22+
"abe": "Abessiv",
23+
24+
"gna_impf": "Imperfektverb"
1325
}

src/strings/pos/eng.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,17 @@
99
"n.f.nn": "inanimate feminine noun",
1010
"n.f.aa": "animate feminine noun",
1111
"n.nt.nn": "inanimate neutral noun",
12-
"n.nt.aa": "animate neutral noun"
12+
"n.nt.aa": "animate neutral noun",
13+
14+
"nom": "nominative",
15+
"acc": "accusative",
16+
"dat": "dative",
17+
"gen": "genitive",
18+
"loc": "locative",
19+
"abl": "ablative",
20+
"ins": "instrumental",
21+
"term": "terminative",
22+
"abe": "abessive",
23+
24+
"gna_impf": "imperfect verb"
1325
}

src/strings/pos/rus.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,17 @@
99
"n.f.nn": "неодуш. сущ. жен. рода",
1010
"n.f.aa": "одуш. сущ. жен. рода",
1111
"n.nt.nn": "неодуш. сущ. ср. рода",
12-
"n.nt.aa": "одуш. сущ. ср. рода"
12+
"n.nt.aa": "одуш. сущ. ср. рода",
13+
14+
"nom": "именительный",
15+
"acc": "винительный",
16+
"dat": "дательный",
17+
"gen": "родительный",
18+
"loc": "местный",
19+
"abl": "исходный",
20+
"ins": "творительный",
21+
"term": "предел",
22+
"abe": "безналичный",
23+
24+
"gna_impf": "несовершенный глагол"
1325
}

src/strings/pos/ukr.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,17 @@
99
"n.f.nn": "неіст. ім. жін. роду",
1010
"n.f.aa": "іст. ім. жін. роду",
1111
"n.nt.nn": "неіст. ім. сер. роду",
12-
"n.nt.aa": "іст. ім. сер. роду"
12+
"n.nt.aa": "іст. ім. сер. роду",
13+
14+
"nom": "називний",
15+
"acc": "знахідний",
16+
"dat": "давальний",
17+
"gen": "родовий",
18+
"loc": "місцевий",
19+
"abl": "відмінок походження",
20+
"ins": "орудний",
21+
"term": "кінцевий",
22+
"abe": "безвідмінковий",
23+
24+
"gna_impf": "недоконане дієслово"
1325
}

0 commit comments

Comments
 (0)