feat: stem exclusion admin setting and analyzer language selector improvements
Add a stem-exclusion textarea to the admin settings page. Words entered here (one per line) are passed as stem_exclusion to the language analyzer, preventing them from being stemmed. Requires a full re-index to take effect. The two language-dependent fields (stem exclusion, min search length) are disabled when CJK is selected, since neither applies to bigram analysis. Settings are reordered: search-scope switches now appear above the language block so the language-dependent fields sit directly below the language selector. Replace the lowercase ES identifier labels in the language dropdown with proper display names (e.g. "Brazilian Portuguese", "CJK (Chinese, Japanese, Korean)", "Sorani (Kurdish)"). Drift detection now tracks stem exclusion instead of the removed min_gram index setting.
This commit is contained in:
parent
0f58abf141
commit
33d4946947
|
|
@ -35,5 +35,7 @@ return [
|
||||||
->default('blomstra-search.search-discussion-subjects', true)
|
->default('blomstra-search.search-discussion-subjects', true)
|
||||||
->default('blomstra-search.search-post-bodies', true)
|
->default('blomstra-search.search-post-bodies', true)
|
||||||
->default('blomstra-search.min-search-length', Commands\BuildCommand::DEFAULT_MIN_SEARCH_LENGTH)
|
->default('blomstra-search.min-search-length', Commands\BuildCommand::DEFAULT_MIN_SEARCH_LENGTH)
|
||||||
->serializeToForum('blomstraSearchMinLength', 'blomstra-search.min-search-length', 'intval'),
|
->default('blomstra-search.stem-exclusion', '')
|
||||||
|
->serializeToForum('blomstraSearchMinLength', 'blomstra-search.min-search-length', 'intval')
|
||||||
|
->serializeToForum('blomstraSearchPostBodies', 'blomstra-search.search-post-bodies', fn ($v) => (bool) $v, true),
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import DashboardPage from 'flarum/admin/components/DashboardPage';
|
||||||
import DashboardWidget from 'flarum/admin/components/DashboardWidget';
|
import DashboardWidget from 'flarum/admin/components/DashboardWidget';
|
||||||
import Alert from 'flarum/common/components/Alert';
|
import Alert from 'flarum/common/components/Alert';
|
||||||
|
|
||||||
const REQUIRED_INDEX_COMPAT = 'v2';
|
const REQUIRED_INDEX_COMPAT = 'v3';
|
||||||
|
|
||||||
class ReindexWarningWidget extends DashboardWidget {
|
class ReindexWarningWidget extends DashboardWidget {
|
||||||
className() {
|
className() {
|
||||||
|
|
@ -35,46 +35,43 @@ app.initializers.add('blomstra-search', () => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const languages = new Map();
|
const languages: Record<string, string> = {
|
||||||
[
|
arabic: 'Arabic',
|
||||||
'arabic',
|
armenian: 'Armenian',
|
||||||
'armenian',
|
basque: 'Basque',
|
||||||
'basque',
|
bengali: 'Bengali',
|
||||||
'bengali',
|
brazilian: 'Brazilian Portuguese',
|
||||||
'brazilian',
|
bulgarian: 'Bulgarian',
|
||||||
'bulgarian',
|
catalan: 'Catalan',
|
||||||
'catalan',
|
cjk: 'CJK (Chinese, Japanese, Korean)',
|
||||||
'cjk',
|
czech: 'Czech',
|
||||||
'czech',
|
danish: 'Danish',
|
||||||
'danish',
|
dutch: 'Dutch',
|
||||||
'dutch',
|
english: 'English',
|
||||||
'english',
|
estonian: 'Estonian',
|
||||||
'estonian',
|
finnish: 'Finnish',
|
||||||
'finnish',
|
french: 'French',
|
||||||
'french',
|
galician: 'Galician',
|
||||||
'galician',
|
german: 'German',
|
||||||
'german',
|
greek: 'Greek',
|
||||||
'greek',
|
hindi: 'Hindi',
|
||||||
'hindi',
|
hungarian: 'Hungarian',
|
||||||
'hungarian',
|
indonesian: 'Indonesian',
|
||||||
'indonesian',
|
irish: 'Irish',
|
||||||
'irish',
|
italian: 'Italian',
|
||||||
'italian',
|
latvian: 'Latvian',
|
||||||
'latvian',
|
lithuanian: 'Lithuanian',
|
||||||
'lithuanian',
|
norwegian: 'Norwegian',
|
||||||
'norwegian',
|
persian: 'Persian',
|
||||||
'persian',
|
portuguese: 'Portuguese',
|
||||||
'portuguese',
|
romanian: 'Romanian',
|
||||||
'romanian',
|
russian: 'Russian',
|
||||||
'russian',
|
sorani: 'Sorani (Kurdish)',
|
||||||
'sorani',
|
spanish: 'Spanish',
|
||||||
'spanish',
|
swedish: 'Swedish',
|
||||||
'swedish',
|
turkish: 'Turkish',
|
||||||
'turkish',
|
thai: 'Thai',
|
||||||
'thai',
|
};
|
||||||
].forEach((language) => {
|
|
||||||
languages.set(language, language);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.extensionData
|
app.extensionData
|
||||||
.for('blomstra-search')
|
.for('blomstra-search')
|
||||||
|
|
@ -84,12 +81,10 @@ app.initializers.add('blomstra-search', () => {
|
||||||
if (!activeIndex || !indexedAnalyzer) return null;
|
if (!activeIndex || !indexedAnalyzer) return null;
|
||||||
|
|
||||||
const currentAnalyzer = this.setting('blomstra-search.analyzer-language')() || 'english';
|
const currentAnalyzer = this.setting('blomstra-search.analyzer-language')() || 'english';
|
||||||
const currentMinLength = this.setting('blomstra-search.min-search-length')();
|
const currentStemExclusion = this.setting('blomstra-search.stem-exclusion')() || '';
|
||||||
const indexedMinLength = String(
|
const indexedStemExclusion = app.data.settings['blomstra-search.indexed-stem-exclusion'] || '';
|
||||||
app.data.settings['blomstra-search.indexed-min-search-length'] || app.data.settings['blomstra-search.min-search-length']
|
|
||||||
);
|
|
||||||
|
|
||||||
if (currentAnalyzer === indexedAnalyzer && currentMinLength === indexedMinLength) return null;
|
if (currentAnalyzer === indexedAnalyzer && currentStemExclusion === indexedStemExclusion) return null;
|
||||||
|
|
||||||
return m(
|
return m(
|
||||||
Alert,
|
Alert,
|
||||||
|
|
@ -118,14 +113,6 @@ app.initializers.add('blomstra-search', () => {
|
||||||
default: 'flarum',
|
default: 'flarum',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
})
|
})
|
||||||
.registerSetting({
|
|
||||||
setting: 'blomstra-search.analyzer-language',
|
|
||||||
label: app.translator.trans('blomstra-search.admin.analyzer.label'),
|
|
||||||
help: app.translator.trans('blomstra-search.admin.analyzer.help'),
|
|
||||||
type: 'select',
|
|
||||||
options: Object.fromEntries(languages.entries()),
|
|
||||||
default: 'english',
|
|
||||||
})
|
|
||||||
.registerSetting({
|
.registerSetting({
|
||||||
setting: 'blomstra-search.search-discussion-subjects',
|
setting: 'blomstra-search.search-discussion-subjects',
|
||||||
label: app.translator.trans('blomstra-search.admin.search-discussion-subjects'),
|
label: app.translator.trans('blomstra-search.admin.search-discussion-subjects'),
|
||||||
|
|
@ -137,11 +124,33 @@ app.initializers.add('blomstra-search', () => {
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
})
|
})
|
||||||
.registerSetting({
|
.registerSetting({
|
||||||
setting: 'blomstra-search.min-search-length',
|
setting: 'blomstra-search.analyzer-language',
|
||||||
label: app.translator.trans('blomstra-search.admin.min-search-length.label'),
|
label: app.translator.trans('blomstra-search.admin.analyzer.label'),
|
||||||
help: app.translator.trans('blomstra-search.admin.min-search-length.help'),
|
help: app.translator.trans('blomstra-search.admin.analyzer.help'),
|
||||||
type: 'select',
|
type: 'select',
|
||||||
options: { '1': '1', '2': '2', '3': '3', '4': '4' },
|
options: languages,
|
||||||
default: app.data.settings['blomstra-search.min-search-length'],
|
default: 'english',
|
||||||
|
})
|
||||||
|
.registerSetting(function (this: any) {
|
||||||
|
const isCjk = (this.setting('blomstra-search.analyzer-language')() || 'english') === 'cjk';
|
||||||
|
return this.buildSettingComponent({
|
||||||
|
setting: 'blomstra-search.stem-exclusion',
|
||||||
|
type: 'textarea',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.settings.stem-exclusion.label'),
|
||||||
|
help: app.translator.trans('blomstra-search.admin.settings.stem-exclusion.help'),
|
||||||
|
disabled: isCjk,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.registerSetting(function (this: any) {
|
||||||
|
const isCjk = (this.setting('blomstra-search.analyzer-language')() || 'english') === 'cjk';
|
||||||
|
return this.buildSettingComponent({
|
||||||
|
setting: 'blomstra-search.min-search-length',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.min-search-length.label'),
|
||||||
|
help: app.translator.trans('blomstra-search.admin.min-search-length.help'),
|
||||||
|
type: 'select',
|
||||||
|
options: { '1': '1', '2': '2', '3': '3', '4': '4' },
|
||||||
|
default: app.data.settings['blomstra-search.min-search-length'],
|
||||||
|
disabled: isCjk,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,12 @@ blomstra-search:
|
||||||
search-post-bodies: Search inside comments
|
search-post-bodies: Search inside comments
|
||||||
match-sentences: Match search term against full sentence
|
match-sentences: Match search term against full sentence
|
||||||
match-words: Match search term against full words
|
match-words: Match search term against full words
|
||||||
|
settings:
|
||||||
|
stem-exclusion:
|
||||||
|
label: "Protected words (stem exclusion)"
|
||||||
|
help: "One word per line. These words will not be stemmed during search (e.g. brand names, proper nouns). Not applicable for CJK or Thai languages. Requires a full re-index to take effect."
|
||||||
min-search-length:
|
min-search-length:
|
||||||
label: Minimum search query length
|
label: Minimum search query length
|
||||||
help: |
|
help: |
|
||||||
Minimum number of characters required before a search is triggered. Lower this to 1 or 2
|
Minimum number of characters required before a search is triggered. Lower this to 1 or 2
|
||||||
for CJK (Chinese, Japanese, Korean) communities where single characters carry full meaning.
|
for CJK (Chinese, Japanese, Korean) communities where single characters carry full meaning.
|
||||||
Changing this requires a full index rebuild to take effect.
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue