WikidataBuilder has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/393560 )

Change subject: New Wikidata Build - 2017-11-27T10:00:01+0000
......................................................................

New Wikidata Build - 2017-11-27T10:00:01+0000

Change-Id: Idd89f8edde26b339bf9d1495e315dae7e338dab1
---
M composer.lock
D extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q2.json
D extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q3.json
D extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q4.json
M 
extensions/Constraints/tests/phpunit/Checker/QualifierChecker/QualifiersCheckerTest.php
M extensions/Wikibase/build/generateAutoload.php
M extensions/Wikibase/client/i18n/ais.json
M extensions/Wikibase/client/i18n/pt-br.json
M extensions/Wikibase/docs/options.wiki
M extensions/Wikibase/lib/i18n/sat.json
M extensions/Wikibase/repo/Wikibase.hooks.php
M extensions/Wikibase/repo/autoload.php
M extensions/Wikibase/repo/config/Wikibase.default.php
M extensions/Wikibase/repo/i18n/ais.json
M extensions/Wikibase/repo/i18n/be-tarask.json
M extensions/Wikibase/repo/i18n/ca.json
M extensions/Wikibase/repo/i18n/sat.json
A extensions/Wikibase/repo/includes/Search/Elastic/ConfigBuilder.php
M extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsField.php
M 
extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsProviderFieldDefinitions.php
M extensions/Wikibase/repo/includes/Search/Elastic/Fields/LabelsField.php
M extensions/Wikibase/repo/includes/Search/Elastic/Fields/TermIndexField.php
M extensions/Wikibase/repo/includes/WikibaseRepo.php
A extensions/Wikibase/repo/tests/phpunit/data/analyzer/en-ru-es-de-zh.expected
A extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-nolang.expected
A extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-noplug.expected
A extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk.expected
A extensions/Wikibase/repo/tests/phpunit/data/analyzer/sv.expected
A 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/AnalysisConfigBuilderTest.php
M 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/AllLabelsFieldTest.php
A 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionFieldTest.php
A 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionProviderFieldDefinitionsTest.php
M 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/ItemFieldDefinitionsTest.php
M 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelCountFieldTest.php
M 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsFieldTest.php
M 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsProviderFieldDefinitionsTest.php
A 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/SearchFieldTestCase.php
M 
extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/StatementCountFieldTest.php
M vendor/composer/installed.json
39 files changed, 1,594 insertions(+), 301 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikidata 
refs/changes/60/393560/1

diff --git a/composer.lock b/composer.lock
index 905650e..41c93ce 100644
--- a/composer.lock
+++ b/composer.lock
@@ -855,7 +855,7 @@
             "source": {
                 "type": "git",
                 "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseQualityConstraints";,
-                "reference": "881e265221b80e6ea20a4baff90e5d53b69ed8a6"
+                "reference": "7c591dc0c9ed46bd76a4541263c6fa1015715146"
             },
             "require": {
                 "php": ">=5.5.9",
@@ -906,7 +906,7 @@
             "support": {
                 "issues": 
"https://phabricator.wikimedia.org/project/profile/1202/";
             },
-            "time": "2017-11-24 22:29:05"
+            "time": "2017-11-27 08:10:20"
         },
         {
             "name": "wikibase/data-model",
@@ -1228,7 +1228,7 @@
             "source": {
                 "type": "git",
                 "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/Wikibase";,
-                "reference": "45dabf27253840cc8271fbf59a8c05324e6b9400"
+                "reference": "55d1e3f7b56db18b134259fb2a86bbf8a87691af"
             },
             "require": {
                 "composer/installers": ">=1.0.1",
@@ -1289,7 +1289,7 @@
                 "issues": "https://phabricator.wikimedia.org/";,
                 "irc": "irc://irc.freenode.net/wikidata"
             },
-            "time": "2017-11-25 21:59:04"
+            "time": "2017-11-27 08:47:48"
         },
         {
             "name": "wikibase/wikimedia-badges",
diff --git 
a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q2.json 
b/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q2.json
deleted file mode 100644
index e0ac9b7..0000000
--- a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q2.json
+++ /dev/null
@@ -1,90 +0,0 @@
-{
-  "pageid": 3708,
-  "ns": 120,
-  "title": "Item:Q2",
-  "lastrevid": 3798,
-  "modified": "2015-02-20T17:16:17Z",
-  "id": "Q2",
-  "type": "item",
-  "labels": {
-    "en": {
-      "language": "en",
-      "value": "TestItemQualifier"
-    }
-  },
-  "descriptions": {
-    "en": {
-      "language": "en",
-      "value": "Used for tests"
-    }
-  },
-  "claims": {
-    "P39": [
-      {
-        "id": "Q2$58d44e49-4f6e-0b54-2053-87ca689b782d",
-        "mainsnak": {
-          "snaktype": "value",
-          "property": "P39",
-          "datatype": "wikibase-item",
-          "datavalue": {
-            "value": {
-              "entity-type": "item",
-              "numeric-id": 11696
-            },
-            "type": "wikibase-entityid"
-          }
-        },
-        "qualifiers": {
-          "P580": [
-            {
-              "hash": "260f6c7209e0cca030566a31875f1bbac2b6f897",
-              "snaktype": "value",
-              "property": "P580",
-              "datatype": "time",
-              "datavalue": {
-                "value": {
-                  "time": "+00000001970-01-01T00:00:00Z",
-                  "timezone": 0,
-                  "before": 0,
-                  "after": 0,
-                  "precision": 11,
-                  "calendarmodel": "http://www.wikidata.org/entity/Q1985727";
-                },
-                "type": "time"
-              }
-            }
-          ],
-          "P582": [
-            {
-              "hash": "cfd28d592bad8e17a97cc614b65d871234118fac",
-              "snaktype": "somevalue",
-              "property": "P582"
-            }
-          ],
-          "P1365": [
-            {
-              "hash": "becbfbdf359b0a0e96a53c9ef1c433f41a394fef",
-              "snaktype": "value",
-              "property": "P1365",
-              "datatype": "wikibase-item",
-              "datavalue": {
-                "value": {
-                  "entity-type": "item",
-                  "numeric-id": 207
-                },
-                "type": "wikibase-entityid"
-              }
-            }
-          ]
-        },
-        "qualifiers-order": [
-          "P580",
-          "P582",
-          "P1365"
-        ],
-        "type": "statement",
-        "rank": "normal"
-      }
-    ]
-  }
-}
\ No newline at end of file
diff --git 
a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q3.json 
b/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q3.json
deleted file mode 100644
index a3baf06..0000000
--- a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q3.json
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "pageid": 3708,
-  "ns": 120,
-  "title": "Item:Q3",
-  "lastrevid": 3799,
-  "modified": "2015-02-20T17:29:07Z",
-  "id": "Q3",
-  "type": "item",
-  "labels": {
-    "en": {
-      "language": "en",
-      "value": "TestItemQualifier"
-    }
-  },
-  "descriptions": {
-    "en": {
-      "language": "en",
-      "value": "Used for tests"
-    }
-  },
-  "claims": {
-    "P39": [
-      {
-        "id": "Q3$58d44e49-4f6e-0b54-2053-87ca689b782d",
-        "mainsnak": {
-          "snaktype": "value",
-          "property": "P39",
-          "datatype": "wikibase-item",
-          "datavalue": {
-            "value": {
-              "entity-type": "item",
-              "numeric-id": 11696
-            },
-            "type": "wikibase-entityid"
-          }
-        },
-        "qualifiers": {
-          "P580": [
-            {
-              "hash": "260f6c7209e0cca030566a31875f1bbac2b6f897",
-              "snaktype": "value",
-              "property": "P580",
-              "datatype": "time",
-              "datavalue": {
-                "value": {
-                  "time": "+00000001970-01-01T00:00:00Z",
-                  "timezone": 0,
-                  "before": 0,
-                  "after": 0,
-                  "precision": 11,
-                  "calendarmodel": "http://www.wikidata.org/entity/Q1985727";
-                },
-                "type": "time"
-              }
-            }
-          ],
-          "P582": [
-            {
-              "hash": "cfd28d592bad8e17a97cc614b65d871234118fac",
-              "snaktype": "somevalue",
-              "property": "P582"
-            }
-          ],
-          "P1365": [
-            {
-              "hash": "becbfbdf359b0a0e96a53c9ef1c433f41a394fef",
-              "snaktype": "value",
-              "property": "P1365",
-              "datatype": "wikibase-item",
-              "datavalue": {
-                "value": {
-                  "entity-type": "item",
-                  "numeric-id": 207
-                },
-                "type": "wikibase-entityid"
-              }
-            }
-          ],
-          "P39": [
-            {
-              "hash": "cba7752d4f0b1657056117681065f62621e18679",
-              "snaktype": "value",
-              "property": "P39",
-              "datatype": "wikibase-item",
-              "datavalue": {
-                "value": {
-                  "entity-type": "item",
-                  "numeric-id": 11696
-                },
-                "type": "wikibase-entityid"
-              }
-            }
-          ]
-        },
-        "qualifiers-order": [
-          "P580",
-          "P582",
-          "P1365",
-          "P39"
-        ],
-        "type": "statement",
-        "rank": "normal"
-      }
-    ]
-  }
-}
\ No newline at end of file
diff --git 
a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q4.json 
b/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q4.json
deleted file mode 100644
index d466a71..0000000
--- a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/Q4.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "pageid": 2060,
-  "ns": 0,
-  "title": "Q4",
-  "lastrevid": 10966,
-  "modified": "2015-03-30T12:08:45Z",
-  "id": "Q4",
-  "type": "item",
-  "labels": {
-    "en": {
-      "language": "en",
-      "value": "TestItemNoQualifiers"
-    }
-  },
-  "descriptions": {
-    "en": {
-      "language": "en",
-      "value": "Used for tests"
-    }
-  },
-  "claims": {
-    "P39": [
-      {
-        "id": "Q4$1664c9bc-48d9-5e8e-90c9-d1ef226e5e7e",
-        "mainsnak": {
-          "snaktype": "value",
-          "property": "P39",
-          "datatype": "wikibase-item",
-          "datavalue": {
-            "value": {
-              "entity-type": "item",
-              "numeric-id": 344
-            },
-            "type": "wikibase-entityid"
-          }
-        },
-        "type": "statement",
-        "rank": "normal"
-      }
-    ]
-  }
-}
\ No newline at end of file
diff --git 
a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/QualifiersCheckerTest.php
 
b/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/QualifiersCheckerTest.php
index 4e22076..a31d09e 100644
--- 
a/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/QualifiersCheckerTest.php
+++ 
b/extensions/Constraints/tests/phpunit/Checker/QualifierChecker/QualifiersCheckerTest.php
@@ -2,7 +2,6 @@
 
 namespace WikibaseQuality\ConstraintReport\Test\QualifierChecker;
 
-use Wikibase\DataModel\Entity\Item;
 use Wikibase\DataModel\Entity\ItemId;
 use Wikibase\DataModel\Statement\Statement;
 use Wikibase\DataModel\Statement\StatementListProvider;
