Repository: martin-majlis/Wikipedia-API

Issue:
Allow specifying language variant
Some wikipedia pages (such as Serbian and Chinese) have multiple language variants that are equivalent.

Fetching the content is then dependent on the variant variable in the API: https://zh.wikipedia.org/wiki/Special:API%E6%B2%99%E7%9B%92?uselang=en#action=parse&format=json&variant=zh-tw&page=Main%20Page&formatversion=2

I'm currently working around this by monkey-patching the `wikipediaapi.Wikipedia._query` method like this:
```python
def patched_query(self, page: "WikipediaPage", params: dict[str, Any]):
        """Queries Wikimedia API to fetch content."""
        print(self._request_kwargs)
        if 'variant' in self._request_kwargs:
            params['variant'] = self._request_kwargs['variant']
            del(self._request_kwargs['variant'])
        base_url = "https://" + page.language + ".wikipedia.org/w/api.php"
        #log.info(
        #    "Request URL: %s",
        #    base_url + "?" + "&".join([k + "=" + str(v) for k, v in params.items()])
        #)
        params["format"] = "json"
        params["redirects"] = 1
        print(params)
        r = self._session.get(base_url, params=params, **self._request_kwargs)
        return r.json()
```
Ideally there would be a way to specify extra params that go to the wikipedia call, not just to the request library.

Discussion:

Patch:
diff --git a/API.rst b/API.rst
index 7055c5c..8212beb 100644
--- a/API.rst
+++ b/API.rst
@@ -3,7 +3,7 @@ API
 
 Wikipedia
 ---------
-* ``__init__(user_agent: str, language='en', extract_format=ExtractFormat.WIKI, headers: Optional[Dict[str, Any]] = None, **kwargs)``
+* ``__init__(user_agent: str, language='en', variant=Optional[str] = None, extract_format=ExtractFormat.WIKI, headers: Optional[Dict[str, Any]] = None, extra_api_params: Optional[dict[str, Any]] = None, **request_kwargs)``
 * ``page(title)``
 
 WikipediaPage
@@ -20,6 +20,7 @@ WikipediaPage
 * ``links`` - links to other pages ({title: ``WikipediaPage``})
 * ``categories`` - all categories ({title: ``WikipediaPage``})
 * ``displaytitle``
+* ``varianttitles``
 * ``canonicalurl``
 * ``ns``
 * ``contentmodel``
diff --git a/Makefile b/Makefile
index 8b9367e..bd0cc50 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ help:
 
 pypi-html:
 	python3 setup.py --long-description | rst2html.py > pypi-doc.html
+	echo file://$$( pwd )/pypi-doc.html
 
 run-pre-commit:
 	pre-commit run -a
@@ -37,19 +38,24 @@ run-coverage:
 	coverage report -m
 	coverage xml
 
+run-example:
+	./example.py
+
+requirements-all: requirements requirements-dev requirements-doc
+
 requirements:
 	pip install -r requirements.txt
 
 requirements-dev:
 	pip install -r requirements-dev.txt
 
-requirements-docs:
-	pip install -r requirements-docs.txt
+requirements-doc:
+	pip install -r requirements-doc.txt
 
 requirements-build:
 	pip install -r requirements-build.txt
 
-pre-release-check: run-pre-commit run-type-check run-flake8 run-coverage pypi-html run-tox
+pre-release-check: run-pre-commit run-type-check run-flake8 run-coverage pypi-html run-tox run-example
 	echo "Pre-release check was successful"
 
 release: pre-release-check
diff --git a/README.rst b/README.rst
index c603f35..59803b0 100644
--- a/README.rst
+++ b/README.rst
@@ -10,7 +10,7 @@ Wikipedia API
 Installation
 ------------
 
-This package requires at least Python 3.8 to install because it's using IntEnum.
+This package requires at least Python 3.9 to install because it's using IntEnum.
 
 .. code-block:: python
 
@@ -27,7 +27,7 @@ Importing
 
 .. code-block:: python
 
-	import wikipediaapi
+    import wikipediaapi
 
 How To Get Single Page
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -44,9 +44,9 @@ To initialize it, you have to provide:
 .. code-block:: python
 
     import wikipediaapi
-	wiki_wiki = wikipediaapi.Wikipedia('MyProjectName (merlin@example.com)', 'en')
+    wiki_wiki = wikipediaapi.Wikipedia('MyProjectName (merlin@example.com)', 'en')
 
-	page_py = wiki_wiki.page('Python_(programming_language)')
+    page_py = wiki_wiki.page('Python_(programming_language)')
 
 
 How To Check If Wiki Page Exists
@@ -56,13 +56,13 @@ For checking, whether page exists, you can use function ``exists``.
 
 .. code-block:: python
 
-	page_py = wiki_wiki.page('Python_(programming_language)')
-	print("Page - Exists: %s" % page_py.exists())
-	# Page - Exists: True
+    page_py = wiki_wiki.page('Python_(programming_language)')
+    print("Page - Exists: %s" % page_py.exists())
+    # Page - Exists: True
 
-	page_missing = wiki_wiki.page('NonExistingPageWithStrangeName')
-	print("Page - Exists: %s" % 	page_missing.exists())
-	# Page - Exists: False
+    page_missing = wiki_wiki.page('NonExistingPageWithStrangeName')
+    print("Page - Exists: %s" %     page_missing.exists())
+    # Page - Exists: False
 
 How To Get Page Summary
 ~~~~~~~~~~~~~~~~~~~~~~~
@@ -73,13 +73,13 @@ Class ``WikipediaPage`` has property ``summary``, which returns description of W
 
 
     import wikipediaapi
-	wiki_wiki = wikipediaapi.Wikipedia('MyProjectName (merlin@example.com)', 'en')
+    wiki_wiki = wikipediaapi.Wikipedia('MyProjectName (merlin@example.com)', 'en')
 
-	print("Page - Title: %s" % page_py.title)
-	# Page - Title: Python (programming language)
+    print("Page - Title: %s" % page_py.title)
+    # Page - Title: Python (programming language)
 
-	print("Page - Summary: %s" % page_py.summary[0:60])
-	# Page - Summary: Python is a widely used high-level programming language for
+    print("Page - Summary: %s" % page_py.summary[0:60])
+    # Page - Summary: Python is a widely used high-level programming language for
 
 
 How To Get Page URL
@@ -89,11 +89,11 @@ How To Get Page URL
 
 .. code-block:: python
 
-	print(page_py.fullurl)
-	# https://en.wikipedia.org/wiki/Python_(programming_language)
+    print(page_py.fullurl)
+    # https://en.wikipedia.org/wiki/Python_(programming_language)
 
-	print(page_py.canonicalurl)
-	# https://en.wikipedia.org/wiki/Python_(programming_language)
+    print(page_py.canonicalurl)
+    # https://en.wikipedia.org/wiki/Python_(programming_language)
 
 How To Get Full Text
 ~~~~~~~~~~~~~~~~~~~~
