Repository: WeblateOrg/weblate

Issue:
glossaries do not have a search box.
### Steps to reproduce
1. you have a large glossary
2. you need to check an entry if there is or not. 
3. you don't have a simple search box for entries.



### Expected behaviour
Put a searh box on every glossary page.




Discussion:
Good idea, probably nobody considered so far need for search in glossaries.
+1 same need for me.
Hi @nijel, i was thinking about this and there should be an attribute in this class for search term and the result should be filtered there:

https://github.com/WeblateOrg/weblate/blob/9b04dbd50b7c72ed9d47d15652177df4c41c96e0/weblate/trans/views/dictionary.py#L284-L348

Then some form should be made in template to reference the search term.

What do you think?

Edit: Now i can see the letter_form and what it does. I may start this way, shouldn't I?
Another thought:
If there is search field in `Glossary`, what is the justification for Letter form filtering?

Regards, F.
Now I examined all the forms and it seems that the whole `show_dictionary` view should be wrapped into `SearchForm`.
At least it looks like it should.

Resolving patch:
diff --git a/weblate/trans/forms.py b/weblate/trans/forms.py
--- a/weblate/trans/forms.py
+++ b/weblate/trans/forms.py
@@ -1008,6 +1008,11 @@ def to_python(self, value):
             raise ValidationError(_('Invalid integer list!'))
 
 
+class OneWordForm(forms.Form):
+    """Simple one-word form"""
+    term = forms.CharField(label=_('Search'), max_length=30, required=False)
+
+
 class WordForm(forms.Form):
     """Form for adding word to a glossary."""
     source = forms.CharField(label=_('Source'), max_length=190)
diff --git a/weblate/trans/views/dictionary.py b/weblate/trans/views/dictionary.py
--- a/weblate/trans/views/dictionary.py
+++ b/weblate/trans/views/dictionary.py
@@ -39,7 +39,7 @@
 from weblate.utils.site import get_site_url
 from weblate.utils.errors import report_error
 from weblate.trans.util import render, redirect_next, redirect_param
-from weblate.trans.forms import WordForm, DictUploadForm, LetterForm
+from weblate.trans.forms import WordForm, DictUploadForm, LetterForm, OneWordForm
 from weblate.utils.views import get_project, import_message
 from weblate.utils.views import get_paginator
 
@@ -310,6 +310,16 @@ def show_dictionary(request, project, lang):
 
     letterform = LetterForm(request.GET)
 
+    searchform = OneWordForm(request.GET)
+
+    if searchform.is_valid() and searchform.cleaned_data['term'] != '':
+        words = words.filter(
+            source__icontains=searchform.cleaned_data['term']
+        )
+        search = searchform.cleaned_data['term']
+    else:
+        search = ''
+
     if letterform.is_valid() and letterform.cleaned_data['letter'] != '':
         words = words.filter(
             source__istartswith=letterform.cleaned_data['letter']
@@ -334,9 +344,13 @@ def show_dictionary(request, project, lang):
             'language': lang,
             'page_obj': words,
             'form': form,
-            'query_string': 'letter={}'.format(letter) if letter else '',
+            'query_string': urlencode({
+                'term': search,
+                'letter': letter
+            }),
             'uploadform': uploadform,
             'letterform': letterform,
+            'searchform': searchform,
             'letter': letter,
             'last_changes': last_changes,
             'last_changes_url': urlencode({


Test patch:
diff --git a/weblate/trans/tests/test_dictionary.py b/weblate/trans/tests/test_dictionary.py
--- a/weblate/trans/tests/test_dictionary.py
+++ b/weblate/trans/tests/test_dictionary.py
@@ -318,6 +318,12 @@ def test_list(self):
         self.assertContains(response, '1 / 1')
         self.assertContains(response, 'datový tok')
 
+        # Filtering by string
+        response = self.client.get(dict_url, {'term': 'mark'})
+        self.assertContains(response, 'Czech')
+        self.assertContains(response, '1 / 1')
+        self.assertContains(response, 'záložka')
+
     def test_get_words(self):
         translation = self.get_translation()
         Dictionary.objects.create(