Repository: ckan/ckan

Issue:
Datastore_search full-text language parameter is not parsed correctly
### CKAN Version if known (or site URL)

2.8.3

### Please describe the expected behaviour

The full-text language used for `datastore_search` should be controlled by the 'language' parameter.

### Please describe the actual behaviour

The 'language' parameter to `/api/action/datastore_search` is ignored.

Code inspection indicates that `ckanext/datastore/backend/postgres.py` expects the parameter to be called "lang", but the validation in `ckanext/datastore/plugin.py` only permits a parameter called "language", which is then thrown away.

### What steps can be taken to reproduce the issue? 

- Perform a datastore search via `/api/action/datastore_search?resource_id=<id>&q=<query>&language=english`
- Perform a datastore search via `/api/action/datastore_search?resource_id=<id>&q=<query>&language=spanish`
- Perform a datastore search via `/api/action/datastore_search?resource_id=<id>&q=<query>&language=simple`
- Perform a datastore search via `/api/action/datastore_search?resource_id=<id>&q=<query>&language=klingon`

All queries will produce the same results.

- Perform a datastore search via `/api/action/datastore_search?resource_id=<id>&q=<query>&lang=simple`

The "lang" parameter is rejected.


Discussion:
The problem is with the inconsistent with the params. If you can provide PR with the fix will be great 
Should the parameter be called "language" as the validation expects, or "lang" as the action expects? I suppose using "language" means no external change.
Hi , I have been investigating the point of code where the change needs to take place, mostly in `/ckanext/datastore` of `datastore_search`, location with the following files:
1) `/ckan/ckanext/datastore/logic/action.py `
2) `/ckan/ckanext/datastore/backend/postgres.py
`

But, when I request the API: 

`http://ckan-hostname:port/api/3/action/datastore_search?limit=5&resource_id=ce41bda8-9ff6-457a-92e9-f664f9b8bba0`

After debugging and inserting the checkpoint in (`datastore_search `method) It doesn't stops at the breakpoint. Could you please suggest whether is there any other location apart from the above which I have stated ?
Thanks !

Resolving patch:
diff --git a/ckanext/datastore/backend/postgres.py b/ckanext/datastore/backend/postgres.py
--- a/ckanext/datastore/backend/postgres.py
+++ b/ckanext/datastore/backend/postgres.py
@@ -389,7 +389,7 @@ def _where_clauses(data_dict, fields_types):
             clause_str = u'_full_text @@ {0}'.format(ts_query_alias)
             clauses.append((clause_str,))
         elif isinstance(q, dict):
-            lang = _fts_lang(data_dict.get('lang'))
+            lang = _fts_lang(data_dict.get('language'))
             for field, value in six.iteritems(q):
                 if field not in fields_types:
                     continue
@@ -573,7 +573,7 @@ def _build_fts_indexes(connection, data_dict, sql_index_str_method, fields):
     default_fts_lang = config.get('ckan.datastore.default_fts_lang')
     if default_fts_lang is None:
         default_fts_lang = u'english'
-    fts_lang = data_dict.get('lang', default_fts_lang)
+    fts_lang = data_dict.get('language', default_fts_lang)
 
     # create full-text search indexes
     def to_tsvector(x):
@@ -1774,7 +1774,7 @@ def datastore_search(self, context, data_dict, fields_types, query_dict):
         fields = data_dict.get('fields')
 
         ts_query, rank_columns = _textsearch_query(
-            _fts_lang(data_dict.get('lang')),
+            _fts_lang(data_dict.get('language')),
             data_dict.get('q'),
             data_dict.get('plain', True))
         # mutate parameter to add rank columns for _result_fields


Test patch:
diff --git a/ckanext/datastore/tests/test_db.py b/ckanext/datastore/tests/test_db.py
--- a/ckanext/datastore/tests/test_db.py
+++ b/ckanext/datastore/tests/test_db.py
@@ -90,7 +90,7 @@ def test_creates_fts_index_on_textual_fields_can_overwrite_lang_using_lang_param
         connection = mock.MagicMock()
         context = {"connection": connection}
         resource_id = "resource_id"
-        data_dict = {"resource_id": resource_id, "lang": "french"}
+        data_dict = {"resource_id": resource_id, "language": "french"}
 
         db.create_indexes(context, data_dict)
 
diff --git a/ckanext/datastore/tests/test_plugin.py b/ckanext/datastore/tests/test_plugin.py
--- a/ckanext/datastore/tests/test_plugin.py
+++ b/ckanext/datastore/tests/test_plugin.py
@@ -85,7 +85,7 @@ def test_can_overwrite_default_fts_lang_using_config_variable(self):
     @pytest.mark.ckan_config("ckan.datastore.default_fts_lang", "simple")
     def test_lang_parameter_overwrites_default_fts_lang(self):
         expected_ts_query = ", plainto_tsquery('french', 'foo') \"query\""
-        data_dict = {"q": "foo", "lang": "french"}
+        data_dict = {"q": "foo", "language": "french"}
 
         result = self._datastore_search(data_dict=data_dict)
 
@@ -95,7 +95,7 @@ def test_fts_rank_column_uses_lang_when_casting_to_tsvector(self):
         expected_select_content = (
             u"to_tsvector('french', cast(\"country\" as text))"
         )
-        data_dict = {"q": {"country": "Brazil"}, "lang": "french"}
+        data_dict = {"q": {"country": "Brazil"}, "language": "french"}
         result = self._datastore_search(data_dict=data_dict, fields_types={})
         assert expected_select_content in result["select"][0]
 
@@ -156,7 +156,7 @@ def test_fts_where_clause_lang_can_be_overwritten_using_lang_param(self):
                 u' @@ "query country"',
             )
         ]
-        data_dict = {"q": {"country": "Brazil"}, "lang": "french"}
+        data_dict = {"q": {"country": "Brazil"}, "language": "french"}
         fields_types = {"country": "text"}
 
         result = self._datastore_search(
@@ -177,7 +177,7 @@ def test_fts_adds_where_clause_on_full_text_when_querying_non_indexed_fields(
                 u' @@ "query country"',
             ),
         ]
-        data_dict = {"q": {"country": "Brazil"}, "lang": "english"}
+        data_dict = {"q": {"country": "Brazil"}, "language": "english"}
         fields_types = {"country": "non-indexed field type"}
 
         result = self._datastore_search(