@@ -103,35 +103,35 @@ as concatanation of summary and sections with their titles and texts.
 
 .. code-block:: python
 
-	wiki_wiki = wikipediaapi.Wikipedia(
-	    user_agent='MyProjectName (merlin@example.com)',
-		language='en',
-		extract_format=wikipediaapi.ExtractFormat.WIKI
-	)
-
-	p_wiki = wiki_wiki.page("Test 1")
-	print(p_wiki.text)
-	# Summary
-	# Section 1
-	# Text of section 1
-	# Section 1.1
-	# Text of section 1.1
-	# ...
-
-
-	wiki_html = wikipediaapi.Wikipedia(
-	    user_agent='MyProjectName (merlin@example.com)',
-		language='en',
-		extract_format=wikipediaapi.ExtractFormat.HTML
-	)
-	p_html = wiki_html.page("Test 1")
-	print(p_html.text)
-	# <p>Summary</p>
-	# <h2>Section 1</h2>
-	# <p>Text of section 1</p>
-	# <h3>Section 1.1</h3>
-	# <p>Text of section 1.1</p>
-	# ...
+    wiki_wiki = wikipediaapi.Wikipedia(
+        user_agent='MyProjectName (merlin@example.com)',
+        language='en',
+        extract_format=wikipediaapi.ExtractFormat.WIKI
+    )
+
+    p_wiki = wiki_wiki.page("Test 1")
+    print(p_wiki.text)
+    # Summary
+    # Section 1
+    # Text of section 1
+    # Section 1.1
+    # Text of section 1.1
+    # ...
+
+
+    wiki_html = wikipediaapi.Wikipedia(
+        user_agent='MyProjectName (merlin@example.com)',
+        language='en',
+        extract_format=wikipediaapi.ExtractFormat.HTML
+    )
+    p_html = wiki_html.page("Test 1")
+    print(p_html.text)
+    # <p>Summary</p>
+    # <h2>Section 1</h2>
+    # <p>Text of section 1</p>
+    # <h3>Section 1.1</h3>
+    # <p>Text of section 1.1</p>
+    # ...
 
 How To Get Page Sections
 ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -141,19 +141,19 @@ To get all top level sections of page, you have to use property ``sections``. It
 
 .. code-block:: python
 
-	def print_sections(sections, level=0):
-		for s in sections:
-			print("%s: %s - %s" % ("*" * (level + 1), s.title, s.text[0:40]))
-			print_sections(s.sections, level + 1)
+    def print_sections(sections, level=0):
+        for s in sections:
+            print("%s: %s - %s" % ("*" * (level + 1), s.title, s.text[0:40]))
+            print_sections(s.sections, level + 1)
 
 
-	print_sections(page_py.sections)
-	# *: History - Python was conceived in the late 1980s,
-	# *: Features and philosophy - Python is a multi-paradigm programming l
-	# *: Syntax and semantics - Python is meant to be an easily readable
-	# **: Indentation - Python uses whitespace indentation, rath
-	# **: Statements and control flow - Python's statements include (among other
-	# **: Expressions - Some Python expressions are similar to l
+    print_sections(page_py.sections)
+    # *: History - Python was conceived in the late 1980s,
+    # *: Features and philosophy - Python is a multi-paradigm programming l
+    # *: Syntax and semantics - Python is meant to be an easily readable
+    # **: Indentation - Python uses whitespace indentation, rath
+    # **: Statements and control flow - Python's statements include (among other
+    # **: Expressions - Some Python expressions are similar to l
 
 How To Get Page Section By Title
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -163,10 +163,10 @@ It returns the last ``WikipediaPageSection`` with this title.
 
 .. code-block:: python
 
-	section_history = page_py.section_by_title('History')
-	print("%s - %s" % (section_history.title, section_history.text[0:40]))
+    section_history = page_py.section_by_title('History')
+    print("%s - %s" % (section_history.title, section_history.text[0:40]))
 
-	# History - Python was conceived in the late 1980s b
+    # History - Python was conceived in the late 1980s b
 
 How To Get All Page Sections By Title
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -176,10 +176,10 @@ It returns the all ``WikipediaPageSection`` with this title.
 
 .. code-block:: python
 
-	page_1920 = wiki_wiki.page('1920')
-	sections_january = page_1920.sections_by_title('January')
-	for s in sections_january:
-	    print("* %s - %s" % (s.title, s.text[0:40]))
+    page_1920 = wiki_wiki.page('1920')
+    sections_january = page_1920.sections_by_title('January')
+    for s in sections_january:
+        print("* %s - %s" % (s.title, s.text[0:40]))
 
     # * January - January 1
     # Polish–Soviet War in 1920: The
@@ -195,22 +195,22 @@ where key is language code and value is ``WikipediaPage``.
 
 .. code-block:: python
 
-	def print_langlinks(page):
-		langlinks = page.langlinks
-		for k in sorted(langlinks.keys()):
-		    v = langlinks[k]
-		    print("%s: %s - %s: %s" % (k, v.language, v.title, v.fullurl))
+    def print_langlinks(page):
+        langlinks = page.langlinks
+        for k in sorted(langlinks.keys()):
+            v = langlinks[k]
+            print("%s: %s - %s: %s" % (k, v.language, v.title, v.fullurl))
 
-	print_langlinks(page_py)
-	# af: af - Python (programmeertaal): https://af.wikipedia.org/wiki/Python_(programmeertaal)
-	# als: als - Python (Programmiersprache): https://als.wikipedia.org/wiki/Python_(Programmiersprache)
-	# an: an - Python: https://an.wikipedia.org/wiki/Python
-	# ar: ar - بايثون: https://ar.wikipedia.org/wiki/%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86
-	# as: as - পাইথন: https://as.wikipedia.org/wiki/%E0%A6%AA%E0%A6%BE%E0%A6%87%E0%A6%A5%E0%A6%A8
+    print_langlinks(page_py)
+    # af: af - Python (programmeertaal): https://af.wikipedia.org/wiki/Python_(programmeertaal)
+    # als: als - Python (Programmiersprache): https://als.wikipedia.org/wiki/Python_(Programmiersprache)
+    # an: an - Python: https://an.wikipedia.org/wiki/Python
+    # ar: ar - بايثون: https://ar.wikipedia.org/wiki/%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86
+    # as: as - পাইথন: https://as.wikipedia.org/wiki/%E0%A6%AA%E0%A6%BE%E0%A6%87%E0%A6%A5%E0%A6%A8
 
-	page_py_cs = page_py.langlinks['cs']
-	print("Page - Summary: %s" % page_py_cs.summary[0:60])
-	# Page - Summary: Python (anglická výslovnost [ˈpaiθtən]) je vysokoúrovňový sk
+    page_py_cs = page_py.langlinks['cs']
+    print("Page - Summary: %s" % page_py_cs.summary[0:60])
+    # Page - Summary: Python (anglická výslovnost [ˈpaiθtən]) je vysokoúrovňový sk
 
 How To Get Links To Other Pages
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -220,18 +220,18 @@ It's map, where key is page title and value is ``WikipediaPage``.
 
 .. code-block:: python
 