@@ -13,7 +12,6 @@
 use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\MainSnakContext;
 use WikibaseQuality\ConstraintReport\Tests\ConstraintParameters;
 use WikibaseQuality\ConstraintReport\Tests\ResultAssertions;
-use WikibaseQuality\Tests\Helper\JsonFileEntityLookup;
 
 /**
  * @covers 
\WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\QualifiersChecker
@@ -36,11 +34,6 @@
        private $qualifiersList;
 
        /**
-        * @var JsonFileEntityLookup
-        */
-       private $lookup;
-
-       /**
         * @var QualifiersChecker
         */
        private $checker;
@@ -48,7 +41,6 @@
        protected function setUp() {
                parent::setUp();
                $this->qualifiersList = [ 'P580', 'P582', 'P1365', 'P1366', 
'P642', 'P805' ];
-               $this->lookup = new JsonFileEntityLookup( __DIR__ );
                $this->checker = new QualifiersChecker( 
$this->getConstraintParameterParser(), $this->getConstraintParameterRenderer() 
);
        }
 
@@ -63,8 +55,15 @@
        }
 
        public function testQualifiersConstraint() {
-               /** @var Item $entity */
-               $entity = $this->lookup->getEntity( new ItemId( 'Q2' ) );
+               $entity = NewItem::withId( 'Q2' )
+                       ->andStatement(
+                               NewStatement::forProperty( 'P39' )
+                                       ->withValue( new ItemId( 'Q11696' ) )
+                                       ->withQualifier( 'P580', '1970-01-01' )
+                                       ->withQualifier( 'P582', 'somevalue' )
+                                       ->withQualifier( 'P1365', new ItemId( 
'Q207' ) )
+                       )
+                       ->build();
                $statement = $this->getFirstStatement( $entity );
                $constraint = $this->getConstraintMock( 
$this->propertiesParameter( $this->qualifiersList ) );
 
@@ -74,8 +73,16 @@
        }
 
        public function testQualifiersConstraintTooManyQualifiers() {
-               /** @var Item $entity */
-               $entity = $this->lookup->getEntity( new ItemId( 'Q3' ) );
+               $entity = NewItem::withId( 'Q3' )
+                       ->andStatement(
+                               NewStatement::forProperty( 'P39' )
+                                       ->withValue( new ItemId( 'Q11696' ) )
+                                       ->withQualifier( 'P580', '1970-01-01' )
+                                       ->withQualifier( 'P582', 'somevalue' )
+                                       ->withQualifier( 'P1365', new ItemId( 
'Q207' ) )
+                                       ->withQualifier( 'P39', new ItemId( 
'Q11696' ) )
+                       )
+                       ->build();
                $statement = $this->getFirstStatement( $entity );
                $constraint = $this->getConstraintMock( 
$this->propertiesParameter( $this->qualifiersList ) );
 
@@ -85,8 +92,12 @@
        }
 
        public function testQualifiersConstraintNoQualifiers() {
-               /** @var Item $entity */
-               $entity = $this->lookup->getEntity( new ItemId( 'Q4' ) );
+               $entity = NewItem::withId( 'Q4' )
+                       ->andStatement(
+                               NewStatement::forProperty( 'P39' )
+                                       ->withValue( new ItemId( 'Q344' ) )
+                       )
+                       ->build();
                $statement = $this->getFirstStatement( $entity );
                $constraint = $this->getConstraintMock( 
$this->propertiesParameter( $this->qualifiersList ) );
 
diff --git a/extensions/Wikibase/build/generateAutoload.php 
b/extensions/Wikibase/build/generateAutoload.php
index 5435c69..b606c63 100644
--- a/extensions/Wikibase/build/generateAutoload.php
+++ b/extensions/Wikibase/build/generateAutoload.php
@@ -72,6 +72,7 @@
                                
'tests/phpunit/includes/LinkedData/EntityDataTestProvider.php',
                                
'tests/phpunit/includes/Rdf/NTriplesRdfTestHelper.php',
                                
'tests/phpunit/includes/Rdf/RdfBuilderTestData.php',
+                               
'tests/phpunit/includes/Search/Elastic/Fields/SearchFieldTestCase.php',
                                
'tests/phpunit/includes/Search/Elastic/Fields/WikibaseNumericFieldTest.php',
                                
'tests/phpunit/includes/Store/MockEntityIdPager.php',
                                
'tests/phpunit/includes/Specials/HtmlAssertionHelpers.php',
diff --git a/extensions/Wikibase/client/i18n/ais.json 
b/extensions/Wikibase/client/i18n/ais.json
index ef1707c..fd2e656 100644
--- a/extensions/Wikibase/client/i18n/ais.json
+++ b/extensions/Wikibase/client/i18n/ais.json
@@ -8,8 +8,11 @@
        },
        "wikibase-client-desc": "mamaedapay-malutapiingan nu Wikibase sacunusan 
a sakaluk",
        "tooltip-t-wikibase": "masasiket tayza i papatunay a kalunasulitan 
pisupeday a kakitizaan tu kasacacay",
+       "wikibase-after-page-move-queued": "masasiket tina kasabelih a [$1 
{{WBREPONAME}} kasacacay] amalunuk misabaluh sawsawni. piazihen tian caay 
dayhiw amisabaluh tansul.",
+       "wikibase-after-page-delete-queued": "masasiket tina kasabelih a [$1 
{{WBREPONAME}} kasacacay] amalunuk misabaluh sawsawni. piazihen tian caay 
dayhiw amisabaluh tansul.",
        "wikibase-comment-add": "mapatizeng {{WBREPONAME}} kasacacay tuway.",
        "wikibase-comment-remove": "masipu masasiketay a {{WBREPONAME}} 
kasacacay, kamu masasiket masipu tuway.",
+       "wikibase-comment-linked": "masasiket {{WBREPONAME}} tuway kasacacay tu 
tina kasabelih.",
        "wikibase-comment-unlink": "tina kasabelih mahulak tuway namakay 
{{WBREPONAME}} kasacacay misiket, kamu masasiket masipu tuway.",
        "wikibase-comment-restore": "mapalawpes tu masipu mahizaay 
{{WBREPONAME}} kasacacay, kamu masasiket mapatiku tuway",
        "wikibase-comment-update": "masumad tuway {{WBREPONAME}} kasacacay",
@@ -48,6 +51,7 @@
        "wikibase-error-invalid-entity-id": "sisetyimo la’cus taazihan 
nasulitan a ID [$2]. pisaungay kapahay a ID",
        "wikibase-error-exceeded-entity-access-limit": "ciwsac sayadah 
{{WBREPONAME}} kasacacay.",
        "unconnectedpages": "kasabelih caay masasiket tayza amahicahica tu 
kasacacay",
+       "wikibase-unconnectedpages-format-row": "(kya kasabelih izaw 
{{PLURAL:$1|$1 malakuit kamu masasiket}})",
        "wikibase-unconnectedpages-submit": "paazih  kasabelih",
        "pageswithbadges": "u sikunpayay kasabelih",
        "wikibase-pageswithbadges-invalid-id": "$1 caay ku kapahay a ID 
kasacacay",
diff --git a/extensions/Wikibase/client/i18n/pt-br.json 
b/extensions/Wikibase/client/i18n/pt-br.json
index ddda4fb..cd7cd4b 100644
--- a/extensions/Wikibase/client/i18n/pt-br.json
+++ b/extensions/Wikibase/client/i18n/pt-br.json
@@ -13,7 +13,8 @@
                        "He7d3r",
                        "Luk3",
                        "Felipe L. Ewald",
-                       "Eduardo Addad de Oliveira"
+                       "Eduardo Addad de Oliveira",
+                       "TheEduGobi"
                ]
        },
        "wikibase-client-desc": "Cliente para a extensão Wikibase",
@@ -85,7 +86,7 @@
        "wikibase-rc-show-wikidata-pref": "Mostrar as edições {{WBREPONAME}} 
nas mudanças recentes",
        "wikibase-rc-wikibase-edit-letter": "D",
        "wikibase-rc-wikibase-edit-title": "Edição {{WBREPONAME}}",
-       "wikibase-rcfilters-hide-wikibase-label": "Edições {{WBREPONAME}}",
+       "wikibase-rcfilters-hide-wikibase-label": "Edições no {{WBREPONAME}}",
        "wikibase-rcfilters-hide-wikibase-description": "Edições que se 
originam em {{WBREPONAME}}.",
        "wikibase-rcfilters-hide-wikibase-conflicts-ores": "Este filtro está em 
conflito com um ou mais filtros de Qualidade de Contribuição ou Intenção de 
Usuário. As previsões de qualidade e intenção não estão disponíveis para as 
edições {{WBREPONAME}}.",
        "wikibase-rcfilters-hide-wikibase-conflicts-ores-global": "O filtro 
\"{{WBREPONAME}} edits\" está em conflito com um ou mais filtros de Qualidade 
de Contribuição ou Intenção de Usuário. As previsões de qualidade e intenção 
não estão disponíveis para as edições {{WBREPONAME}}. Os filtros conflitantes 
estão marcados na área Filtros Ativos, acima.",
diff --git a/extensions/Wikibase/docs/options.wiki 
b/extensions/Wikibase/docs/options.wiki
index 0f18e7b..5299af4 100644
--- a/extensions/Wikibase/docs/options.wiki
+++ b/extensions/Wikibase/docs/options.wiki
@@ -69,6 +69,7 @@
 :;defaultPrefixRescoreProfile: name of the rescoring profile to use for prefix 
search. The profile should be defined in 
<code>config/ElasticSearchRescoreProfiles.php</code>. (Cirrus)
 :;rescoreProfiles: Loaded from 
<code>config/ElasticSearchRescoreProfiles.php</code>, does not have to be 
defined manually. (Cirrus).
 :;statementBoost: Configuration to boost or deboost certain statement values 
(Cirrus).
+:;useStemming: Configuration to use stemming analyzer for descriptions in 
certain languages. Array of two fields: index - use it for indexing, query - 
use main text field for querying. (Cirrus)
 ;searchIndexProperties: Array of properties (by ID string) that should be 
included in the "statement_keywords" field of the search index. For now, only 
relevant when Cirrus search is enabled.
 
 == Client Settings ==
diff --git a/extensions/Wikibase/lib/i18n/sat.json 
b/extensions/Wikibase/lib/i18n/sat.json
index 66d1e3e..6fd31d4 100644
--- a/extensions/Wikibase/lib/i18n/sat.json
+++ b/extensions/Wikibase/lib/i18n/sat.json
@@ -1,8 +1,10 @@
 {
        "@metadata": {
                "authors": [
-                       "Albinus"
+                       "Albinus",
+                       "Ramjit Tudu"
                ]
        },
-       "wikibase-sitelinks-wikipedia": "Wikipeḍia"
+       "wikibase-sitelinks-wikipedia": "Wikipeḍia",
+       "version-wikibase": "ᱣᱤᱠᱤᱵᱮᱥ"
 }
