Derive JS class name from stemmer filename to fix Chinese search (#14416)

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Hugo van KemenadeandBénédikt Tran authored and GitHub committed 2026-07-22 17:23:07 +02:00
1 parent c1b618c559
commit 9af5b469df
3 files changed
+43 -1

No files matched your search

+5
View File
@@ -8,6 +8,11 @@ Bugs fixed
styled with ``'colorrows'`` (which is the default).
Patch by Jean-François B.
* #14229: Fix JavaScript search for languages whose stemmer class name
does not match the language name, such as Chinese (which reuses the
English stemmer) and Dutch (which uses the Dutch Porter stemmer).
Patch by Hugo van Kemenade
Release 9.1.0 (released Dec 31, 2025)
=====================================
+12 -1
View File
@@ -582,10 +582,21 @@ class IndexBuilder:
base_js_path = _MINIFIED_JS_PATH / 'base-stemmer.js'
language_js_path = _MINIFIED_JS_PATH / self.lang.js_stemmer_rawcode
# Derive the JS class name from the stemmer filename rather than
# from language_name, since some languages reuse another language's
# stemmer. For example, SearchChinese reuses english-stemmer.js,
# which defines EnglishStemmer.
stemmer_class = (
self.lang.js_stemmer_rawcode.removesuffix('-stemmer.js')
.title()
.replace('_', '')
.replace('-', '')
+ 'Stemmer'
)
return '\n'.join((
base_js_path.read_text(encoding='utf-8'),
language_js_path.read_text(encoding='utf-8'),
f'window.Stemmer = {self.lang.language_name}Stemmer;',
f'window.Stemmer = {stemmer_class};',
))
+26
View File
@@ -393,6 +393,32 @@ def test_search_index_gen_zh(app: SphinxTestApp) -> None:
assert 'chinesetesttwo' in index['terms']
assert 'cas' in index['terms']
language_data = (app.outdir / '_static' / 'language_data.js').read_text(
encoding='utf-8'
)
# SearchChinese reuses english-stemmer.js
assert 'var EnglishStemmer' in language_data
assert 'window.Stemmer = EnglishStemmer;' in language_data
assert 'ChineseStemmer' not in language_data
@pytest.mark.parametrize(
('js_stemmer_rawcode', 'stemmer_class'),
[
('english-stemmer.js', 'EnglishStemmer'),
# dutch_porter-stemmer.js is the only one with an underscore
('dutch_porter-stemmer.js', 'DutchPorterStemmer'),
],
)
def test_js_stemmer_class_name(js_stemmer_rawcode: str, stemmer_class: str) -> None:
# check that the JS class name is correctly derived from the filename
env = DummyEnvironment('1.0', DummyDomainsContainer())
index = IndexBuilder(env, 'en', {}, '') # type: ignore[arg-type]
index.lang.js_stemmer_rawcode = js_stemmer_rawcode
js = index.get_js_stemmer_code()
assert f'var {stemmer_class}' in js
assert f'window.Stemmer = {stemmer_class};' in js
@pytest.mark.sphinx(
'html',