-	def print_links(page):
-		links = page.links
-		for title in sorted(links.keys()):
-		    print("%s: %s" % (title, links[title]))
+    def print_links(page):
+        links = page.links
+        for title in sorted(links.keys()):
+            print("%s: %s" % (title, links[title]))
 
-	print_links(page_py)
-	# 3ds Max: 3ds Max (id: ??, ns: 0)
-	# ?:: ?: (id: ??, ns: 0)
-	# ABC (programming language): ABC (programming language) (id: ??, ns: 0)
-	# ALGOL 68: ALGOL 68 (id: ??, ns: 0)
-	# Abaqus: Abaqus (id: ??, ns: 0)
-	# ...
+    print_links(page_py)
+    # 3ds Max: 3ds Max (id: ??, ns: 0)
+    # ?:: ?: (id: ??, ns: 0)
+    # ABC (programming language): ABC (programming language) (id: ??, ns: 0)
+    # ALGOL 68: ALGOL 68 (id: ??, ns: 0)
+    # Abaqus: Abaqus (id: ??, ns: 0)
+    # ...
 
 How To Get Page Categories
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -241,19 +241,19 @@ It's map, where key is category title and value is ``WikipediaPage``.
 
 .. code-block:: python
 
-	def print_categories(page):
-		categories = page.categories
-		for title in sorted(categories.keys()):
-		    print("%s: %s" % (title, categories[title]))
+    def print_categories(page):
+        categories = page.categories
+        for title in sorted(categories.keys()):
+            print("%s: %s" % (title, categories[title]))
 
 
-	print("Categories")
-	print_categories(page_py)
-	# Category:All articles containing potentially dated statements: ...
-	# Category:All articles with unsourced statements: ...
-	# Category:Articles containing potentially dated statements from August 2016: ...
-	# Category:Articles containing potentially dated statements from March 2017: ...
-	# Category:Articles containing potentially dated statements from September 2017: ...
+    print("Categories")
+    print_categories(page_py)
+    # Category:All articles containing potentially dated statements: ...
+    # Category:All articles with unsourced statements: ...
+    # Category:Articles containing potentially dated statements from August 2016: ...
+    # Category:Articles containing potentially dated statements from March 2017: ...
+    # Category:Articles containing potentially dated statements from September 2017: ...
 
 How To Get All Pages From Category
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -263,26 +263,47 @@ You have to implement recursion and deduplication by yourself.
 
 .. code-block:: python
 
-	def print_categorymembers(categorymembers, level=0, max_level=1):
-		for c in categorymembers.values():
-		    print("%s: %s (ns: %d)" % ("*" * (level + 1), c.title, c.ns))
-		    if c.ns == wikipediaapi.Namespace.CATEGORY and level < max_level:
-		        print_categorymembers(c.categorymembers, level=level + 1, max_level=max_level)
+    def print_categorymembers(categorymembers, level=0, max_level=1):
+        for c in categorymembers.values():
+            print("%s: %s (ns: %d)" % ("*" * (level + 1), c.title, c.ns))
+            if c.ns == wikipediaapi.Namespace.CATEGORY and level < max_level:
+                print_categorymembers(c.categorymembers, level=level + 1, max_level=max_level)
+
+
+    cat = wiki_wiki.page("Category:Physics")
+    print("Category members: Category:Physics")
+    print_categorymembers(cat.categorymembers)
+
+    # Category members: Category:Physics
+    # * Statistical mechanics (ns: 0)
+    # * Category:Physical quantities (ns: 14)
+    # ** Refractive index (ns: 0)
+    # ** Vapor quality (ns: 0)
+    # ** Electric susceptibility (ns: 0)
+    # ** Specific weight (ns: 0)
+    # ** Category:Viscosity (ns: 14)
+    # *** Brookfield Engineering (ns: 0)
+
+Use Extra API Parameters
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Official API supports many different parameters. You can see them in the `sandbox`_. Not all these
+parameters are supported directly as parameters of the functions. If you want to specify them,
+you can pass them as additional parameters in the constructor. For the `info API call`_ you can
+specify parameter `converttitles`. If you want to specify it, you can use:
+
+.. code-block:: python
+
+    import sys
 
+    import wikipediaapi
+    wiki_wiki = wikipediaapi.Wikipedia('MyProjectName (merlin@example.com)', 'zh', 'zh-tw', extra_api_params={'converttitles': 1})
+    page = wiki_wiki.page("孟卯")
+    print(repr(page.varianttitles))
 
-	cat = wiki_wiki.page("Category:Physics")
-	print("Category members: Category:Physics")
-	print_categorymembers(cat.categorymembers)
 
-	# Category members: Category:Physics
-	# * Statistical mechanics (ns: 0)
-	# * Category:Physical quantities (ns: 14)
-	# ** Refractive index (ns: 0)
-	# ** Vapor quality (ns: 0)
-	# ** Electric susceptibility (ns: 0)
-	# ** Specific weight (ns: 0)
-	# ** Category:Viscosity (ns: 14)
-	# *** Brookfield Engineering (ns: 0)
+.. _sandbox: https://en.wikipedia.org/wiki/Special:ApiSandbox
+.. _info API call: https://zh.wikipedia.org/wiki/Special:API%E6%B2%99%E7%9B%92#action=query&format=json&variant=zh-tw&prop=info&titles=%E5%AD%9F%E5%8D%AF&converttitles=1&formatversion=2&inprop=varianttitles%7Cdisplaytitle
 
 How To See Underlying API Call
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -337,12 +358,12 @@ Other Pages
 
 .. PYPI-BEGIN
 .. toctree::
-	:maxdepth: 2
+    :maxdepth: 2
 
-	API
-	CHANGES
-	DEVELOPMENT
-	wikipediaapi/api
+    API
+    CHANGES
+    DEVELOPMENT
+    wikipediaapi/api
 
 .. PYPI-END
 
@@ -364,108 +385,108 @@ Other Pages
     :alt: Test Coverage
 
 .. |coveralls| image:: https://coveralls.io/repos/github/martin-majlis/Wikipedia-API/badge.svg?branch=master
-	:target: https://coveralls.io/github/martin-majlis/Wikipedia-API?branch=master
-	:alt: Coveralls
+    :target: https://coveralls.io/github/martin-majlis/Wikipedia-API?branch=master
+    :alt: Coveralls
 
 .. |version| image:: https://img.shields.io/pypi/v/wikipedia-api.svg?style=flat
-	:target: https://pypi.python.org/pypi/Wikipedia-API
-	:alt: Version
+    :target: https://pypi.python.org/pypi/Wikipedia-API
+    :alt: Version
 
 .. |pyversions| image:: https://img.shields.io/pypi/pyversions/wikipedia-api.svg?style=flat