diff --git a/extensions/Wikibase/repo/Wikibase.hooks.php 
b/extensions/Wikibase/repo/Wikibase.hooks.php
index 0d6eb3d..dbe5cab 100644
--- a/extensions/Wikibase/repo/Wikibase.hooks.php
+++ b/extensions/Wikibase/repo/Wikibase.hooks.php
@@ -6,6 +6,7 @@
 use ApiEditPage;
 use ApiQuerySiteinfo;
 use BaseTemplate;
+use CirrusSearch\Maintenance\AnalysisConfigBuilder;
 use CirrusSearch\Search\FunctionScoreBuilder;
 use CirrusSearch\Search\SearchContext;
 use Content;
@@ -38,6 +39,7 @@
 use Wikibase\Repo\Hooks\InfoActionHookHandler;
 use Wikibase\Repo\Hooks\OutputPageEntityIdReader;
 use Wikibase\Repo\Search\Elastic\Fields\StatementsField;
+use Wikibase\Repo\Search\Elastic\ConfigBuilder;
 use Wikibase\Repo\Search\Elastic\StatementBoostScoreBuilder;
 use Wikibase\Repo\WikibaseRepo;
 use Wikibase\Store\Sql\SqlSubscriptionLookup;
@@ -1002,11 +1004,21 @@
        }
 
        /**
-        * Adds Wikibase-specific ElasticSearch analyzer configurations.
-        *
+        * Add Wikibase-specific ElasticSearch analyzer configurations.
         * @param array &$config
+        * @param AnalysisConfigBuilder $builder
         */