-	:target: https://pypi.python.org/pypi/Wikipedia-API
-	:alt: Py Versions
+    :target: https://pypi.python.org/pypi/Wikipedia-API
+    :alt: Py Versions
 
 .. |implementations| image:: https://img.shields.io/pypi/implementation/wikipedia-api.svg?style=flat
     :target: https://pypi.python.org/pypi/Wikipedia-API
-	:alt: Implementations
+    :alt: Implementations
 
 .. |github-downloads| image:: https://img.shields.io/github/downloads/martin-majlis/Wikipedia-API/total.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/releases
-	:alt: Downloads
+    :target: https://github.com/martin-majlis/Wikipedia-API/releases
+    :alt: Downloads
 
 .. |github-tag| image:: https://img.shields.io/github/tag/martin-majlis/Wikipedia-API.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/tags
-	:alt: Tags
+    :target: https://github.com/martin-majlis/Wikipedia-API/tags
+    :alt: Tags
 
 .. |github-release| image:: https://img.shields.io/github/release/martin-majlis/Wikipedia-API.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/
+    :target: https://github.com/martin-majlis/Wikipedia-API/
 
 .. |github-commits-since-latest| image:: https://img.shields.io/github/commits-since/martin-majlis/Wikipedia-API/latest.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: Github commits (since latest release)
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: Github commits (since latest release)
 
 .. |github-forks| image:: https://img.shields.io/github/forks/martin-majlis/Wikipedia-API.svg?style=social&label=Fork
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: GitHub forks
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: GitHub forks
 
 .. |github-stars| image:: https://img.shields.io/github/stars/martin-majlis/Wikipedia-API.svg?style=social&label=Stars
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: GitHub stars
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: GitHub stars
 
 .. |github-stars-flat| image:: https://img.shields.io/github/stars/martin-majlis/Wikipedia-API.svg?style=flat&label=Stars
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: GitHub stars
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: GitHub stars
 
 .. |github-watches| image:: https://img.shields.io/github/watchers/martin-majlis/Wikipedia-API.svg?style=social&label=Watch
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: GitHub watchers
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: GitHub watchers
 
 .. |github-commit-activity| image:: https://img.shields.io/github/commit-activity/y/martin-majlis/Wikipedia-API.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/commits/master
-	:alt: GitHub commit activity the past week, 4 weeks, year
+    :target: https://github.com/martin-majlis/Wikipedia-API/commits/master
+    :alt: GitHub commit activity the past week, 4 weeks, year
 
 .. |github-last-commit| image:: https://img.shields.io/github/commits/martin-majlis/Wikipedia-API/last.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: Last commit
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: Last commit
 
 .. |github-code-size| image:: https://img.shields.io/github/languages/code-size/martin-majlis/Wikipedia-API.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: GitHub code size in bytes
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: GitHub code size in bytes
 
 .. |github-repo-size| image:: https://img.shields.io/github/repo-size/martin-majlis/Wikipedia-API.svg
-	:target: https://github.com/martin-majlis/Wikipedia-API/
-	:alt: GitHub repo size in bytes
+    :target: https://github.com/martin-majlis/Wikipedia-API/
+    :alt: GitHub repo size in bytes
 
 .. |pypi-license| image:: https://img.shields.io/pypi/l/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi License
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi License
 
 .. |pypi-wheel| image:: https://img.shields.io/pypi/wheel/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Wheel
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Wheel
 
 .. |pypi-format| image:: https://img.shields.io/pypi/format/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Format
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Format
 
 .. |pypi-pyversions| image:: https://img.shields.io/pypi/pyversions/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi PyVersions
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi PyVersions
 
 .. |pypi-implementations| image:: https://img.shields.io/pypi/implementation/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Implementations
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Implementations
 
 .. |pypi-status| image:: https://img.shields.io/pypi/status/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Status
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Status
 
 .. |pypi-downloads-dd| image:: https://img.shields.io/pypi/dd/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Downloads - Day
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Downloads - Day
 
 .. |pypi-downloads-dw| image:: https://img.shields.io/pypi/dw/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Downloads - Week
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Downloads - Week
 
 .. |pypi-downloads-dm| image:: https://img.shields.io/pypi/dm/Wikipedia-API.svg
-	:target: https://pypi.python.org/pypi/Wikipedia-API/
-	:alt: PyPi Downloads - Month
+    :target: https://pypi.python.org/pypi/Wikipedia-API/
+    :alt: PyPi Downloads - Month
 
 .. |libraries-io-sourcerank| image:: https://img.shields.io/librariesio/sourcerank/pypi/Wikipedia-API.svg
-	:target: https://libraries.io/pypi/Wikipedia-API
-	:alt: Libraries.io - SourceRank
+    :target: https://libraries.io/pypi/Wikipedia-API
+    :alt: Libraries.io - SourceRank
 
 .. |libraries-io-dependent-repos| image:: https://img.shields.io/librariesio/dependent-repos/pypi/Wikipedia-API.svg
-	:target: https://libraries.io/pypi/Wikipedia-API
-	:alt: Libraries.io - Dependent Repos
+    :target: https://libraries.io/pypi/Wikipedia-API
+    :alt: Libraries.io - Dependent Repos
diff --git a/example.py b/example.py
old mode 100644
new mode 100755
index 20c881f..7ce4931
--- a/example.py
+++ b/example.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
 import logging
 
 import wikipediaapi
@@ -119,3 +120,31 @@ p_hi_python_quoted = wiki_hi.article(
 )
 print(p_hi_python_quoted.title)
 print(p_hi_python_quoted.summary[0:60])
+
+# Fetch page about Python in Chinese
+wiki_zh = wikipediaapi.Wikipedia(user_agent, "zh")
+zh_page = wiki_zh.page("Python")
+print(zh_page.title + ": " + zh_page.fullurl)
+print(zh_page.summary[0:60])
+print(repr(zh_page.varianttitles))
+
+# https://zh.wikipedia.org/zh-cn/Python
+wiki_zh_cn = wikipediaapi.Wikipedia(user_agent, "zh", "zh-cn")
+zh_page_cn = wiki_zh_cn.page("Python")
+print(zh_page_cn.title + ": " + zh_page_cn.fullurl)
+print(zh_page_cn.summary[0:60])
+print(repr(zh_page_cn.varianttitles))
+
+# https://zh.wikipedia.org/zh-tw/Python
+wiki_zh_tw = wikipediaapi.Wikipedia(user_agent, "zh", "zh-tw")
+zh_page_tw = wiki_zh_tw.page("Python")
+print(zh_page_tw.title + ": " + zh_page_tw.fullurl)
+print(zh_page_tw.summary[0:60])
+print(repr(zh_page_tw.varianttitles))
+
+# https://zh.wikipedia.org/zh-sg/Python
+wiki_zh_sg = wikipediaapi.Wikipedia(user_agent, "zh", "zh-sg")
+zh_page_sg = wiki_zh_sg.page("Python")
+print(zh_page_sg.title + ": " + zh_page_sg.fullurl)
+print(zh_page_sg.summary[0:60])
+print(repr(zh_page_sg.varianttitles))
diff --git a/wikipediaapi/__init__.py b/wikipediaapi/__init__.py
index 3dda7ae..c833ca9 100644
--- a/wikipediaapi/__init__.py
+++ b/wikipediaapi/__init__.py
@@ -133,9 +133,11 @@ class Wikipedia:
         self,
         user_agent: str,
         language: str = "en",