-       public static function onCirrusSearchAnalysisConfig( &$config ) {
+       public static function onCirrusSearchAnalysisConfig( &$config, 
AnalysisConfigBuilder $builder ) {
+               static $inHook;
+               if ( $inHook ) {
+                       // Do not call this hook repeatedly, since 
ConfigBuilder calls AnalysisConfigBuilder
+                       // FIXME: this is not a very nice hack, but we need it 
because we want AnalysisConfigBuilder
+                       // to call the hook, since other extensions may make 
relevant changes to config.
+                       // We just don't want to run this specific hook again, 
but Mediawiki API does not have
+                       // the means to exclude one hook temporarily.
+                       return;
+               }
+
                // Analyzer for splitting statements and extracting properties:
                // P31:Q1234 => P31
                $config['analyzer']['extract_wb_property'] = [
@@ -1022,6 +1034,19 @@
                        'type' => 'limit',
                        'max_token_count' => 1
                ];
+
+               // Language analyzers for descriptions
+               $repo = WikibaseRepo::getDefaultInstance();
+               $wbBuilder = new ConfigBuilder( 
$repo->getTermsLanguages()->getLanguages(),
+                       $repo->getSettings()->getSetting( 'entitySearch' ),
+                       $builder
+               );
+               $inHook = true;
+               try {
+                       $wbBuilder->buildConfig( $config );
+               } finally {
+                       $inHook = false;
+               }
        }
 
        /**
diff --git a/extensions/Wikibase/repo/autoload.php 
b/extensions/Wikibase/repo/autoload.php
index 3b1f6c4..302dc44 100644
--- a/extensions/Wikibase/repo/autoload.php
+++ b/extensions/Wikibase/repo/autoload.php
@@ -253,6 +253,7 @@
        'Wikibase\\Repo\\PropertyDataTypeChanger' => __DIR__ . 
'/includes/PropertyDataTypeChanger.php',
        'Wikibase\\Repo\\Rdf\\Values\\GeoShapeRdfBuilder' => __DIR__ . 
'/includes/Rdf/Values/GeoShapeRdfBuilder.php',
        'Wikibase\\Repo\\Rdf\\Values\\TabularDataRdfBuilder' => __DIR__ . 
'/includes/Rdf/Values/TabularDataRdfBuilder.php',
+       'Wikibase\\Repo\\Search\\Elastic\\ConfigBuilder' => __DIR__ . 
'/includes/Search/Elastic/ConfigBuilder.php',
        'Wikibase\\Repo\\Search\\Elastic\\ElasticTermResult' => __DIR__ . 
'/includes/Search/Elastic/ElasticTermResult.php',
        'Wikibase\\Repo\\Search\\Elastic\\EntitySearchElastic' => __DIR__ . 
'/includes/Search/Elastic/EntitySearchElastic.php',
        'Wikibase\\Repo\\Search\\Elastic\\Fields\\AllLabelsField' => __DIR__ . 
'/includes/Search/Elastic/Fields/AllLabelsField.php',
@@ -355,6 +356,7 @@
        'Wikibase\\Repo\\Tests\\PermissionsHelper' => __DIR__ . 
'/tests/phpunit/includes/PermissionsHelper.php',
        'Wikibase\\Repo\\Tests\\Rdf\\NTriplesRdfTestHelper' => __DIR__ . 
'/tests/phpunit/includes/Rdf/NTriplesRdfTestHelper.php',
        'Wikibase\\Repo\\Tests\\Rdf\\RdfBuilderTestData' => __DIR__ . 
'/tests/phpunit/includes/Rdf/RdfBuilderTestData.php',
+       'Wikibase\\Repo\\Tests\\Search\\Elastic\\Fields\\SearchFieldTestCase' 
=> __DIR__ . 
'/tests/phpunit/includes/Search/Elastic/Fields/SearchFieldTestCase.php',
        
'Wikibase\\Repo\\Tests\\Search\\Elastic\\Fields\\WikibaseNumericFieldTest' => 
__DIR__ . 
'/tests/phpunit/includes/Search/Elastic/Fields/WikibaseNumericFieldTest.php',
        'Wikibase\\Repo\\Tests\\Specials\\HtmlAssertionHelpers' => __DIR__ . 
'/tests/phpunit/includes/Specials/HtmlAssertionHelpers.php',
        'Wikibase\\Repo\\Tests\\Specials\\SpecialModifyTermTestCase' => __DIR__ 
. '/tests/phpunit/includes/Specials/SpecialModifyTermTestCase.php',
diff --git a/extensions/Wikibase/repo/config/Wikibase.default.php 
b/extensions/Wikibase/repo/config/Wikibase.default.php
index a009366..4517aad 100644
--- a/extensions/Wikibase/repo/config/Wikibase.default.php
+++ b/extensions/Wikibase/repo/config/Wikibase.default.php
@@ -257,8 +257,14 @@
                'rescoreProfiles' => [],
                // Type (de)boosts for rescoring functions
                'statementBoost' => [],
+               // List of languages that we want to have stemming analyzers
+               // 'index' means we generate stemmed field on index
+               // 'query' means we use it on query
+               // See https://phabricator.wikimedia.org/T180169 for discussion.
+               'useStemming' => [],
        ],
 
        // List of properties to be indexed
-       'searchIndexProperties' => []
+       'searchIndexProperties' => [],
+
 ];
diff --git a/extensions/Wikibase/repo/i18n/ais.json 
b/extensions/Wikibase/repo/i18n/ais.json
index f696691..8a5ca20 100644
--- a/extensions/Wikibase/repo/i18n/ais.json
+++ b/extensions/Wikibase/repo/i18n/ais.json
@@ -64,7 +64,7 @@
        "wikibase-undo-title": "patiku \"$1\" a mikawaway-kalumyiti",
        "wikibase-restore-title": "patiku tu \"$1\" a malumanay a masumad nu 
ayaway",
        "wikibase-partial-undo": "liyad nu mikawaway-kalumyiti kapah patiku.",
-       "wikibase-omitted-undo-ops": "zayhan {{PLURAL:$1|sulyang}} masumad tu 
nu ayaway, $1 ce {{PLURAL:$1|misumad}} la’cus patiku.",
+       "wikibase-omitted-undo-ops": "zayhan{{PLURAL:$1|sulyang}} masumad tu nu 
ayaway, $1 {{PLURAL:$1|misumad}} la’cus patiku.",
        "wikibase-empty-undo": "itini inayi’ ku patiku a sumad.",
        "wikibase-undo-revision-error": "patiku mungangaw",
        "wikibase-undo-samerev": "apatiku mikawaway-kalumyiti kanca matuzu’ 
tusa caay kalecaday a sumad.",
diff --git a/extensions/Wikibase/repo/i18n/be-tarask.json 
b/extensions/Wikibase/repo/i18n/be-tarask.json
index e832840..d8559c5 100644
--- a/extensions/Wikibase/repo/i18n/be-tarask.json
+++ b/extensions/Wikibase/repo/i18n/be-tarask.json
@@ -145,6 +145,7 @@
        "wikibase-itembytitle-error-site": "Калі ласка, увядзіце існы 
ідэнтыфікатар сайту, напрыклад, «enwiki» для ангельскай Вікіпэдыі.",
        "wikibase-itembytitle-error-item": "Элемэнт, які спасылаецца на 
пададзеную старонку, ня знойдзены.",
        "wikibase-itembytitle-create": "Вы можаце таксама [$1 стварыць новы 
аб’ект].",
+       "wikibase-itembytitle-summary": "Special:ItemByTitle ужываецца, каб 
знайсьці адпаведны элемэнт для пададзенай старонкі на злучаным сайце.<br />У 
першае поле, «{{int:wikibase-itembytitle-lookup-site}}», вы ўводзіце коды мовы 
і сайту.<br />У другое поле, «{{int:wikibase-itembytitle-lookup-page}}», вы 
мусіце ўвесьці дакладную назву старонкі так, як яна выглядае на злучаным 
сайце.",
        "wikibase-gotolinkedpage-lookup-site": "Сайт:",
        "wikibase-gotolinkedpage-error-item-not-found": "Элемэнт ня знойдзены",
        "special-itemdisambiguation": "Неадназначнасьць аб’ектаў",
diff --git a/extensions/Wikibase/repo/i18n/ca.json 
b/extensions/Wikibase/repo/i18n/ca.json
index e1a85d1..ceb0a51 100644
--- a/extensions/Wikibase/repo/i18n/ca.json
+++ b/extensions/Wikibase/repo/i18n/ca.json
@@ -197,6 +197,7 @@
        "wikibase-itemmerge-cant-load-entity-content": "No s'ha pogut carregar 
l'element.",
        "wikibase-dispatchstats-lag-num": "Pendent",
        "special-listdatatypes": "Llista de tipus de dades disponibles",
+       "wikibase-listdatatypes-listproperties": "Llista de propietats amb 
aquest tipus de dades",
        "wikibase-history-title-with-label": "«$2» ($1): Historial de 
revisions",
        "wikibase-listproperties-datatype": "Tipus de dades:",
        "wikibase-listproperties-all": "Tots els tipus de dades",
diff --git a/extensions/Wikibase/repo/i18n/sat.json 
b/extensions/Wikibase/repo/i18n/sat.json
index b58a1ce..2264b61 100644
--- a/extensions/Wikibase/repo/i18n/sat.json
+++ b/extensions/Wikibase/repo/i18n/sat.json
@@ -10,6 +10,7 @@
        "wikibase-add": "Joṛao",
        "wikibase-label-empty": "Jahan lebel Bạnuḱa",
        "wikibase-description-empty": "Jahan jạṛ baṅ joṅṛao akana",
+       "wikibase-sitelink-site-edit-placeholder": "ᱣᱤᱠᱤ",
        "wikibase-sitelinks-special": "Eṭaḱ siteko",
        "wikibase-statementview-rank-normal": "ᱥᱟᱫᱷᱟᱨᱚᱱ ᱨᱮᱸᱠ"
 }
diff --git a/extensions/Wikibase/repo/includes/Search/Elastic/ConfigBuilder.php 
b/extensions/Wikibase/repo/includes/Search/Elastic/ConfigBuilder.php
new file mode 100644
index 0000000..3fbb733
--- /dev/null
+++ b/extensions/Wikibase/repo/includes/Search/Elastic/ConfigBuilder.php
@@ -0,0 +1,185 @@
+<?php
+namespace Wikibase\Repo\Search\Elastic;
+
+use CirrusSearch\Maintenance\AnalysisConfigBuilder;
+
+/**
+ * Utility class to build analyzer configs for ElasticSearch
+ * @package Wikibase\Repo\Search\Elastic
+ */
+class ConfigBuilder {
+
+       /**
+        * @var AnalysisConfigBuilder
+        */
+       private $builder;
+       /**
+        * @var string[]
+        */
+       private $languageList;
+       /**
+        * @var array
+        */
+       private $searchSettings;
+
+       /**
+        * @param string[] $languageList
+        * @param array $searchSettings
+        * @param AnalysisConfigBuilder $builder
+        */
+       public function __construct( array $languageList, array 
$searchSettings, AnalysisConfigBuilder $builder ) {
+               $this->builder = $builder;
+               $this->languageList = $languageList;
+               $this->searchSettings = $searchSettings;
+       }
+
+       /**
+        * Replace certain filter name in all configs with different name.
+        * @param array[] $config Configuration being processed
+        * @param string $oldName
+        * @param string $newName
+        */
+       private function replaceFilter( array &$config, $oldName, $newName ) {
+               foreach ( $config['analyzer'] as &$analyzer ) {
+                       if ( !isset( $analyzer['filter'] ) ) {
+                               continue;
+                       }
+                       $analyzer['filter'] = array_map( function ( $filter ) 
use ( $oldName, $newName ) {
+                               if ( $filter === $oldName ) {
+                                       return $newName;
+                               }
+                               return $filter;
+                       }, $analyzer['filter'] );
+               }
+       }
+
+       /**
+        * Check every filter in the config - if it's the same as in old config,
+        * ignore it. If it has the same name, but different content - create 
new filter
+        * with different name by prefixing it with language name.
+        *
+        * @param array[] $config Configuration being processed
+        * @param array[] $standardFilters Existing filters list
+        * @param array[] $defaultFilters List of default filters already 
mentioned in the config
+        * @param string $prefix Prefix for disambiguation
+        * @return array[] The list of filters not in the old config.
+        */
+       private function resolveFilters( array &$config, array 
$standardFilters, array $defaultFilters, $prefix ) {
+               $resultFilters = [];
+               foreach ( $config['filter'] as $name => $filter ) {
+                       $existingFilter = null;
+                       if ( isset( $standardFilters[$name] ) ) {
+                               $existingFilter = $standardFilters[$name];
+                       } elseif ( isset( $defaultFilters[$name] ) ) {
+                               $existingFilter = $defaultFilters[$name];
+                       }
+
+                       if ( $existingFilter ) { // Filter with this name 
already exists
+                               if ( $existingFilter != $filter ) {
+                                       // filter with the same name but 
different config - need to
+                                       // rename by adding prefix
+                                       $newName = $prefix . '_' . $name;
+                                       $this->replaceFilter( $config, $name, 
$newName );
+                                       $resultFilters[$newName] = $filter;
+                               }
+                       } else {
+                               $resultFilters[$name] = $filter;
+                       }
+               }
+               return $resultFilters;
+       }
+
+       /**
+        * Merge per-language config into the main config.
+        * It will copy specific analyzer and all dependant filters and 
char_filters.
+        * @param array $config Main config
+        * @param array $langConfig Per-language config
+        * @param string $name Name for analyzer whose config we're merging
+        * @param string $prefix Prefix for this configuration
+        */
+       private function mergeConfig( array &$config, array $langConfig, $name, 
$prefix ) {
+               $analyzer = $langConfig['analyzer'][$name];
+               $config['analyzer'][$prefix . '_' . $name] = $analyzer;
+               if ( !empty( $analyzer['filter'] ) ) {
+                       // Add private filters for this analyzer
+                       foreach ( $analyzer['filter'] as $filter ) {
+                               // Copy filters that are in language config but 
not in the main config.
+                               // We would not copy the same filter into the 
main config since due to
+                               // the resolution step we know they are the 
same (otherwise we would have
+                               // renamed it).
+                               if ( isset( $langConfig['filter'][$filter] ) &&
+                                       !isset( $config['filter'][$filter] ) ) {
+                                       $config['filter'][$filter] = 
$langConfig['filter'][$filter];
+                               }
+                       }
+               }
+               if ( !empty( $analyzer['char_filter'] ) ) {
+                       // Add private char_filters for this analyzer
+                       foreach ( $analyzer['char_filter'] as $filter ) {
+                               // Here unlike above we do not check for 
$langConfig since we assume
+                               // language config is not broken and all char 
filters are namespaced
+                               // nicely, so if the filter is mentioned in 
analyzer it is also defined.
+                               if ( !isset( $config['char_filter'][$filter] ) 
) {
+                                       $config['char_filter'][$filter] = 
$langConfig['char_filter'][$filter];
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Get list of filters that are mentioned in analyzers but not defined
+        * explicitly.
+        * @param array[] $config Full configuration array
+        * @return array List of default filters, each containing only filter 
type
+        */
+       private function getDefaultFilters( array &$config ) {
+               $defaultFilters = [];
+               foreach ( [ 'plain', 'plain_search', 'text', 'text_search' ] as 
$analyzer ) {
+                       if ( empty( $config['analyzer'][$analyzer]['filter'] ) 
) {
+                               continue;
+                       }
+                       foreach ( $config['analyzer'][$analyzer]['filter'] as 
$filterName ) {
+                               if ( !isset( $config['filter'][$filterName] ) ) 
{
+                                       // This is default definition for the 
built-in filter
+                                       $defaultFilters[$filterName] = [ 'type' 
=> $filterName ];
+                               }
+                       }
+               }
+               return $defaultFilters;
+       }
+
+       /**
+        * Build a new all-language analyzer configuration.
+        * This adds analyzers, filters, etc. which are required for 
language-specific
+        * indexing of Wikidata fields.
+        * @param array[] $config Existing config which will be modified with 
new analyzers
+        */
+       public function buildConfig( array &$config ) {
+               $defaultFilters = $this->getDefaultFilters( $config );
+               foreach ( $this->languageList as $lang ) {
+                       $langConfig = $this->builder->buildConfig( $lang );
+                       $defaultFilters += $this->getDefaultFilters( 
$langConfig );
+               }
+               foreach ( $this->languageList as $lang ) {
+                       $langConfig = $this->builder->buildConfig( $lang );
+                       // Analyzer is: tokenizer + filter + char_filter
+                       // Tokenizers don't seem to be subject to customization 
now
+                       // Char filters are nicely namespaced
+                       // Filters are NOT - e.g. lowercase & icu_folding 
filters are different for different
+                       // languages! So we need to do some disambiguation here.
+                       $langConfig['filter'] = $this->resolveFilters( 
$langConfig, $config['filter'], $defaultFilters, $lang );
+                       // Merge configs
+                       // Used analyzers: plain, plain_search, text, 
text_search,
+                       foreach ( [ 'plain', 'plain_search' ] as $analyzer ) {
+                               $this->mergeConfig( $config, $langConfig, 
$analyzer, $lang );
+                       }
+                       if ( !empty( 
$this->searchSettings['useStemming'][$lang]['index'] ) ) {
+                               // only set up custom analyzers for "text" ones 
for stemmed languages
+                               foreach ( [ 'text', 'text_search' ] as 
$analyzer ) {
+                                       $this->mergeConfig( $config, 
$langConfig, $analyzer, $lang );
+                               }
+                       }
+               }
+       }
+
+}
diff --git 
a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsField.php 
b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsField.php
index 2526901..40c6217 100644
--- 
a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsField.php
+++ 
b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsField.php
@@ -13,30 +13,60 @@
  * @license GPL-2.0+
  * @author Stas Malyshev
  */
-class DescriptionsField implements WikibaseIndexField {
+class DescriptionsField extends TermIndexField {
 
        /**
         * List of available languages
         * @var string[]
         */
        private $languages;
+       /**
+        * @var array
+        */
+       private $searchSettings;
 
        /**
         * @param string[] $languages Available languages list.
+        * @param array $searchSettings Search config
         */
-       public function __construct( array $languages ) {
+       public function __construct( array $languages, array $searchSettings ) {
                $this->languages = $languages;
+               parent::__construct( "description", 
\SearchIndexField::INDEX_TYPE_NESTED );
+               $this->searchSettings = $searchSettings;
        }
 
        /**
         * @param SearchEngine $engine
-        * @param string $name
-        * @return null|\SearchIndexField
+        * @return null|array
         */
-       public function getMappingField( SearchEngine $engine, $name ) {
-               // TODO: no mapping for now, since we're only storing it for 
retrieval
-               // When we start indexing it, we'll need to figure out how to 
add proper analyzers
-               return null;
+       public function getMapping( SearchEngine $engine ) {
+               // Since we need a specially tuned field, we can not use
+               // standard search engine types.
+               if ( !( $engine instanceof CirrusSearch ) ) {
+                       // For now only Cirrus/Elastic is supported
+                       return [];
+               }
+
+               $config = [
+                       'type' => 'object',
+                       'properties' => []
+               ];
+               foreach ( $this->languages as $language ) {
+                       // TODO: here we probably will need better 
language-specific analyzers
+                       if ( empty( 
$this->searchSettings['useStemming'][$language]['index'] ) ) {
+                               $langConfig = [ 'type' => 'text', 'index' => 
'no' ];
+                       } else {
+                               $langConfig = $this->getTokenizedSubfield( 
$engine->getConfig(),
+                                       $language . '_text',
+                                       $language . '_text_search'
+                               );
+                       }
+                       $langConfig['fields']['plain'] = 
$this->getTokenizedSubfield( $engine->getConfig(), $language . '_plain',
+                                       $language . '_plain_search' );
+                       $config['properties'][$language] = $langConfig;
+               }
+
+               return $config;
        }
 
        /**
@@ -55,6 +85,13 @@
                return $data;
        }
 
+       /**
+        * Set engine hints.
+        * Specifically, sets noop hint so that descriptions would be compared
+        * as arrays and removal of description would be processed correctly.
+        * @param SearchEngine $engine
+        * @return array
+        */
        public function getEngineHints( SearchEngine $engine ) {
                if ( !( $engine instanceof CirrusSearch ) ) {
                        // For now only Cirrus/Elastic is supported
diff --git 
a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsProviderFieldDefinitions.php
 
b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsProviderFieldDefinitions.php
index bd3c204..8dd8a96 100644
--- 
a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsProviderFieldDefinitions.php
+++ 
b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/DescriptionsProviderFieldDefinitions.php
@@ -14,12 +14,18 @@
         * @var string[]
         */
        private $languageCodes;
+       /**
+        * @var array
+        */
+       private $searchSettings;
 
        /**
         * @param string[] $languageCodes
+        * @param array $searchSettings
         */
-       public function __construct( array $languageCodes ) {
+       public function __construct( array $languageCodes, array 
$searchSettings ) {
                $this->languageCodes = $languageCodes;
+               $this->searchSettings = $searchSettings;
        }
 
        /**
@@ -27,7 +33,7 @@
         */
        public function getFields() {
                return [
-                       'descriptions' => new DescriptionsField( 
$this->languageCodes ),
+                       'descriptions' => new DescriptionsField( 
$this->languageCodes, $this->searchSettings ),
                ];
        }
 
diff --git 
a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/LabelsField.php 
b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/LabelsField.php
index 808cb84..b48c45d 100644
--- a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/LabelsField.php
+++ b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/LabelsField.php
@@ -21,9 +21,13 @@
         */
        private $languages;
 
+       /**
+        * LabelsField constructor.
+        * @param string[] $languages
+        */
        public function __construct( $languages ) {
                $this->languages = $languages;
-               parent::__construct( "", \SearchIndexField::INDEX_TYPE_NESTED );
+               parent::__construct( "labels", 
\SearchIndexField::INDEX_TYPE_NESTED );
        }
 
        /**
@@ -50,6 +54,11 @@
                        $langConfig['fields']['near_match_folded'] =
                                $this->getSubfield( 'near_match_asciifolding' );
                        $langConfig['fields']['near_match'] = 
$this->getSubfield( 'near_match' );
+                       // This one is for full-text search, will tokenize
+                       // TODO: here we probably will need better 
language-specific analyzers
+                       $langConfig['fields']['plain'] = 
$this->getTokenizedSubfield( $engine->getConfig(),
+                               $language . '_plain', $language . 
'_plain_search' );
+                       // All labels are copies to labels_all
                        $langConfig['copy_to'] = 'labels_all';
 
                        $config['properties'][$language] = $langConfig;
@@ -85,6 +94,13 @@
                return $data;
        }
 
+       /**
+        * Set engine hints.
+        * Specifically, sets noop hint so that labels would be compared
+        * as arrays and removal of labels would be processed correctly.
+        * @param SearchEngine $engine
+        * @return array
+        */
        public function getEngineHints( SearchEngine $engine ) {
                if ( !( $engine instanceof CirrusSearch ) ) {
                        // For now only Cirrus/Elastic is supported
diff --git 
a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/TermIndexField.php 
b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/TermIndexField.php
index a6e7879..ab177c0 100644
--- a/extensions/Wikibase/repo/includes/Search/Elastic/Fields/TermIndexField.php
+++ b/extensions/Wikibase/repo/includes/Search/Elastic/Fields/TermIndexField.php
@@ -3,6 +3,8 @@
 namespace Wikibase\Repo\Search\Elastic\Fields;
 
 use CirrusSearch;
+use CirrusSearch\Search\TextIndexField;
+use CirrusSearch\SearchConfig;
 use SearchEngine;
 use SearchIndexField;
 use SearchIndexFieldDefinition;
@@ -50,6 +52,29 @@
        }
 
        /**
+        * Create a tokenized string field config with specific analyzer fields.
+        *
+        * @param SearchConfig $config
+        * @param string $analyzer
+        * @param string $search_analyzer
+        * @return array
+        */
+       protected function getTokenizedSubfield( SearchConfig $config, 
$analyzer, $search_analyzer = null ) {
+               $field = [
+                       'type' => 'text',
+                       'analyzer' => $analyzer,
+                       'position_increment_gap' => 
TextIndexField::POSITION_INCREMENT_GAP,
+                       'similarity' => TextIndexField::getSimilarity( $config, 
$this->name, $analyzer ),
+               ];
+
+               if ( $search_analyzer ) {
+                       $field['search_analyzer'] = $search_analyzer;
+               }
+
+               return $field;
+       }
+
+       /**
         * Merge two field definitions if possible.
         *
         * @param SearchIndexField $that
diff --git a/extensions/Wikibase/repo/includes/WikibaseRepo.php 
b/extensions/Wikibase/repo/includes/WikibaseRepo.php
index 5ea20fb..969bb71 100644
--- a/extensions/Wikibase/repo/includes/WikibaseRepo.php
+++ b/extensions/Wikibase/repo/includes/WikibaseRepo.php
@@ -1475,8 +1475,10 @@
         * @return FieldDefinitions
         */
        public function getDescriptionProviderDefinitions() {
-               return new DescriptionsProviderFieldDefinitions( 
$this->getTermsLanguages()
-                       ->getLanguages() );
+               return new DescriptionsProviderFieldDefinitions(
+                       $this->getTermsLanguages()->getLanguages(),
+                       $this->getSettings()->getSetting( 'entitySearch' )
+               );
        }
 
        /**
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/data/analyzer/en-ru-es-de-zh.expected 
b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/en-ru-es-de-zh.expected
new file mode 100644
index 0000000..edaaecf
--- /dev/null
+++ 
b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/en-ru-es-de-zh.expected
@@ -0,0 +1,355 @@
+{
+    "analyzer": {
+        "en_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer",
+                "preserve_original_recorder",
+                "icu_folding",
+                "preserve_original"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "en_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "en_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "char_filter": [
+                "word_break_helper",
+                "kana_map"
+            ],
+            "filter": [
+                "aggressive_splitting",
+                "possessive_english",
+                "icu_normalizer",
+                "stop",
+                "icu_folding",
+                "kstem",
+                "custom_stem"
+            ]
+        },
+        "en_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "char_filter": [
+                "word_break_helper",
+                "kana_map"
+            ],
+            "filter": [
+                "aggressive_splitting",
+                "possessive_english",
+                "icu_normalizer",
+                "stop",
+                "icu_folding",
+                "kstem",
+                "custom_stem"
+            ]
+        },
+        "ru_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper",
+                "russian_charfilter"
+            ]
+        },
+        "ru_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper",
+                "russian_charfilter"
+            ]
+        },
+        "ru_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "char_filter": [
+                "russian_charfilter"
+            ],
+            "filter": [
+                "icu_normalizer",
+                "russian_stop",
+                "russian_stemmer"
+            ]
+        },
+        "ru_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "char_filter": [
+                "russian_charfilter"
+            ],
+            "filter": [
+                "icu_normalizer",
+                "russian_stop",
+                "russian_stemmer"
+            ]
+        },
+        "es_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "es_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "de_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "de_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "zh_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "zh_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "zh_text": {
+            "type": "custom",
+            "tokenizer": "smartcn_tokenizer",
+            "char_filter": [
+                "stconvertfix",
+                "tsconvert"
+            ],
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ]
+        },
+        "zh_text_search": {
+            "type": "custom",
+            "tokenizer": "smartcn_tokenizer",
+            "char_filter": [
+                "stconvertfix",
+                "tsconvert"
+            ],
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ]
+        }
+    },
+    "filter": {
+        "icu_normalizer": {
+            "type": "icu_normalizer",
+            "name": "nfkc_cf"
+        },
+        "icu_folding": {
+            "type": "icu_folding"
+        },
+        "aggressive_splitting": {
+            "type": "word_delimiter",
+            "stem_english_possessive": false,
+            "preserve_original": false
+        },
+        "possessive_english": {
+            "type": "stemmer",
+            "language": "possessive_english"
+        },
+        "custom_stem": {
+            "type": "stemmer_override",
+            "rules": "guidelines => guideline"
+        },
+        "russian_stop": {
+            "type": "stop",
+            "stopwords": "_russian_"
+        },
+        "russian_stemmer": {
+            "type": "stemmer",
+            "language": "russian"
+        },
+        "smartcn_stop": {
+            "type": "stop",
+            "stopwords": [
+                ","
+            ]
+        }
+    },
+    "char_filter": {
+        "word_break_helper": {
+            "type": "mapping",
+            "mappings": [
+                "_=>\\u0020",
+                ".=>\\u0020",
+                "(=>\\u0020",
+                ")=>\\u0020"
+            ]
+        },
+        "kana_map": {
+            "type": "mapping",
+            "mappings": [
+                "\\u3041=>\\u30a1",
+                "\\u3042=>\\u30a2",
+                "\\u3043=>\\u30a3",
+                "\\u3044=>\\u30a4",
+                "\\u3045=>\\u30a5",
+                "\\u3046=>\\u30a6",
+                "\\u3094=>\\u30f4",
+                "\\u3047=>\\u30a7",
+                "\\u3048=>\\u30a8",
+                "\\u3049=>\\u30a9",
+                "\\u304a=>\\u30aa",
+                "\\u3095=>\\u30f5",
+                "\\u304b=>\\u30ab",
+                "\\u304c=>\\u30ac",
+                "\\u304d=>\\u30ad",
+                "\\u304e=>\\u30ae",
+                "\\u304f=>\\u30af",
+                "\\u3050=>\\u30b0",
+                "\\u3096=>\\u30f6",
+                "\\u3051=>\\u30b1",
+                "\\u3052=>\\u30b2",
+                "\\u3053=>\\u30b3",
+                "\\u3054=>\\u30b4",
+                "\\u3055=>\\u30b5",
+                "\\u3056=>\\u30b6",
+                "\\u3057=>\\u30b7",
+                "\\u3058=>\\u30b8",
+                "\\u3059=>\\u30b9",
+                "\\u305a=>\\u30ba",
+                "\\u305b=>\\u30bb",
+                "\\u305c=>\\u30bc",
+                "\\u305d=>\\u30bd",
+                "\\u305e=>\\u30be",
+                "\\u305f=>\\u30bf",
+                "\\u3060=>\\u30c0",
+                "\\u3061=>\\u30c1",
+                "\\u3062=>\\u30c2",
+                "\\u3063=>\\u30c3",
+                "\\u3064=>\\u30c4",
+                "\\u3065=>\\u30c5",
+                "\\u3066=>\\u30c6",
+                "\\u3067=>\\u30c7",
+                "\\u3068=>\\u30c8",
+                "\\u3069=>\\u30c9",
+                "\\u306a=>\\u30ca",
+                "\\u306b=>\\u30cb",
+                "\\u306c=>\\u30cc",
+                "\\u306d=>\\u30cd",
+                "\\u306e=>\\u30ce",
+                "\\u306f=>\\u30cf",
+                "\\u3070=>\\u30d0",
+                "\\u3071=>\\u30d1",
+                "\\u3072=>\\u30d2",
+                "\\u3073=>\\u30d3",
+                "\\u3074=>\\u30d4",
+                "\\u3075=>\\u30d5",
+                "\\u3076=>\\u30d6",
+                "\\u3077=>\\u30d7",
+                "\\u3078=>\\u30d8",
+                "\\u3079=>\\u30d9",
+                "\\u307a=>\\u30da",
+                "\\u307b=>\\u30db",
+                "\\u307c=>\\u30dc",
+                "\\u307d=>\\u30dd",
+                "\\u307e=>\\u30de",
+                "\\u307f=>\\u30df",
+                "\\u3080=>\\u30e0",
+                "\\u3081=>\\u30e1",
+                "\\u3082=>\\u30e2",
+                "\\u3083=>\\u30e3",
+                "\\u3084=>\\u30e4",
+                "\\u3085=>\\u30e5",
+                "\\u3086=>\\u30e6",
+                "\\u3087=>\\u30e7",
+                "\\u3088=>\\u30e8",
+                "\\u3089=>\\u30e9",
+                "\\u308a=>\\u30ea",
+                "\\u308b=>\\u30eb",
+                "\\u308c=>\\u30ec",
+                "\\u308d=>\\u30ed",
+                "\\u308e=>\\u30ee",
+                "\\u308f=>\\u30ef",
+                "\\u3090=>\\u30f0",
+                "\\u3091=>\\u30f1",
+                "\\u3092=>\\u30f2",
+                "\\u3093=>\\u30f3"
+            ]
+        },
+        "russian_charfilter": {
+            "type": "mapping",
+            "mappings": [
+                "\\u0301=>",
+                "\\u0130=>I",
+                "\\u0435\\u0308=>\\u0435",
+                "\\u0415\\u0308=>\\u0415",
+                "\\u0451=>\\u0435",
+                "\\u0401=>\\u0415"
+            ]
+        },
+        "stconvertfix": {
+            "type": "mapping",
+            "mappings": [
+                "\\u606d\\u5f18=>\\u606d \\u5f18",
+                "\\u5138=>\\u3469"
+            ]
+        },
+        "tsconvert": {
+            "type": "stconvert",
+            "delimiter": "#",
+            "keep_both": false,
+            "convert_type": "t2s"
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-nolang.expected 
b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-nolang.expected
new file mode 100644
index 0000000..0935ec7
--- /dev/null
+++ b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-nolang.expected
@@ -0,0 +1,95 @@
+{
+    "analyzer": {
+        "he_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer",
+                "preserve_original_recorder",
+                "icu_folding",
+                "preserve_original"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "he_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "he_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ]
+        },
+        "he_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ]
+        },
+        "uk_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ]
+        },
+        "uk_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ]
+        }
+    },
+    "filter": {
+        "icu_normalizer": {
+            "type": "icu_normalizer",
+            "name": "nfkc_cf"
+        },
+        "icu_folding": {
+            "type": "icu_folding"
+        }
+    },
+    "char_filter": {
+        "word_break_helper": {
+            "type": "mapping",
+            "mappings": [
+                "_=>\\u0020",
+                ".=>\\u0020",
+                "(=>\\u0020",
+                ")=>\\u0020"
+            ]
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-noplug.expected 
b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-noplug.expected
new file mode 100644
index 0000000..af0c051
--- /dev/null
+++ b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk-noplug.expected
@@ -0,0 +1,88 @@
+{
+    "analyzer": {
+        "he_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "he_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "he_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ]
+        },
+        "he_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ]
+        },
+        "uk_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ]
+        },
+        "uk_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "lowercase"
+            ]
+        }
+    },
+    "filter": {
+        "lowercase": {
+            "type": "lowercase"
+        }
+    },
+    "char_filter": {
+        "word_break_helper": {
+            "type": "mapping",
+            "mappings": [
+                "_=>\\u0020",
+                ".=>\\u0020",
+                "(=>\\u0020",
+                ")=>\\u0020"
+            ]
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk.expected 
b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk.expected
new file mode 100644
index 0000000..d419d4d
--- /dev/null
+++ b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/he-uk.expected
@@ -0,0 +1,99 @@
+{
+    "analyzer": {
+        "he_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer",
+                "preserve_original_recorder",
+                "icu_folding",
+                "preserve_original"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "he_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "he_text": {
+            "type": "custom",
+            "tokenizer": "hebrew",
+            "filter": [
+                "niqqud",
+                "hebrew_lemmatizer",
+                "icu_normalizer",
+                "icu_folding"
+            ]
+        },
+        "he_text_search": {
+            "type": "custom",
+            "tokenizer": "hebrew",
+            "filter": [
+                "niqqud",
+                "hebrew_lemmatizer",
+                "icu_normalizer",
+                "icu_folding"
+            ]
+        },
+        "uk_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_text": {
+            "type": "ukrainian",
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "uk_text_search": {
+            "type": "ukrainian",
+            "char_filter": [
+                "word_break_helper"
+            ]
+        }
+    },
+    "filter": {
+        "icu_normalizer": {
+            "type": "icu_normalizer",
+            "name": "nfkc_cf"
+        },
+        "icu_folding": {
+            "type": "icu_folding"
+        }
+    },
+    "char_filter": {
+        "word_break_helper": {
+            "type": "mapping",
+            "mappings": [
+                "_=>\\u0020",
+                ".=>\\u0020",
+                "(=>\\u0020",
+                ")=>\\u0020"
+            ]
+        }
+    }
+}
\ No newline at end of file
diff --git a/extensions/Wikibase/repo/tests/phpunit/data/analyzer/sv.expected 
b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/sv.expected
new file mode 100644
index 0000000..ff1cf79
--- /dev/null
+++ b/extensions/Wikibase/repo/tests/phpunit/data/analyzer/sv.expected
@@ -0,0 +1,277 @@
+{
+    "analyzer": {
+        "en_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer",
+                "preserve_original_recorder",
+                "icu_folding",
+                "preserve_original"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "en_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "en_text": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "char_filter": [
+                "word_break_helper",
+                "kana_map"
+            ],
+            "filter": [
+                "aggressive_splitting",
+                "possessive_english",
+                "icu_normalizer",
+                "stop",
+                "icu_folding",
+                "kstem",
+                "custom_stem"
+            ]
+        },
+        "en_text_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "char_filter": [
+                "word_break_helper",
+                "kana_map"
+            ],
+            "filter": [
+                "aggressive_splitting",
+                "possessive_english",
+                "icu_normalizer",
+                "stop",
+                "icu_folding",
+                "kstem",
+                "custom_stem"
+            ]
+        },
+        "zh_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "zh_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "zh_text": {
+            "type": "custom",
+            "tokenizer": "smartcn_tokenizer",
+            "char_filter": [
+                "stconvertfix",
+                "tsconvert"
+            ],
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ]
+        },
+        "zh_text_search": {
+            "type": "custom",
+            "tokenizer": "smartcn_tokenizer",
+            "char_filter": [
+                "stconvertfix",
+                "tsconvert"
+            ],
+            "filter": [
+                "smartcn_stop",
+                "icu_normalizer"
+            ]
+        },
+        "sv_plain": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer",
+                "preserve_original_recorder",
+                "sv_icu_folding",
+                "preserve_original"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        },
+        "sv_plain_search": {
+            "type": "custom",
+            "tokenizer": "standard",
+            "filter": [
+                "icu_normalizer"
+            ],
+            "char_filter": [
+                "word_break_helper"
+            ]
+        }
+    },
+    "filter": {
+        "icu_normalizer": {
+            "type": "icu_normalizer",
+            "name": "nfkc_cf"
+        },
+        "icu_folding": {
+            "type": "icu_folding"
+        },
+        "aggressive_splitting": {
+            "type": "word_delimiter",
+            "stem_english_possessive": false,
+            "preserve_original": false
+        },
+        "possessive_english": {
+            "type": "stemmer",
+            "language": "possessive_english"
+        },
+        "custom_stem": {
+            "type": "stemmer_override",
+            "rules": "guidelines => guideline"
+        },
+        "smartcn_stop": {
+            "type": "stop",
+            "stopwords": [
+                ","
+            ]
+        },
+        "sv_icu_folding": {
+            "type": "icu_folding",
+            "unicodeSetFilter": "[^\u00e5\u00e4\u00f6\u00c5\u00c4\u00d6]"
+        }
+    },
+    "char_filter": {
+        "word_break_helper": {
+            "type": "mapping",
+            "mappings": [
+                "_=>\\u0020",
+                ".=>\\u0020",
+                "(=>\\u0020",
+                ")=>\\u0020"
+            ]
+        },
+        "kana_map": {
+            "type": "mapping",
+            "mappings": [
+                "\\u3041=>\\u30a1",
+                "\\u3042=>\\u30a2",
+                "\\u3043=>\\u30a3",
+                "\\u3044=>\\u30a4",
+                "\\u3045=>\\u30a5",
+                "\\u3046=>\\u30a6",
+                "\\u3094=>\\u30f4",
+                "\\u3047=>\\u30a7",
+                "\\u3048=>\\u30a8",
+                "\\u3049=>\\u30a9",
+                "\\u304a=>\\u30aa",
+                "\\u3095=>\\u30f5",
+                "\\u304b=>\\u30ab",
+                "\\u304c=>\\u30ac",
+                "\\u304d=>\\u30ad",
+                "\\u304e=>\\u30ae",
+                "\\u304f=>\\u30af",
+                "\\u3050=>\\u30b0",
+                "\\u3096=>\\u30f6",
+                "\\u3051=>\\u30b1",
+                "\\u3052=>\\u30b2",
+                "\\u3053=>\\u30b3",
+                "\\u3054=>\\u30b4",
+                "\\u3055=>\\u30b5",
+                "\\u3056=>\\u30b6",
+                "\\u3057=>\\u30b7",
+                "\\u3058=>\\u30b8",
+                "\\u3059=>\\u30b9",
+                "\\u305a=>\\u30ba",
+                "\\u305b=>\\u30bb",
+                "\\u305c=>\\u30bc",
+                "\\u305d=>\\u30bd",
+                "\\u305e=>\\u30be",
+                "\\u305f=>\\u30bf",
+                "\\u3060=>\\u30c0",
+                "\\u3061=>\\u30c1",
+                "\\u3062=>\\u30c2",
+                "\\u3063=>\\u30c3",
+                "\\u3064=>\\u30c4",
+                "\\u3065=>\\u30c5",
+                "\\u3066=>\\u30c6",
+                "\\u3067=>\\u30c7",
+                "\\u3068=>\\u30c8",
+                "\\u3069=>\\u30c9",
+                "\\u306a=>\\u30ca",
+                "\\u306b=>\\u30cb",
+                "\\u306c=>\\u30cc",
+                "\\u306d=>\\u30cd",
+                "\\u306e=>\\u30ce",
+                "\\u306f=>\\u30cf",
+                "\\u3070=>\\u30d0",
+                "\\u3071=>\\u30d1",
+                "\\u3072=>\\u30d2",
+                "\\u3073=>\\u30d3",
+                "\\u3074=>\\u30d4",
+                "\\u3075=>\\u30d5",
+                "\\u3076=>\\u30d6",
+                "\\u3077=>\\u30d7",
+                "\\u3078=>\\u30d8",
+                "\\u3079=>\\u30d9",
+                "\\u307a=>\\u30da",
+                "\\u307b=>\\u30db",
+                "\\u307c=>\\u30dc",
+                "\\u307d=>\\u30dd",
+                "\\u307e=>\\u30de",
+                "\\u307f=>\\u30df",
+                "\\u3080=>\\u30e0",
+                "\\u3081=>\\u30e1",
+                "\\u3082=>\\u30e2",
+                "\\u3083=>\\u30e3",
+                "\\u3084=>\\u30e4",
+                "\\u3085=>\\u30e5",
+                "\\u3086=>\\u30e6",
+                "\\u3087=>\\u30e7",
+                "\\u3088=>\\u30e8",
+                "\\u3089=>\\u30e9",
+                "\\u308a=>\\u30ea",
+                "\\u308b=>\\u30eb",
+                "\\u308c=>\\u30ec",
+                "\\u308d=>\\u30ed",
+                "\\u308e=>\\u30ee",
+                "\\u308f=>\\u30ef",
+                "\\u3090=>\\u30f0",
+                "\\u3091=>\\u30f1",
+                "\\u3092=>\\u30f2",
+                "\\u3093=>\\u30f3"
+            ]
+        },
+        "stconvertfix": {
+            "type": "mapping",
+            "mappings": [
+                "\\u606d\\u5f18=>\\u606d \\u5f18",
+                "\\u5138=>\\u3469"
+            ]
+        },
+        "tsconvert": {
+            "type": "stconvert",
+            "delimiter": "#",
+            "keep_both": false,
+            "convert_type": "t2s"
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/AnalysisConfigBuilderTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/AnalysisConfigBuilderTest.php
new file mode 100644
index 0000000..64e107f
--- /dev/null
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/AnalysisConfigBuilderTest.php
@@ -0,0 +1,114 @@
+<?php
+namespace Wikibase\Repo\Search\Elastic\Tests;
+
+use CirrusSearch;
+use CirrusSearch\HashSearchConfig;
+use CirrusSearch\Maintenance\AnalysisConfigBuilder;
+use MediaWikiTestCase;
+use Wikibase\Repo\Search\Elastic\ConfigBuilder;
+
+/**
+ * @group Wikibase
+ * @covers \Wikibase\Repo\Search\Elastic\ConfigBuilder
+ * FIXME: this test depends on internal configs of 
CirrusSearch\Maintenance\AnalysisConfigBuilder
+ * This is not an ideal situation, but I am not sure how to fix it without 
making it more hacky.
+ */
+class AnalysisConfigBuilderTest extends MediaWikiTestCase {
+
+       public function setUp() {
+               parent::setUp();
+
+               if ( !class_exists( CirrusSearch::class ) ) {
+                       $this->markTestSkipped( 'CirrusSearch needed.' );
+               }
+       }
+
+       public function configDataProvider() {
+               $emptyConfig = [
+                       'analyzer' => [],
+                       'filter' => [],
+                       'char_filter' => []
+               ];
+               $allPlugins = [
+                       'extra',
+                       'analysis-icu',
+                       'analysis-stempel',
+                       'analysis-kuromoji',
+                       'analysis-smartcn',
+                       'analysis-hebrew',
+                       'analysis-ukrainian',
+                       'analysis-stconvert'
+               ];
+
+               return [
+                       "some languages" => [
+                               [ 'en', 'ru', 'es', 'de', 'zh' ],
+                               $emptyConfig,
+                               $allPlugins,
+                               'en-ru-es-de-zh',
+                       ],
+                       // sv has custom icu_folding filter
+                       "sv" => [
+                               [ 'en', 'zh', 'sv' ],
+                               $emptyConfig,
+                               $allPlugins,
+                               'sv',
+                       ],
+                       "with plugins" => [
+                               [ 'he', 'uk' ],
+                               $emptyConfig,
+                               $allPlugins,
+                               'he-uk',
+                       ],
+                       "without language plugins" => [
+                               [ 'he', 'uk' ],
+                               $emptyConfig,
+                               [ 'extra', 'analysis-icu' ],
+                               'he-uk-nolang',
+                       ],
+                       "without any plugins" => [
+                               [ 'he', 'uk' ],
+                               $emptyConfig,
+                               [],
+                               'he-uk-noplug',
+                       ],
+               ];
+       }
+
+       /**
+        * @param string[] $languages
+        * @param array $oldConfig
+        * @param string[] $plugins
+        * @param string $expectedConfig Filename with expected config
+        * @dataProvider configDataProvider
+        */
+       public function testAnalysisConfig( $languages, $oldConfig, $plugins, 
$expectedConfig ) {
+               // We use these static settings because we rely on tests in main
+               // AnalysisConfigBuilderTest to handle variations
+               $config = new HashSearchConfig( [ 'CirrusSearchUseIcuFolding' 
=> 'default' ] );
+
+               $langSettings = [];
+               $langSettings['useStemming'] = [
+                       'en' => [ 'index' => true, 'query' => true ],
+                       'ru' => [ 'index' => true, 'query' => true ],
+                       'uk' => [ 'index' => true, 'query' => true ],
+                       'he' => [ 'index' => true, 'query' => false ],
+                       'zh' => [ 'index' => true, 'query' => false ],
+               ];
+
+               $upstreamBuilder = new AnalysisConfigBuilder( 'dummy', 
$plugins, $config );
+               $builder = new ConfigBuilder( $languages, $langSettings, 
$upstreamBuilder );
+
+               $builder->buildConfig( $oldConfig );
+
+               $expectedFile = __DIR__ . 
"/../../../data/analyzer/$expectedConfig.expected";
+               if ( is_file( $expectedFile ) ) {
+                       $expected = json_decode( file_get_contents( 
$expectedFile ), true );
+                       $this->assertEquals( $expected, $oldConfig );
+               } else {
+                       file_put_contents( $expectedFile, json_encode( 
$oldConfig, JSON_PRETTY_PRINT ) );
+                       $this->markTestSkipped( "Generated new fixture" );
+               }
+       }
+
+}
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/AllLabelsFieldTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/AllLabelsFieldTest.php
index cefce8b..a48c761 100644
--- 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/AllLabelsFieldTest.php
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/AllLabelsFieldTest.php
@@ -11,7 +11,7 @@
 use Wikibase\Repo\Search\Elastic\Fields\AllLabelsField;
 
 /**
- * @covers Wikibase\Repo\Search\Elastic\Fields\AllLabelsField
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\AllLabelsField
  *
  * @group WikibaseElastic
  * @group Wikibase
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionFieldTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionFieldTest.php
new file mode 100644
index 0000000..c09f00b
--- /dev/null
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionFieldTest.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace Wikibase\Repo\Tests\Search\Elastic\Fields;
+
+use CirrusSearch;
+use SearchEngine;
+use Wikibase\DataModel\Entity\EntityDocument;
+use Wikibase\DataModel\Entity\Item;
+use Wikibase\DataModel\Entity\Property;
+use Wikibase\Repo\Search\Elastic\Fields\DescriptionsField;
+
+/**
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\DescriptionsField
+ *
+ * @group WikibaseElastic
+ * @group Wikibase
+ *
+ */
+class DescriptionFieldTest extends SearchFieldTestCase {
+
+       public function getFieldDataProvider() {
+               $item = new Item();
+               $item->getFingerprint()->setDescription( 'es', 'Gato' );
+               $item->getFingerprint()->setDescription( 'ru', 'Кошка' );
+               $item->getFingerprint()->setDescription( 'de', 'Katze' );
+               $item->getFingerprint()->setDescription( 'fr', 'Chat' );
+
+               $prop = Property::newFromType( 'string' );
+               $prop->getFingerprint()->setDescription( 'en', 'astrological 
sign' );
+               $prop->getFingerprint()->setDescription( 'ru', 'знак зодиака' );
+
+               $mock = $this->getMock( EntityDocument::class );
+
+               return [
+                       [
+                               [
+                                       'es' => 'Gato',
+                                       'ru' => 'Кошка',
+                                       'de' => 'Katze',
+                                       'fr' => 'Chat'
+                               ],
+                               $item
+                       ],
+                       [
+                               [
+                                       'en' => 'astrological sign',
+                                       'ru' => 'знак зодиака',
+                               ],
+                               $prop
+                       ],
+                       [ [], $mock ]
+               ];
+       }
+
+       /**
+        * @dataProvider  getFieldDataProvider
+        * @param $expected
+        * @param EntityDocument $entity
+        */
+       public function testDescriptions( $expected, EntityDocument $entity ) {
+               $labels = new DescriptionsField( [ 'en', 'es', 'ru', 'de' ], [] 
);
+               $this->assertEquals( $expected, $labels->getFieldData( $entity 
) );
+       }
+
+       public function testGetMapping() {
+               if ( !class_exists( CirrusSearch::class ) ) {
+                       $this->markTestSkipped( 'CirrusSearch needed.' );
+               }
+               $labels = new DescriptionsField( [ 'en', 'es', 'ru', 'de' ],
+                       [ 'useStemming' =>
+                                 [
+                                       'en' => [ 'index' => true, 'search' => 
true ],
+                                       'es' => [ 'index' => true, 'search' => 
false ],
+                                       'ru' => [ 'index' => false, 'search' => 
true ],
+                                 ]
+                       ]
+               );
+               $searchEngine = $this->getSearchEngineMock();
+               $searchEngine->expects( $this->never() )->method( 
'makeSearchFieldMapping' );
+
+               $mapping = $labels->getMapping( $searchEngine );
+               $this->assertArrayHasKey( 'properties', $mapping );
+               $this->assertCount( 4, $mapping['properties'] );
+               $this->assertEquals( 'object', $mapping['type'] );
+
+               $this->assertEquals( "en_text", 
$mapping['properties']['en']['analyzer'] );
+               $this->assertEquals( "es_text_search", 
$mapping['properties']['es']['search_analyzer'] );
+               $this->assertEquals( "no", 
$mapping['properties']['ru']['index'] );
+               $this->assertEquals( "ru_plain",
+                       
$mapping['properties']['ru']['fields']['plain']['analyzer'] );
+               $this->assertEquals( "no", 
$mapping['properties']['de']['index'] );
+               $this->assertEquals( "de_plain_search",
+                       
$mapping['properties']['de']['fields']['plain']['search_analyzer'] );
+       }
+
+       public function testGetMappingOtherSearchEngine() {
+               $labels = new DescriptionsField( [ 'en', 'es', 'ru', 'de' ], [] 
);
+
+               $searchEngine = $this->getMockBuilder( SearchEngine::class 
)->getMock();
+               $searchEngine->expects( $this->never() )->method( 
'makeSearchFieldMapping' );
+
+               $this->assertSame( [], $labels->getMapping( $searchEngine ) );
+       }
+
+       public function testHints() {
+               $labels = new DescriptionsField( [ 'en', 'es', 'ru', 'de' ], [] 
);
+               $searchEngine = $this->getSearchEngineMock();
+               if ( !class_exists( CirrusSearch::class ) ) {
+                       $this->assertEquals( [], $labels->getEngineHints( 
$searchEngine ) );
+               } else {
+                       $this->assertEquals( [ 'noop' => 'equals' ], 
$labels->getEngineHints( $searchEngine ) );
+               }
+       }
+
+}
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionProviderFieldDefinitionsTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionProviderFieldDefinitionsTest.php
new file mode 100644
index 0000000..5f88a06
--- /dev/null
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/DescriptionProviderFieldDefinitionsTest.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Wikibase\Repo\Tests\Search\Elastic\Fields;
+
+use CirrusSearch;
+use Wikibase\Repo\Search\Elastic\Fields\DescriptionsField;
+use Wikibase\Repo\Search\Elastic\Fields\DescriptionsProviderFieldDefinitions;
+
+/**
+ * @covers 
\Wikibase\Repo\Search\Elastic\Fields\DescriptionsProviderFieldDefinitions
+ *
+ * @group WikibaseElastic
+ * @group WikibaseRepo
+ * @group Wikibase
+ */
+class DescriptionProviderFieldDefinitionsTest extends SearchFieldTestCase {
+
+       public function testGetFields() {
+               $languageCodes = [ 'ar', 'es' ];
+               $fieldDefinitions = new DescriptionsProviderFieldDefinitions(
+                       $languageCodes, []
+               );
+
+               $fields = $fieldDefinitions->getFields();
+               $this->assertArrayHasKey( 'descriptions', $fields );
+               $this->assertInstanceOf( DescriptionsField::class, 
$fields['descriptions'] );
+
+               if ( !class_exists( CirrusSearch::class ) ) {
+                       $this->markTestSkipped( 'CirrusSearch needed.' );
+               }
+               $searchEngine = $this->getSearchEngineMock();
+
+               $mapping = $fields['descriptions']->getMapping( $searchEngine );
+               $this->assertEquals( $languageCodes, array_keys( 
$mapping['properties'] ) );
+       }
+
+}
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/ItemFieldDefinitionsTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/ItemFieldDefinitionsTest.php
index 7e19eff..bd9dec1 100644
--- 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/ItemFieldDefinitionsTest.php
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/ItemFieldDefinitionsTest.php
@@ -13,7 +13,7 @@
 use Wikibase\Repo\Search\Elastic\Fields\StatementsField;
 
 /**
- * @covers Wikibase\Repo\Search\Elastic\Fields\ItemFieldDefinitions
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\ItemFieldDefinitions
  *
  * @group WikibaseElastic
  * @group WikibaseRepo
@@ -56,7 +56,7 @@
 
        private function newDescriptionsProviderFieldDefinitions( array 
$languageCodes ) {
                return new DescriptionsProviderFieldDefinitions(
-                       $languageCodes
+                       $languageCodes, []
                );
        }
 
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelCountFieldTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelCountFieldTest.php
index 1e6a3cb..1c9cc81 100644
--- 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelCountFieldTest.php
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelCountFieldTest.php
@@ -8,7 +8,7 @@
 use Wikibase\Repo\Search\Elastic\Fields\WikibaseNumericField;
 
 /**
- * @covers Wikibase\Repo\Search\Elastic\Fields\LabelCountField
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\LabelCountField
  *
  * @group WikibaseElastic
  * @group Wikibase
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsFieldTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsFieldTest.php
index a94f61c..6528169 100644
--- 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsFieldTest.php
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsFieldTest.php
@@ -3,7 +3,6 @@
 namespace Wikibase\Repo\Tests\Search\Elastic\Fields;
 
 use CirrusSearch;
-use PHPUnit_Framework_TestCase;
 use SearchEngine;
 use Wikibase\DataModel\Entity\EntityDocument;
 use Wikibase\DataModel\Entity\Item;
@@ -11,7 +10,7 @@
 use Wikibase\Repo\Search\Elastic\Fields\LabelsField;
 
 /**
- * @covers Wikibase\Repo\Search\Elastic\Fields\LabelsField
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\LabelsField
  *
  * @group WikibaseElastic
  * @group Wikibase
@@ -19,7 +18,7 @@
  * @license GPL-2.0+
  * @author Stas Malyshev
  */
-class LabelsFieldTest extends PHPUnit_Framework_TestCase {
+class LabelsFieldTest extends SearchFieldTestCase {
 
        public function getFieldDataProvider() {
                $item = new Item();
@@ -60,6 +59,8 @@
 
        /**
         * @dataProvider  getFieldDataProvider
+        * @param $expected
+        * @param EntityDocument $entity
         */
        public function testLabels( $expected, EntityDocument $entity ) {
                $labels = new LabelsField( [ 'en', 'es', 'ru', 'de' ] );
@@ -71,8 +72,7 @@
                        $this->markTestSkipped( 'CirrusSearch needed.' );
                }
                $labels = new LabelsField( [ 'en', 'es', 'ru', 'de' ] );
-
-               $searchEngine = $this->getMockBuilder( CirrusSearch::class 
)->getMock();
+               $searchEngine = $this->getSearchEngineMock();
                $searchEngine->expects( $this->never() )->method( 
'makeSearchFieldMapping' );
 
                $mapping = $labels->getMapping( $searchEngine );
@@ -92,13 +92,11 @@
 
        public function testHints() {
                $labels = new LabelsField( [ 'en', 'es', 'ru', 'de' ] );
+               $searchEngine = $this->getSearchEngineMock();
                if ( !class_exists( CirrusSearch::class ) ) {
-                       $searchEngine = $this->getMockBuilder( 
SearchEngine::class )->getMock();
                        $this->assertEquals( [], $labels->getEngineHints( 
$searchEngine ) );
                } else {
-                       $searchEngine = $this->getMockBuilder( 
CirrusSearch::class )->getMock();
-                       $this->assertEquals( [ 'noop' => 'equals' ],
-                               $labels->getEngineHints( $searchEngine ) );
+                       $this->assertEquals( [ 'noop' => 'equals' ], 
$labels->getEngineHints( $searchEngine ) );
                }
        }
 
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsProviderFieldDefinitionsTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsProviderFieldDefinitionsTest.php
index a3ef4aa..9b425ab 100644
--- 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsProviderFieldDefinitionsTest.php
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/LabelsProviderFieldDefinitionsTest.php
@@ -3,14 +3,13 @@
 namespace Wikibase\Repo\Tests\Search\Elastic\Fields;
 
 use CirrusSearch;
-use PHPUnit_Framework_TestCase;
 use Wikibase\Repo\Search\Elastic\Fields\AllLabelsField;
 use Wikibase\Repo\Search\Elastic\Fields\LabelCountField;
 use Wikibase\Repo\Search\Elastic\Fields\LabelsField;
 use Wikibase\Repo\Search\Elastic\Fields\LabelsProviderFieldDefinitions;
 
 /**
- * @covers Wikibase\Repo\Search\Elastic\Fields\LabelsProviderFieldDefinitions
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\LabelsProviderFieldDefinitions
  *
  * @group WikibaseElastic
  * @group WikibaseRepo
@@ -19,7 +18,7 @@
  * @license GPL-2.0+
  * @author Stas Malyshev
  */
-class LabelsProviderFieldDefinitionsTest extends PHPUnit_Framework_TestCase {
+class LabelsProviderFieldDefinitionsTest extends SearchFieldTestCase {
 
        public function testGetFields() {
                $languageCodes = [ 'ar', 'es' ];
@@ -38,8 +37,7 @@
                if ( !class_exists( CirrusSearch::class ) ) {
                        $this->markTestSkipped( 'CirrusSearch needed.' );
                }
-               $searchEngine = $this->getMockBuilder( CirrusSearch::class 
)->getMock();
-               $searchEngine->expects( $this->never() )->method( 
'makeSearchFieldMapping' );
+               $searchEngine = $this->getSearchEngineMock();
 
                $mapping = $fields['labels']->getMapping( $searchEngine );
                $this->assertEquals( $languageCodes, array_keys( 
$mapping['properties'] ) );
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/SearchFieldTestCase.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/SearchFieldTestCase.php
new file mode 100644
index 0000000..5564c54
--- /dev/null
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/SearchFieldTestCase.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Wikibase\Repo\Tests\Search\Elastic\Fields;
+
+use CirrusSearch;
+use PHPUnit_Framework_TestCase;
+use SearchEngine;
+
+/**
+ * Helper test class for search field testing.
+ */
+class SearchFieldTestCase extends PHPUnit_Framework_TestCase {
+
+       /**
+        * Prepare search engine mock suitable for testing search fields.
+        * @return SearchEngine
+        */
+       protected function getSearchEngineMock() {
+               if ( class_exists( CirrusSearch::class ) ) {
+                       $searchEngine = $this->getMockBuilder( 
CirrusSearch::class )->getMock();
+                       $searchEngine->method( 'getConfig' )->willReturn( new 
CirrusSearch\SearchConfig() );
+               } else {
+                       $searchEngine = $this->getMockBuilder( 
SearchEngine::class )->getMock();
+               }
+               return $searchEngine;
+       }
+
+}
diff --git 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/StatementCountFieldTest.php
 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/StatementCountFieldTest.php
index 018a7ab..df8f938 100644
--- 
a/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/StatementCountFieldTest.php
+++ 
b/extensions/Wikibase/repo/tests/phpunit/includes/Search/Elastic/Fields/StatementCountFieldTest.php
@@ -9,7 +9,7 @@
 use Wikibase\Repo\Search\Elastic\Fields\WikibaseNumericField;
 
 /**
- * @covers Wikibase\Repo\Search\Elastic\Fields\StatementCountField
+ * @covers \Wikibase\Repo\Search\Elastic\Fields\StatementCountField
  *
  * @group WikibaseElastic
  * @group Wikibase
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index d37eef8..b4892f9 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1298,7 +1298,7 @@
         "source": {
             "type": "git",
             "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/Wikibase";,
-            "reference": "45dabf27253840cc8271fbf59a8c05324e6b9400"
+            "reference": "55d1e3f7b56db18b134259fb2a86bbf8a87691af"
         },
         "require": {
             "composer/installers": ">=1.0.1",
@@ -1327,7 +1327,7 @@
             "mediawiki/minus-x": "0.1.0",
             "wikibase/wikibase-codesniffer": "^0.2.0"
         },
-        "time": "2017-11-25 21:59:04",
+        "time": "2017-11-27 08:47:48",
         "type": "mediawiki-extension",
         "installation-source": "source",
         "scripts": {
@@ -1433,7 +1433,7 @@
         "source": {
             "type": "git",
             "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseQualityConstraints";,
-            "reference": "881e265221b80e6ea20a4baff90e5d53b69ed8a6"
+            "reference": "7c591dc0c9ed46bd76a4541263c6fa1015715146"
         },
         "require": {
             "php": ">=5.5.9",
@@ -1450,7 +1450,7 @@
             "satooshi/php-coveralls": "master-dev",
             "wikibase/wikibase-codesniffer": "^0.2.0"
         },
-        "time": "2017-11-24 22:29:05",
+        "time": "2017-11-27 08:10:20",
         "type": "mediawiki-extension",
         "installation-source": "source",
         "scripts": {

-- 
To view, visit https://gerrit.wikimedia.org/r/393560
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idd89f8edde26b339bf9d1495e315dae7e338dab1
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikidata
Gerrit-Branch: master
Gerrit-Owner: WikidataBuilder <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to