+        variant: Optional[str] = None,
         extract_format: ExtractFormat = ExtractFormat.WIKI,
         headers: Optional[dict[str, Any]] = None,
-        **kwargs,
+        extra_api_params: Optional[dict[str, Any]] = None,
+        **request_kwargs,
     ) -> None:
         """
         Constructs Wikipedia object for extracting information Wikipedia.
@@ -144,17 +146,21 @@ class Wikipedia:
                 https://meta.wikimedia.org/wiki/User-Agent_policy
         :param language: Language mutation of Wikipedia -
                 http://meta.wikimedia.org/wiki/List_of_Wikipedias
+        :param variant: Language variant.
+                Only works if the base language supports variant conversion.
         :param extract_format: Format used for extractions
                 :class:`ExtractFormat` object.
         :param headers:  Headers sent as part of HTTP request
-        :param kwargs: Optional parameters used in -
+        :param extra_api_params:  Extra parameters that are used to construct
+                query string when calling Wikipedia API
+        :param request_kwargs: Optional parameters used in -
                 http://docs.python-requests.org/en/master/api/#requests.request
 
         Examples:
 
         * Proxy: ``Wikipedia('foo (merlin@example.com)', proxies={'http': 'http://proxy:1234'})``
         """
-        kwargs.setdefault("timeout", 10.0)
+        request_kwargs.setdefault("timeout", 10.0)
 
         default_headers = {} if headers is None else headers
         if user_agent:
@@ -179,6 +185,7 @@ class Wikipedia:
                 + str(self.language)
                 + "' is not sufficient."
             )
+        self.variant = variant.strip().lower() if variant else variant
         self.extract_format = extract_format
 
         log.info(
@@ -188,9 +195,11 @@ class Wikipedia:
             self.extract_format,
         )
 
+        self._extra_api_params = extra_api_params
+
         self._session = requests.Session()
         self._session.headers.update(default_headers)
-        self._request_kwargs = kwargs
+        self._request_kwargs = request_kwargs
 
     def __del__(self) -> None:
         """Closes session."""
@@ -233,7 +242,9 @@ class Wikipedia:
         if unquote:
             title = parse.unquote(title)
 
-        return WikipediaPage(self, title=title, ns=ns, language=self.language)
+        return WikipediaPage(
+            self, title=title, ns=ns, language=self.language, variant=self.variant
+        )
 
     def article(
         self, title: str, ns: WikiNamespace = Namespace.MAIN, unquote: bool = False
@@ -327,6 +338,7 @@ class Wikipedia:
                     "readable",
                     "preload",
                     "displaytitle",
+                    "varianttitles",
                 ]
             ),
         }
@@ -520,15 +532,31 @@ class Wikipedia:
     def _query(self, page: "WikipediaPage", params: dict[str, Any]):
         """Queries Wikimedia API to fetch content."""
         base_url = "https://" + page.language + ".wikipedia.org/w/api.php"
+        used_params = self._construct_params(page, params)
+
         log.info(
             "Request URL: %s",
-            base_url + "?" + "&".join([k + "=" + str(v) for k, v in params.items()]),
+            base_url
+            + "?"
+            + "&".join([k + "=" + str(v) for k, v in used_params.items()]),
         )
-        params["format"] = "json"
-        params["redirects"] = 1
-        r = self._session.get(base_url, params=params, **self._request_kwargs)
+
+        r = self._session.get(base_url, params=used_params, **self._request_kwargs)
         return r.json()
 
+    def _construct_params(
+        self, page: "WikipediaPage", params: dict[str, Any]
+    ) -> dict[str, Any]:
+        used_params = {}  # type: dict[str, Any]
+        if page.variant:
+            used_params["variant"] = page.variant
+        used_params["format"] = "json"
+        used_params["redirects"] = 1
+        used_params.update(params)
+        if self._extra_api_params:
+            used_params.update(self._extra_api_params)
+        return used_params
+
     def _build_extracts(self, extract, page: "WikipediaPage") -> str:
         """Constructs summary of given page."""
         page._summary = ""
@@ -626,6 +654,7 @@ class Wikipedia:
                 title=link["title"],
                 ns=int(link["ns"]),
                 language=page.language,
+                variant=page.variant,
             )
 
         return page._links
@@ -642,6 +671,7 @@ class Wikipedia:
                 title=backlink["title"],
                 ns=int(backlink["ns"]),
                 language=page.language,
+                variant=page.variant,
             )
 
         return page._backlinks
@@ -658,6 +688,7 @@ class Wikipedia:
                 title=category["title"],
                 ns=int(category["ns"]),
                 language=page.language,
+                variant=page.variant,
             )
 
         return page._categories
@@ -674,6 +705,7 @@ class Wikipedia:
                 title=member["title"],
                 ns=int(member["ns"]),
                 language=page.language,
+                variant=page.variant,
             )
             p.pageid = member["pageid"]  # type: ignore
 
@@ -802,6 +834,7 @@ class WikipediaPage:
 
     ATTRIBUTES_MAPPING = {
         "language": [],
+        "variant": [],
         "pageid": ["info", "extracts", "langlinks"],
         "ns": ["info", "extracts", "langlinks"],
         "title": ["info", "extracts", "langlinks"],
@@ -824,6 +857,7 @@ class WikipediaPage:
         "readable": ["info"],
         "preload": ["info"],
         "displaytitle": ["info"],
+        "varianttitles": ["info"],
     }
 
     def __init__(
@@ -832,6 +866,7 @@ class WikipediaPage:
         title: str,
         ns: WikiNamespace = Namespace.MAIN,
         language: str = "en",
+        variant: Optional[str] = None,
         url: Optional[str] = None,
     ) -> None:
         self.wiki = wiki
@@ -858,6 +893,7 @@ class WikipediaPage:
             "title": title,
             "ns": namespace2int(ns),
             "language": language,
+            "variant": variant,
         }  # type: dict[str, Any]
 
         if url is not None:
@@ -884,6 +920,16 @@ class WikipediaPage:
         """
         return str(self._attributes["language"])
 
+    @property
+    def variant(self) -> Optional[str]:
+        """
+        Returns language variant of the current page.
+
+        :return: language variant
+        """
+        v = self._attributes["variant"]
+        return str(v) if v else None
+
     @property
     def title(self) -> str:
         """
@@ -1067,6 +1113,11 @@ class WikipediaPage:
         return self
 
     def __repr__(self):
+        r = f"{self.title} (lang: {self.language}, variant: {self.variant}, "
         if any(self._called.values()):
-            return f"{self.title} (id: {self.pageid}, ns: {self.ns})"
-        return f"{self.title} (id: ??, ns: {self.ns})"
+            r += f"id: {self.pageid}, "
+        else:
+            r += "id: ??, "
+
+        r += f"ns: {self.ns})"
+        return r


Test patch:
diff --git a/tests/backlinks_test.py b/tests/backlinks_test.py
index 3261792..170144b 100644
--- a/tests/backlinks_test.py
+++ b/tests/backlinks_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestBackLinks(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_backlinks_nonexistent_count(self):
         page = self.wiki.page("Non_Existent")
diff --git a/tests/categories_test.py b/tests/categories_test.py
index 1f520e0..179114b 100644
--- a/tests/categories_test.py
+++ b/tests/categories_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestCategories(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_categories_count(self):
         page = self.wiki.page("Test_1")
diff --git a/tests/categorymembers_test.py b/tests/categorymembers_test.py
index cc25c5a..efb8109 100644
--- a/tests/categorymembers_test.py
+++ b/tests/categorymembers_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestCategoryMembers(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_links_single_page_count(self):
         page = self.wiki.page("Category:C1")
diff --git a/tests/extract_errors_test.py b/tests/extract_errors_test.py
index 0c04b20..632c30d 100644
--- a/tests/extract_errors_test.py
+++ b/tests/extract_errors_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestErrorsExtracts(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_title_before_fetching(self):
         page = self.wiki.page("NonExisting")
diff --git a/tests/extract_html_format_test.py b/tests/extract_html_format_test.py
index 9a37dfc..c71efb1 100644
--- a/tests/extract_html_format_test.py
+++ b/tests/extract_html_format_test.py
@@ -10,7 +10,7 @@ class TestHtmlFormatExtracts(unittest.TestCase):
         self.wiki = wikipediaapi.Wikipedia(
             user_agent, "en", extract_format=wikipediaapi.ExtractFormat.HTML
         )
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_title_before_fetching(self):
         page = self.wiki.page("Test_1")
diff --git a/tests/extract_wiki_format_test.py b/tests/extract_wiki_format_test.py
index 6ae3009..bc5e73a 100644
--- a/tests/extract_wiki_format_test.py
+++ b/tests/extract_wiki_format_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestWikiFormatExtracts(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_title_before_fetching(self):
         page = self.wiki.page("Test_1")
diff --git a/tests/langlinks_test.py b/tests/langlinks_test.py
index 8f582a4..7e5275e 100644
--- a/tests/langlinks_test.py
+++ b/tests/langlinks_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestLangLinks(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_langlinks_count(self):
         page = self.wiki.page("Test_1")
diff --git a/tests/links_test.py b/tests/links_test.py
index 813857b..123649f 100644
--- a/tests/links_test.py
+++ b/tests/links_test.py
@@ -8,7 +8,7 @@ import wikipediaapi
 class TestLinks(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_links_single_page_count(self):
         page = self.wiki.page("Test_1")
@@ -35,3 +35,12 @@ class TestLinks(unittest.TestCase):
     def test_links_no_links_count(self):
         page = self.wiki.page("No_Links")
         self.assertEqual(len(page.links), 0)
+
+    def test_links_from_variant(self):
+        wiki = wikipediaapi.Wikipedia(user_agent, "zh", "zh-tw")
+        wiki._query = wikipedia_api_request(wiki)
+        page = wiki.page("Test_Zh-Tw")
+        self.assertEqual(
+            list(sorted(map(lambda s: (s.title, s.variant), page.links.values()))),
+            [("Title - Zh-Tw - " + str(i + 1), "zh-tw") for i in range(3)],
+        )
diff --git a/tests/mock_data.py b/tests/mock_data.py
index fb1908d..b9bf38e 100644
--- a/tests/mock_data.py
+++ b/tests/mock_data.py
@@ -3,16 +3,20 @@
 user_agent = "UnitTests (bot@example.com)"
 
 
-def wikipedia_api_request(page, params):
-    query = ""
-    for k in sorted(params.keys()):
-        query += k + "=" + str(params[k]) + "&"
+def wikipedia_api_request(wiki):
+    def api_request(page, params):
+        used_params = wiki._construct_params(page, params)
+        query = ""
+        for k in sorted(used_params.keys()):
+            query += k + "=" + str(used_params[k]) + "&"
 
-    return _MOCK_DATA[page.language + ":" + query]
+        return _MOCK_DATA[page.language + ":" + query]
+
+    return api_request
 
 
 _MOCK_DATA = {
-    "en:action=query&explaintext=1&exsectionformat=wiki&prop=extracts&titles=Test_1&": {
+    "en:action=query&explaintext=1&exsectionformat=wiki&format=json&prop=extracts&redirects=1&titles=Test_1&": {
         "batchcomplete": "",
         "warnings": {
             "extracts": {
@@ -56,7 +60,7 @@ _MOCK_DATA = {
             },
         },
     },
-    "en:action=query&explaintext=1&exsectionformat=wiki&prop=extracts&titles=No_Sections&": {
+    "en:action=query&explaintext=1&exsectionformat=wiki&format=json&prop=extracts&redirects=1&titles=No_Sections&": {
         "batchcomplete": "",
         "warnings": {
             "extracts": {
@@ -75,7 +79,7 @@ _MOCK_DATA = {
             },
         },
     },
-    "en:action=query&prop=extracts&titles=Test_1&": {
+    "en:action=query&format=json&prop=extracts&redirects=1&titles=Test_1&": {
         "batchcomplete": "",
         "warnings": {
             "extracts": {
@@ -119,7 +123,7 @@ _MOCK_DATA = {
             },
         },
     },
-    "en:action=query&prop=extracts&titles=Test_Nested&": {
+    "en:action=query&format=json&prop=extracts&redirects=1&titles=Test_Nested&": {
         "batchcomplete": "",
         "warnings": {
             "extracts": {
@@ -158,7 +162,7 @@ _MOCK_DATA = {
             },
         },
     },
-    "en:action=query&prop=extracts&titles=Test_Edit&": {
+    "en:action=query&format=json&prop=extracts&redirects=1&titles=Test_Edit&": {
         "batchcomplete": "",
         "warnings": {
             "extracts": {
@@ -183,7 +187,7 @@ _MOCK_DATA = {
             },
         },
     },
-    "en:action=query&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle&prop=info&titles=Test_1&": {
+    "en:action=query&format=json&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle|varianttitles&prop=info&redirects=1&titles=Test_1&": {
         "batchcomplete": "",
         "query": {
             "normalized": [{"from": "Test_1", "to": "Test 1"}],
@@ -212,7 +216,7 @@ _MOCK_DATA = {
             },
         },
     },
-    "l1:action=query&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle&prop=info&titles=Test 1 - 1&": {
+    "l1:action=query&format=json&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle|varianttitles&prop=info&redirects=1&titles=Test 1 - 1&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -240,7 +244,7 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle&prop=info&titles=NonExisting&": {
+    "en:action=query&format=json&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle|varianttitles&prop=info&redirects=1&titles=NonExisting&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -265,7 +269,7 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&lllimit=500&llprop=url&prop=langlinks&titles=Test_1&": {
+    "en:action=query&format=json&lllimit=500&llprop=url&prop=langlinks&redirects=1&titles=Test_1&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -294,7 +298,7 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&lllimit=500&llprop=url&prop=langlinks&titles=No_LangLinks&": {
+    "en:action=query&format=json&lllimit=500&llprop=url&prop=langlinks&redirects=1&titles=No_LangLinks&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -306,7 +310,7 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&pllimit=500&prop=links&titles=Test_1&": {
+    "en:action=query&format=json&pllimit=500&prop=links&redirects=1&titles=Test_1&": {
         "query": {
             "pages": {
                 "4": {
@@ -322,7 +326,7 @@ _MOCK_DATA = {
             }
         }
     },
-    "en:action=query&pllimit=500&prop=links&titles=Test_2&": {
+    "en:action=query&format=json&pllimit=500&prop=links&redirects=1&titles=Test_2&": {
         "continue": {"plcontinue": "5|0|Title_-_4", "continue": "||"},
         "query": {
             "pages": {
@@ -339,7 +343,7 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&plcontinue=5|0|Title_-_4&pllimit=500&prop=links&titles=Test_2&": {
+    "en:action=query&format=json&plcontinue=5|0|Title_-_4&pllimit=500&prop=links&redirects=1&titles=Test_2&": {
         "query": {
             "pages": {
                 "4": {
@@ -354,7 +358,7 @@ _MOCK_DATA = {
             }
         }
     },
-    "en:action=query&pllimit=500&prop=links&titles=No_Links&": {
+    "en:action=query&format=json&pllimit=500&prop=links&redirects=1&titles=No_Links&": {
         "query": {
             "pages": {
                 "4": {
@@ -365,7 +369,7 @@ _MOCK_DATA = {
             }
         }
     },
-    "en:action=query&cllimit=500&prop=categories&titles=Test_1&": {
+    "en:action=query&cllimit=500&format=json&prop=categories&redirects=1&titles=Test_1&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -382,7 +386,7 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&cmlimit=500&cmtitle=Category:C1&list=categorymembers&": {
+    "en:action=query&cmlimit=500&cmtitle=Category:C1&format=json&list=categorymembers&redirects=1&": {
         "query": {
             "categorymembers": [
                 {"ns": 0, "pageid": 4, "title": "Title - 1"},
@@ -391,7 +395,7 @@ _MOCK_DATA = {
             ]
         }
     },
-    "en:action=query&cmlimit=500&cmtitle=Category:C2&list=categorymembers&": {
+    "en:action=query&cmlimit=500&cmtitle=Category:C2&format=json&list=categorymembers&redirects=1&": {
         "continue": {"cmcontinue": "5|0|Title_-_4", "continue": "-||"},
         "query": {
             "categorymembers": [
@@ -401,7 +405,7 @@ _MOCK_DATA = {
             ]
         },
     },
-    "en:action=query&cmcontinue=5|0|Title_-_4&cmlimit=500&cmtitle=Category:C2&list=categorymembers&": {
+    "en:action=query&cmcontinue=5|0|Title_-_4&cmlimit=500&cmtitle=Category:C2&format=json&list=categorymembers&redirects=1&": {
         "query": {
             "categorymembers": [
                 {"ns": 0, "pageid": 7, "title": "Title - 4"},
@@ -409,7 +413,7 @@ _MOCK_DATA = {
             ]
         }
     },
-    "en:action=query&cllimit=500&prop=categories&titles=No_Categories&": {
+    "en:action=query&cllimit=500&format=json&prop=categories&redirects=1&titles=No_Categories&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -421,10 +425,10 @@ _MOCK_DATA = {
             }
         },
     },
-    "en:action=query&bllimit=500&bltitle=Non_Existent&list=backlinks&": {
+    "en:action=query&bllimit=500&bltitle=Non_Existent&format=json&list=backlinks&redirects=1&": {
         "query": {"backlinks": []}
     },
-    "en:action=query&bllimit=500&bltitle=Test_1&list=backlinks&": {
+    "en:action=query&bllimit=500&bltitle=Test_1&format=json&list=backlinks&redirects=1&": {
         "query": {
             "backlinks": [
                 {"ns": 0, "title": "Title - 1"},
@@ -433,7 +437,7 @@ _MOCK_DATA = {
             ]
         }
     },
-    "en:action=query&bllimit=500&bltitle=Test_2&list=backlinks&": {
+    "en:action=query&bllimit=500&bltitle=Test_2&format=json&list=backlinks&redirects=1&": {
         "continue": {"blcontinue": "5|0|Title_-_4", "continue": "||"},
         "query": {
             "backlinks": [
@@ -443,7 +447,7 @@ _MOCK_DATA = {
             ]
         },
     },
-    "en:action=query&blcontinue=5|0|Title_-_4&bllimit=500&bltitle=Test_2&list=backlinks&": {
+    "en:action=query&blcontinue=5|0|Title_-_4&bllimit=500&bltitle=Test_2&format=json&list=backlinks&redirects=1&": {
         "query": {
             "backlinks": [
                 {"ns": 0, "title": "Title - 4"},
@@ -451,7 +455,7 @@ _MOCK_DATA = {
             ]
         }
     },
-    "hi:action=query&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle&prop=info&titles=पाइथन&": {
+    "hi:action=query&format=json&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle|varianttitles&prop=info&redirects=1&titles=पाइथन&": {
         "batchcomplete": "",
         "query": {
             "pages": {
@@ -479,4 +483,101 @@ _MOCK_DATA = {
             }
         },
     },
+    "zh:action=query&explaintext=1&exsectionformat=wiki&format=json&prop=extracts&redirects=1&titles=Test_Zh-Tw&variant=zh-tw&": {
+        "batchcomplete": "",
+        "warnings": {
+            "extracts": {
+                "*": '"exlimit" was too large for a whole article extracts request, lowered to 1.'
+            }
+        },
+        "query": {
+            "normalized": [{"from": "Test_Zh-Tw", "to": "Test Zh-Tw"}],
+            "pages": {
+                "4": {
+                    "pageid": 44,
+                    "ns": 0,
+                    "title": "Test Zh-Tw",
+                    "extract": ("ZH-TW\n\n\n"),
+                }
+            },
+        },
+    },
+    "zh:action=query&format=json&pllimit=500&prop=links&redirects=1&titles=Test_Zh-Tw&variant=zh-tw&": {
+        "query": {
+            "pages": {
+                "44": {
+                    "pageid": 44,
+                    "ns": 0,
+                    "title": "Test Zh-Tw",
+                    "links": [
+                        {"ns": 0, "title": "Title - Zh-Tw - 1"},
+                        {"ns": 0, "title": "Title - Zh-Tw - 2"},
+                        {"ns": 0, "title": "Title - Zh-Tw - 3"},
+                    ],
+                }
+            }
+        }
+    },
+    "zh:action=query&format=json&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle|varianttitles&prop=info&redirects=1&titles=Test_Zh-Tw&variant=zh-tw&": {
+        "batchcomplete": "",
+        "query": {
+            "pages": {
+                "44": {
+                    "pageid": 44,
+                    "ns": 0,
+                    "title": "Test Zh-Tw",
+                    "missing": "",
+                    "contentmodel": "wikitext",
+                    "pagelanguage": "zh",
+                    "pagelanguagehtmlcode": "zh",
+                    "pagelanguagedir": "ltr",
+                    "protection": [
+                        {"type": "create", "level": "sysop", "expiry": "infinity"}
+                    ],
+                    "restrictiontypes": ["create"],
+                    "notificationtimestamp": "",
+                    "fullurl": "https://zh.wikipedia.org/wiki/Test Zh-Tw",
+                    "editurl": "https://zh.wikipedia.org/w/index.php?title=Test Zh-Tw&action=edit",
+                    "canonicalurl": "https://zh.wikipedia.org/wiki/Test Zh-Tw",
+                    "readable": "",
+                    "preload": None,
+                    "displaytitle": "Test Zh-Tw",
+                    "varianttitles": {
+                        "zh": "Test Zh",
+                        "zh-hans": "Test Zh-Hans",
+                        "zh-tw": "Test Zh-Tw",
+                    },
+                }
+            }
+        },
+    },
+    "en:action=query&foo=bar&format=json&inprop=protection|talkid|watched|watchers|visitingwatchers|notificationtimestamp|subjectid|url|readable|preload|displaytitle|varianttitles&prop=info&redirects=1&titles=Extra_API_Params&": {
+        "batchcomplete": "",
+        "query": {
+            "normalized": [{"from": "Extra_API_Params", "to": "Extra API Params"}],
+            "pages": {
+                "4": {
+                    "pageid": 9,
+                    "ns": 0,
+                    "title": "Extra API Params",
+                    "missing": "",
+                    "contentmodel": "wikitext",
+                    "pagelanguage": "en",
+                    "pagelanguagehtmlcode": "en",
+                    "pagelanguagedir": "ltr",
+                    "protection": [
+                        {"type": "create", "level": "sysop", "expiry": "infinity"}
+                    ],
+                    "restrictiontypes": ["create"],
+                    "notificationtimestamp": "",
+                    "fullurl": "https://en.wikipedia.org/wiki/Extra_API_Params",
+                    "editurl": "https://en.wikipedia.org/w/index.php?title=Extra_API_Params&action=edit",
+                    "canonicalurl": "https://en.wikipedia.org/wiki/Extra_API_Params",
+                    "readable": "",
+                    "preload": None,
+                    "displaytitle": "Extra API Params",
+                }
+            },
+        },
+    },
 }
diff --git a/tests/wikipedia_page_test.py b/tests/wikipedia_page_test.py
index 8145e85..0d1dcd2 100644
--- a/tests/wikipedia_page_test.py
+++ b/tests/wikipedia_page_test.py
@@ -8,17 +8,17 @@ import wikipediaapi
 class TestWikipediaPage(unittest.TestCase):
     def setUp(self):
         self.wiki = wikipediaapi.Wikipedia(user_agent, "en")
-        self.wiki._query = wikipedia_api_request
+        self.wiki._query = wikipedia_api_request(self.wiki)
 
     def test_repr_before_fetching(self):
         page = self.wiki.page("Test_1")
-        self.assertEqual(repr(page), "Test_1 (id: ??, ns: 0)")
+        self.assertEqual(repr(page), "Test_1 (lang: en, variant: None, id: ??, ns: 0)")
 
     def test_repr_after_fetching(self):
         page = self.wiki.page("Test_1")
-        self.assertEqual(repr(page), "Test_1 (id: ??, ns: 0)")
+        self.assertEqual(repr(page), "Test_1 (lang: en, variant: None, id: ??, ns: 0)")
         self.assertEqual(page.pageid, 4)
-        self.assertEqual(repr(page), "Test 1 (id: 4, ns: 0)")
+        self.assertEqual(repr(page), "Test 1 (lang: en, variant: None, id: 4, ns: 0)")
 
     def test_extract(self):
         page = self.wiki.page("Test_1")
@@ -35,6 +35,7 @@ class TestWikipediaPage(unittest.TestCase):
         )
         self.assertEqual(page.canonicalurl, "https://en.wikipedia.org/wiki/Test_1")
         self.assertEqual(page.displaytitle, "Test 1")
+        self.assertEqual(page.variant, None)
 
     def test_unknown_property(self):
         page = self.wiki.page("Test_1")
@@ -57,7 +58,7 @@ class TestWikipediaPage(unittest.TestCase):
     def test_article_title_unquote(self):
         # https://github.com/goldsmith/Wikipedia/issues/190
         w = wikipediaapi.Wikipedia(user_agent, "hi")
-        w._query = wikipedia_api_request
+        w._query = wikipedia_api_request(w)
         p_encoded = w.article(
             "%E0%A4%AA%E0%A4%BE%E0%A4%87%E0%A4%A5%E0%A4%A8",
             unquote=True,
@@ -68,7 +69,7 @@ class TestWikipediaPage(unittest.TestCase):
     def test_page_title_unquote(self):
         # https://github.com/goldsmith/Wikipedia/issues/190
         w = wikipediaapi.Wikipedia(user_agent, "hi")
-        w._query = wikipedia_api_request
+        w._query = wikipedia_api_request(w)
         p_encoded = w.page(
             "%E0%A4%AA%E0%A4%BE%E0%A4%87%E0%A4%A5%E0%A4%A8",
             unquote=True,
@@ -80,3 +81,22 @@ class TestWikipediaPage(unittest.TestCase):
         page = self.wiki.page("NonExisting", ns=110)
         self.assertFalse(page.exists())
         self.assertEqual(110, page.namespace)
+
+    def test_page_with_variant(self):
+        wiki = wikipediaapi.Wikipedia(user_agent, "zh", "zh-tw")
+        wiki._query = wikipedia_api_request(wiki)
+        page = wiki.page("Test_Zh-Tw")
+        self.assertTrue(page.exists())
+        self.assertEqual(page.pageid, 44)
+        self.assertEqual(page.title, "Test Zh-Tw")
+        self.assertEqual(page.variant, "zh-tw")
+        self.assertEqual(
+            page.varianttitles,
+            {"zh": "Test Zh", "zh-hans": "Test Zh-Hans", "zh-tw": "Test Zh-Tw"},
+        )
+
+    def test_page_with_extra_parameters(self):
+        wiki = wikipediaapi.Wikipedia(user_agent, "en", extra_api_params={"foo": "bar"})
+        wiki._query = wikipedia_api_request(wiki)
+        page = wiki.page("Extra_API_Params")
+        self.assertTrue(page.exists())