├── .github ├── ISSUE_TEMPLATE │ └── report.yml ├── stale.yml └── workflows │ └── ci.yml ├── .gitignore ├── .travis.yml ├── .zed └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.rst ├── docs ├── Makefile ├── _build │ ├── doctrees │ │ ├── environment.pickle │ │ └── index.doctree │ └── html │ │ ├── .buildinfo │ │ ├── _sources │ │ └── index.rst.txt │ │ ├── _static │ │ ├── basic.css │ │ ├── doctools.js │ │ ├── documentation_options.js │ │ ├── file.png │ │ ├── jquery-3.5.1.js │ │ ├── jquery.js │ │ ├── language_data.js │ │ ├── minus.png │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ ├── solar.css │ │ ├── solarized-dark.css │ │ ├── subtle_dots.png │ │ ├── underscore-1.3.1.js │ │ └── underscore.js │ │ ├── index.html │ │ ├── objects.inv │ │ ├── py-modindex.html │ │ ├── search.html │ │ └── searchindex.js ├── _themes │ └── solar │ │ ├── NEWS.txt │ │ ├── README.rst │ │ ├── layout.html │ │ ├── static │ │ ├── solar.css │ │ ├── solarized-dark.css │ │ └── subtle_dots.png │ │ └── theme.conf ├── conf.py ├── index.rst └── make.bat ├── example └── translate_word_doc.py ├── googletrans ├── __init__.py ├── client.py ├── constants.py ├── gtoken.py ├── models.py ├── urls.py └── utils.py ├── pyproject.toml ├── pytest.ini ├── requirements.txt ├── test-requirements.txt ├── tests ├── __init__.py ├── conftest.py ├── test_client.py ├── test_gtoken.py └── test_utils.py ├── tox.ini ├── translate └── uv.lock /.github/ISSUE_TEMPLATE/report.yml: -------------------------------------------------------------------------------- 1 | name: Issue Report (Bug report or feature request) 2 | description: Report a bug or request a feature for the Googletrans library. 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: | 7 | Thank you for contributing to the Googletrans project! 8 | Please read the following carefully before submitting. 9 | 10 | **Note:** The following types of issues will be automatically closed: 11 | - Issues related to non-async function calls 12 | - Rate-limiting issues (this is a Google limitation) 13 | - Proxy configuration issues 14 | - Issues about exceeding the 15k character limit 15 | - Issues from versions prior to 4.0.1 16 | 17 | - type: checkboxes 18 | id: pre-submission-checklist 19 | attributes: 20 | label: "Before submitting, please confirm that:" 21 | options: 22 | - label: "I am using async/await syntax (non-sync calls are not supported since 4.0.0)" 23 | required: true 24 | - label: "This is not a rate-limiting issue or about exceeding the 15k character limit (Google's rate limits are not a library bug)" 25 | required: true 26 | - label: "I have checked the [README](https://github.com/ssut/py-googletrans#readme) for basic usage, known limitations, and have searched existing issues" 27 | required: true 28 | 29 | - type: dropdown 30 | id: googletrans-version 31 | attributes: 32 | label: "Googletrans version" 33 | description: "What version of Googletrans are you using?" 34 | options: 35 | - 4.0.1+ 36 | default: 0 37 | validations: 38 | required: true 39 | 40 | - type: dropdown 41 | id: issue-type 42 | attributes: 43 | label: "Issue Type" 44 | description: "What type of issue are you submitting?" 45 | options: 46 | - "Bug Report" 47 | - "Feature Request" 48 | validations: 49 | required: true 50 | 51 | - type: textarea 52 | id: current-behavior 53 | attributes: 54 | label: "Current Behavior" 55 | description: "Describe how the bug manifests or the current behavior you are trying to improve." 56 | placeholder: "Please provide a detailed description of the issue." 57 | validations: 58 | required: true 59 | 60 | - type: textarea 61 | id: expected-behavior 62 | attributes: 63 | label: "Expected Behavior" 64 | description: "Describe what the behavior would be without the bug or what you would like the feature to do." 65 | placeholder: "Please provide a detailed description of the expected outcome." 66 | validations: 67 | required: true 68 | 69 | - type: textarea 70 | id: steps-to-reproduce 71 | attributes: 72 | label: "Steps to Reproduce" 73 | description: "Please explain the steps required to duplicate the issue." 74 | placeholder: | 75 | 1. ... 76 | 2. ... 77 | 3. ... 78 | 79 | - type: textarea 80 | id: related-code 81 | attributes: 82 | label: "Related Code" 83 | description: "Please provide a code snippet demonstrating the issue (using async/await syntax)" 84 | placeholder: | 85 | ```python 86 | # Insert code snippets here 87 | ``` 88 | 89 | - type: textarea 90 | id: other-information 91 | attributes: 92 | label: "Other Information" 93 | description: "List any other relevant information, such as stack traces or error messages, here." 94 | placeholder: "Any additional information that might be helpful." 95 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - confirmed 9 | - hold 10 | # Label to use when marking an issue as stale 11 | staleLabel: wontfix 12 | # Comment to post when marking an issue as stale. Set to `false` to disable 13 | markComment: > 14 | This issue has been automatically marked as stale because it has not had 15 | recent activity. It will be closed if no further activity occurs. Thank you 16 | for your contributions. 17 | # Comment to post when closing a stale issue. Set to `false` to disable 18 | closeComment: false 19 | 20 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Python tests 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-24.04 10 | strategy: 11 | matrix: 12 | python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Install uv 17 | uses: astral-sh/setup-uv@v3 18 | with: 19 | enable-cache: true 20 | cache-dependency-glob: "requirements**.txt" 21 | - name: Set up Python ${{ matrix.python-version }} 22 | run: uv python install ${{ matrix.python-version }} 23 | - name: Install dependencies 24 | run: uv sync --all-extras --dev 25 | - name: Run tests with coverage 26 | run: | 27 | uv run python -m pytest --cov=googletrans --cov-report=xml 28 | - name: Upload coverage to Codecov 29 | uses: codecov/codecov-action@v4 30 | with: 31 | files: ./coverage.xml 32 | token: ${{ secrets.CODECOV_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | .venv/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .testmondata 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | .DS_Store 62 | .python-version 63 | 64 | # IDE 65 | .idea 66 | .vscode 67 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | dist: bionic 3 | python: 4 | - 3.6 5 | - 3.7 6 | - 3.8 7 | - pypy3 8 | install: 9 | - pip install tox-travis 10 | - pip install pytest-cov coveralls 11 | script: tox 12 | after_success: coveralls 13 | -------------------------------------------------------------------------------- /.zed/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "languages": { 3 | "Python": { 4 | "language_servers": ["pyright", "ruff"], 5 | "format_on_save": "on", 6 | "formatter": [ 7 | { 8 | "code_actions": { 9 | "source.fixAll.ruff": true, 10 | "source.organizeImports.ruff": true 11 | } 12 | }, 13 | { 14 | "language_server": { 15 | "name": "ruff" 16 | } 17 | } 18 | ] 19 | } 20 | }, 21 | "lsp": { 22 | "ruff": { 23 | "initialization_options": { 24 | "settings": { 25 | "path": "./pyproject.toml" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to this library are always welcome and highly encouraged :) 2 | 3 | This is a guide for you to get some ideas~ 4 | 5 | ## Dependencies 6 | 7 | To make sure that the following instructions work, please install the following dependencies 8 | on you machine: 9 | 10 | - coveralls==1.1 11 | 12 | ## Installation 13 | 14 | To get the source of `py-googletrans`, clone the git repository via: 15 | 16 | ```` 17 | $ git clone https://github.com/ssut/py-googletrans 18 | ```` 19 | This will clone the complete source to your local machine. 20 | 21 | ## Issue Reporting 22 | 23 | Feel free to report any issues that you come up with! 24 | Please follow the steps before reporting. We love keeping everything in a good manner :p 25 | 26 | ### Step 1: Checking Previous Issues 27 | 28 | There may be a lot of different issues related to different aspects. 29 | Here we list 12 main types: 30 | 31 | * [bug](https://github.com/ssut/py-googletrans/labels/bug) 32 | * [compromised](https://github.com/ssut/py-googletrans/labels/compromised) 33 | * [dependencies](https://github.com/ssut/py-googletrans/labels/dependencies) 34 | * [duplicate](https://github.com/ssut/py-googletrans/labels/duplicate) 35 | * [enhancement](https://github.com/ssut/py-googletrans/labels/enhancement) 36 | * [help wanted](https://github.com/ssut/py-googletrans/labels/help%20wanted) 37 | * [in progress](https://github.com/ssut/py-googletrans/labels/help%20wanted) 38 | * [invalid](https://github.com/ssut/py-googletrans/labels/invalid) 39 | 40 | Please see [About labels](https://docs.github.com/en/github/managing-your-work-on-github/about-labels) for more information. 41 | 42 | Note there is no labels for closed issues but still remember to have a look! 43 | 44 | ### Step 2: Formatting Your Comment 45 | 46 | Please see the [Issue Template](ISSUE_TEMPLATE.md). 47 | 48 | ## Pull Request Submitting 49 | 50 | > Inspired by [angular-translate](https://github.com/angular-translate/angular-translate/blob/master/CONTRIBUTING.md). 51 | - Check out a new branch based on master and name it to what you intend to do: 52 | - Example: 53 | ```` 54 | $ git checkout -b BRANCH_NAME origin/master 55 | ```` 56 | If you get an error, you may need to fetch master first by using 57 | ```` 58 | $ git remote update && git fetch 59 | ```` 60 | - Use one branch per fix/feature 61 | - Make your changes 62 | - Make sure to provide a spec for unit tests. 63 | - Run the tests ``pytest``. 64 | - Add a test for your feature or bug fix. 65 | - When all tests pass, everything's fine. If your changes are not 100% covered, go back and 66 | run the tests ``pytest`` again 67 | - Commit your changes 68 | - Please provide a git message that explains what you've done. 69 | - Please make sure your commits follow the [conventions](https://www.conventionalcommits.org/en/v1.0.0/) 70 | - Commit to the forked repository. 71 | - Make a pull request 72 | - Make sure you send the PR to the master branch. 73 | - Link the bug issue if there is one. 74 | - Travis CI is watching you! 75 | 76 | If you follow these instructions, your PR will land pretty safely in the main repo! 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 SuHun Han 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Googletrans 2 | =========== 3 | 4 | |GitHub license| |travis status| |Documentation Status| |PyPI version| 5 | |Coverage Status| |Code Climate| 6 | 7 | Googletrans is a **free** and **unlimited** python library that 8 | implemented Google Translate API. This uses the `Google Translate Ajax 9 | API `__ to make calls to such methods as 10 | detect and translate. 11 | 12 | Compatible with Python 3.8+. 13 | 14 | For details refer to the `API 15 | Documentation `__. 16 | 17 | Features 18 | -------- 19 | 20 | - Fast and reliable - it uses the same servers that 21 | translate.google.com uses 22 | - Auto language detection 23 | - Bulk translations 24 | - Customizable service URL 25 | - Async support 26 | - HTTP/2 support 27 | - Proxy support 28 | - Complete type hints 29 | 30 | HTTP/2 support 31 | ~~~~~~~~~~~~~~ 32 | 33 | This library uses httpx for HTTP requests so HTTP/2 is supported by default. 34 | 35 | You can check if http2 is enabled and working by the `._response.http_version` of `Translated` or `Detected` object: 36 | 37 | .. code:: python 38 | 39 | >>> translator.translate('테스트')._response.http_version 40 | # 'HTTP/2' 41 | 42 | 43 | How does this library work 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | You may wonder why this library works properly, whereas other 47 | approaches such like goslate won't work since Google has updated its 48 | translation service recently with a ticket mechanism to prevent a lot of 49 | crawler programs. 50 | 51 | I eventually figure out a way to generate a ticket by reverse 52 | engineering on the `obfuscated and minified code used by Google to 53 | generate such 54 | token `__, 55 | and implemented on the top of Python. However, this could be blocked at 56 | any time. 57 | 58 | -------------- 59 | 60 | Installation 61 | ------------ 62 | 63 | To install, either use things like pip with the package "googletrans" 64 | or download the package and put the "googletrans" directory into your 65 | python path. 66 | 67 | .. code:: bash 68 | 69 | $ pip install googletrans 70 | 71 | Basic Usage 72 | ----------- 73 | 74 | If source language is not given, google translate attempts to detect the 75 | source language. 76 | 77 | .. code:: python 78 | 79 | >>> import asyncio 80 | >>> from googletrans import Translator 81 | >>> 82 | >>> async def translate_text(): 83 | ... async with Translator() as translator: 84 | ... result = await translator.translate('안녕하세요.') 85 | ... print(result) # 86 | ... 87 | ... result = await translator.translate('안녕하세요.', dest='ja') 88 | ... print(result) # 89 | ... 90 | ... result = await translator.translate('veritas lux mea', src='la') 91 | ... print(result) # 92 | ... 93 | >>> asyncio.run(translate_text()) 94 | 95 | Customize service URL 96 | ~~~~~~~~~~~~~~~~~~~~~ 97 | 98 | You can use another google translate domain for translation. If multiple 99 | URLs are provided, it then randomly chooses a domain. 100 | 101 | .. code:: python 102 | 103 | >>> from googletrans import Translator 104 | >>> translator = Translator(service_urls=[ 105 | 'translate.google.com', 106 | 'translate.google.co.kr', 107 | ]) 108 | 109 | Customize service URL to point to standard api 110 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111 | 112 | Considering translate.google. url services use the webapp requiring a token, 113 | you can prefer to use the direct api than does not need any token to process. 114 | It can solve your problems of unstable token providing processes (refer to issue #234) 115 | 116 | .. code:: python 117 | 118 | >>> from googletrans import Translator 119 | >>> translator = Translator(service_urls=[ 120 | 'translate.googleapis.com' 121 | ]) 122 | 123 | 124 | Advanced Usage (Bulk) 125 | ~~~~~~~~~~~~~~~~~~~~~ 126 | 127 | Array can be used to translate a batch of strings in a single method 128 | call and a single HTTP session. The exact same method shown above works 129 | for arrays as well. 130 | 131 | .. code:: python 132 | 133 | >>> async def translate_bulk(): 134 | ... async with Translator() as translator: 135 | ... translations = await translator.translate(['The quick brown fox', 'jumps over', 'the lazy dog'], dest='ko') 136 | ... for translation in translations: 137 | ... print(translation.origin, ' -> ', translation.text) 138 | ... # The quick brown fox -> 빠른 갈색 여우 139 | ... # jumps over -> 이상 점프 140 | ... # the lazy dog -> 게으른 개 141 | ... 142 | >>> asyncio.run(translate_bulk()) 143 | 144 | Language detection 145 | ~~~~~~~~~~~~~~~~~~ 146 | 147 | The detect method, as its name implies, identifies the language used in 148 | a given sentence. 149 | 150 | .. code:: python 151 | 152 | >>> async def detect_languages(): 153 | ... async with Translator() as translator: 154 | ... result = await translator.detect('이 문장은 한글로 쓰여졌습니다.') 155 | ... print(result) # 156 | ... 157 | ... result = await translator.detect('この文章は日本語で書かれました。') 158 | ... print(result) # 159 | ... 160 | ... result = await translator.detect('This sentence is written in English.') 161 | ... print(result) # 162 | ... 163 | ... result = await translator.detect('Tiu frazo estas skribita en Esperanto.') 164 | ... print(result) # 165 | ... 166 | >>> asyncio.run(detect_languages()) 167 | 168 | GoogleTrans as a command line application 169 | ----------------------------------------- 170 | 171 | .. code:: bash 172 | 173 | $ translate -h 174 | usage: translate [-h] [-d DEST] [-s SRC] [-c] text 175 | 176 | Python Google Translator as a command-line tool 177 | 178 | positional arguments: 179 | text The text you want to translate. 180 | 181 | optional arguments: 182 | -h, --help show this help message and exit 183 | -d DEST, --dest DEST The destination language you want to translate. 184 | (Default: en) 185 | -s SRC, --src SRC The source language you want to translate. (Default: 186 | auto) 187 | -c, --detect 188 | 189 | $ translate "veritas lux mea" -s la -d en 190 | [veritas] veritas lux mea 191 | -> 192 | [en] The truth is my light 193 | [pron.] The truth is my light 194 | 195 | $ translate -c "안녕하세요." 196 | [ko, 1] 안녕하세요. 197 | 198 | -------------- 199 | 200 | Note on library usage 201 | --------------------- 202 | 203 | DISCLAIMER: this is an unofficial library using the web API of translate.google.com 204 | and also is not associated with Google. 205 | 206 | - **The maximum character limit on a single text is 15k.** 207 | 208 | - Due to limitations of the web version of google translate, this API 209 | does not guarantee that the library would work properly at all times 210 | (so please use this library if you don't care about stability). 211 | 212 | - **Important:** If you want to use a stable API, I highly recommend you to use 213 | `Google's official translate 214 | API `__. 215 | 216 | - If you get HTTP 5xx error or errors like #6, it's probably because 217 | Google has banned your client IP address. 218 | 219 | -------------- 220 | 221 | Versioning 222 | ---------- 223 | 224 | This library follows `Semantic Versioning `__ from 225 | v2.0.0. Any release versioned 0.x.y is subject to backwards incompatible 226 | changes at any time. 227 | 228 | Contributing 229 | ------------------------- 230 | 231 | Contributions are more than welcomed. See 232 | `CONTRIBUTING.md `__ 233 | 234 | ----------------------------------------- 235 | 236 | License 237 | ------- 238 | 239 | Googletrans is licensed under the MIT License. The terms are as 240 | follows: 241 | 242 | :: 243 | 244 | The MIT License (MIT) 245 | 246 | Copyright (c) 2015 SuHun Han 247 | 248 | Permission is hereby granted, free of charge, to any person obtaining a copy 249 | of this software and associated documentation files (the "Software"), to deal 250 | in the Software without restriction, including without limitation the rights 251 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 252 | copies of the Software, and to permit persons to whom the Software is 253 | furnished to do so, subject to the following conditions: 254 | 255 | The above copyright notice and this permission notice shall be included in all 256 | copies or substantial portions of the Software. 257 | 258 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 259 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 260 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 261 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 262 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 263 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 264 | SOFTWARE. 265 | 266 | .. |GitHub license| image:: https://img.shields.io/github/license/mashape/apistatus.svg 267 | :target: http://opensource.org/licenses/MIT 268 | .. |travis status| image:: https://github.com/ssut/py-googletrans/actions/workflows/ci.yml/badge.svg 269 | :target: https://github.com/ssut/py-googletrans/actions/workflows/ci.yml 270 | .. |Documentation Status| image:: https://readthedocs.org/projects/py-googletrans/badge/?version=latest 271 | :target: https://readthedocs.org/projects/py-googletrans/?badge=latest 272 | .. |PyPI version| image:: https://badge.fury.io/py/googletrans.svg 273 | :target: http://badge.fury.io/py/googletrans 274 | .. |Coverage Status| image:: https://coveralls.io/repos/github/ssut/py-googletrans/badge.svg 275 | :target: https://coveralls.io/github/ssut/py-googletrans 276 | .. |Code Climate| image:: https://codeclimate.com/github/ssut/py-googletrans/badges/gpa.svg 277 | :target: https://codeclimate.com/github/ssut/py-googletrans 278 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/py-googletrans.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/py-googletrans.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/py-googletrans" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/py-googletrans" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: fead46355d4b0b52081e4868f4b42e72 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | =============================================================== 2 | Googletrans: Free and Unlimited Google translate API for Python 3 | =============================================================== 4 | 5 | .. image:: https://img.shields.io/github/license/mashape/apistatus.svg 6 | :target: http://opensource.org/licenses/MIT 7 | .. image:: https://travis-ci.org/ssut/py-googletrans.svg?branch=master 8 | :target: https://travis-ci.org/ssut/py-googletrans 9 | .. image:: https://readthedocs.org/projects/py-googletrans/badge/?version=latest 10 | :target: https://readthedocs.org/projects/py-googletrans/?badge=latest 11 | .. image:: https://badge.fury.io/py/googletrans.svg 12 | :target: http://badge.fury.io/py/googletrans 13 | .. image:: https://coveralls.io/repos/github/ssut/py-googletrans/badge.svg 14 | :target: https://coveralls.io/github/ssut/py-googletrans 15 | .. image:: https://codeclimate.com/github/ssut/py-googletrans/badges/gpa.svg 16 | :target: https://codeclimate.com/github/ssut/py-googletrans 17 | 18 | Googletrans is a **free** and **unlimited** python library that 19 | implemented Google Translate API. This uses the `Google Translate Ajax 20 | API `__ to make calls to such methods as 21 | detect and translate. 22 | 23 | -------- 24 | Features 25 | -------- 26 | 27 | - Fast and reliable - it uses the same servers that 28 | translate.google.com uses 29 | - Auto language detection 30 | - Bulk translations 31 | - Customizable service URL 32 | - Connection pooling (the advantage of using requests.Session) 33 | - HTTP/2 support 34 | 35 | ~~~~~~~~~~~~~~~~~~~~~ 36 | Note on library usage 37 | ~~~~~~~~~~~~~~~~~~~~~ 38 | 39 | - The maximum character limit on a single text is 15k. 40 | 41 | - Due to limitations of the web version of google translate, this API 42 | does not guarantee that the library would work properly at all times. 43 | (so please use this library if you don't care about stability.) 44 | 45 | - If you want to use a stable API, I highly recommend you to use 46 | `Google's official translate 47 | API `__. 48 | 49 | - If you get HTTP 5xx error or errors like #6, it's probably because 50 | Google has banned your client IP address. 51 | 52 | ---------- 53 | Quickstart 54 | ---------- 55 | 56 | You can install it from PyPI_: 57 | 58 | .. sourcecode:: bash 59 | 60 | $ pip install googletrans 61 | 62 | .. _PyPI: https://pypi.python.org/pypi/googletrans 63 | 64 | ~~~~~~~~~~~~~~ 65 | HTTP/2 support 66 | ~~~~~~~~~~~~~~ 67 | 68 | This is a great deal for everyone! (up to 2x times faster in my test) If 69 | you want to get googletrans faster you should install 70 | `hyper `__ package. Googletrans will 71 | automatically detect if hyper is installed and if so, it will be used 72 | for http networking. 73 | 74 | ~~~~~~~~~~~ 75 | Basic Usage 76 | ~~~~~~~~~~~ 77 | 78 | If source language is not given, google translate attempts to detect the 79 | source language. 80 | 81 | .. code-block:: python 82 | 83 | >>> from googletrans import Translator 84 | >>> translator = Translator() 85 | >>> translator.translate('안녕하세요.') 86 | # 87 | 88 | >>> translator.translate('안녕하세요.', dest='ja') 89 | # 90 | 91 | >>> translator.translate('veritas lux mea', src='la') 92 | # 93 | 94 | ~~~~~~~~~~~~~~~~~~~~~ 95 | Customize service URL 96 | ~~~~~~~~~~~~~~~~~~~~~ 97 | 98 | You can use another google translate domain for translation. If multiple 99 | URLs are provided it then randomly chooses a domain. 100 | 101 | .. code:: python 102 | 103 | >>> from googletrans import Translator 104 | >>> translator = Translator(service_urls=[ 105 | 'translate.google.com', 106 | 'translate.google.co.kr', 107 | ]) 108 | 109 | ~~~~~~~~~~~~~~~~~~~~~ 110 | Advanced Usage (Bulk) 111 | ~~~~~~~~~~~~~~~~~~~~~ 112 | 113 | Array can be used to translate a batch of strings in a single method 114 | call and a single HTTP session. The exact same method shown above work 115 | for arrays as well. 116 | 117 | .. code:: python 118 | 119 | >>> translations = translator.translate(['The quick brown fox', 'jumps over', 'the lazy dog'], dest='ko') 120 | >>> for translation in translations: 121 | ... print(translation.origin, ' -> ', translation.text) 122 | # The quick brown fox -> 빠른 갈색 여우 123 | # jumps over -> 이상 점프 124 | # the lazy dog -> 게으른 개 125 | 126 | ~~~~~~~~~~~~~~~~~~ 127 | Language detection 128 | ~~~~~~~~~~~~~~~~~~ 129 | 130 | The detect method, as its name implies, identifies the language used in 131 | a given sentence. 132 | 133 | .. code:: python 134 | 135 | >>> translator.detect('이 문장은 한글로 쓰여졌습니다.') 136 | # 137 | >>> translator.detect('この文章は日本語で書かれました。') 138 | # 139 | >>> translator.detect('This sentence is written in English.') 140 | # 141 | >>> translator.detect('Tiu frazo estas skribita en Esperanto.') 142 | # 143 | 144 | --------- 145 | API Guide 146 | --------- 147 | 148 | 149 | ====================== 150 | googletrans.Translator 151 | ====================== 152 | 153 | .. autoclass:: googletrans.Translator 154 | :members: 155 | 156 | ================== 157 | googletrans.models 158 | ================== 159 | 160 | .. automodule:: googletrans.models 161 | :members: 162 | 163 | ================== 164 | googletrans.gtoken 165 | ================== 166 | 167 | .. hint:: 168 | 169 | This is for internal use only to generate a valid token to access 170 | translate.google.com ajax API. 171 | 172 | .. automodule:: googletrans.gtoken 173 | :members: 174 | 175 | ===================== 176 | googletrans.LANGUAGES 177 | ===================== 178 | 179 | .. hint:: 180 | 181 | iso639-1 language codes for 182 | `supported languages `_ 183 | for translation. Some language codes also include a country code, like zh-CN or zh-TW. 184 | 185 | .. literalinclude:: ../googletrans/constants.py 186 | :language: python 187 | :lines: 70-182 188 | :linenos: 189 | 190 | ================================ 191 | googletrans.DEFAULT_SERVICE_URLS 192 | ================================ 193 | 194 | .. hint:: 195 | 196 | `DEFAULT_SERVICE_URLS `_ is the list of current available Google Translation service urls. 197 | 198 | For using these service urls, please check `Customize service URL`_. -------------------------------------------------------------------------------- /docs/_build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | div.section::after { 19 | display: block; 20 | content: ''; 21 | clear: left; 22 | } 23 | 24 | /* -- relbar ---------------------------------------------------------------- */ 25 | 26 | div.related { 27 | width: 100%; 28 | font-size: 90%; 29 | } 30 | 31 | div.related h3 { 32 | display: none; 33 | } 34 | 35 | div.related ul { 36 | margin: 0; 37 | padding: 0 0 0 10px; 38 | list-style: none; 39 | } 40 | 41 | div.related li { 42 | display: inline; 43 | } 44 | 45 | div.related li.right { 46 | float: right; 47 | margin-right: 5px; 48 | } 49 | 50 | /* -- sidebar --------------------------------------------------------------- */ 51 | 52 | div.sphinxsidebarwrapper { 53 | padding: 10px 5px 0 10px; 54 | } 55 | 56 | div.sphinxsidebar { 57 | float: left; 58 | width: 230px; 59 | margin-left: -100%; 60 | font-size: 90%; 61 | word-wrap: break-word; 62 | overflow-wrap : break-word; 63 | } 64 | 65 | div.sphinxsidebar ul { 66 | list-style: none; 67 | } 68 | 69 | div.sphinxsidebar ul ul, 70 | div.sphinxsidebar ul.want-points { 71 | margin-left: 20px; 72 | list-style: square; 73 | } 74 | 75 | div.sphinxsidebar ul ul { 76 | margin-top: 0; 77 | margin-bottom: 0; 78 | } 79 | 80 | div.sphinxsidebar form { 81 | margin-top: 10px; 82 | } 83 | 84 | div.sphinxsidebar input { 85 | border: 1px solid #98dbcc; 86 | font-family: sans-serif; 87 | font-size: 1em; 88 | } 89 | 90 | div.sphinxsidebar #searchbox form.search { 91 | overflow: hidden; 92 | } 93 | 94 | div.sphinxsidebar #searchbox input[type="text"] { 95 | float: left; 96 | width: 80%; 97 | padding: 0.25em; 98 | box-sizing: border-box; 99 | } 100 | 101 | div.sphinxsidebar #searchbox input[type="submit"] { 102 | float: left; 103 | width: 20%; 104 | border-left: none; 105 | padding: 0.25em; 106 | box-sizing: border-box; 107 | } 108 | 109 | 110 | img { 111 | border: 0; 112 | max-width: 100%; 113 | } 114 | 115 | /* -- search page ----------------------------------------------------------- */ 116 | 117 | ul.search { 118 | margin: 10px 0 0 20px; 119 | padding: 0; 120 | } 121 | 122 | ul.search li { 123 | padding: 5px 0 5px 20px; 124 | background-image: url(file.png); 125 | background-repeat: no-repeat; 126 | background-position: 0 7px; 127 | } 128 | 129 | ul.search li a { 130 | font-weight: bold; 131 | } 132 | 133 | ul.search li div.context { 134 | color: #888; 135 | margin: 2px 0 0 30px; 136 | text-align: left; 137 | } 138 | 139 | ul.keywordmatches li.goodmatch a { 140 | font-weight: bold; 141 | } 142 | 143 | /* -- index page ------------------------------------------------------------ */ 144 | 145 | table.contentstable { 146 | width: 90%; 147 | margin-left: auto; 148 | margin-right: auto; 149 | } 150 | 151 | table.contentstable p.biglink { 152 | line-height: 150%; 153 | } 154 | 155 | a.biglink { 156 | font-size: 1.3em; 157 | } 158 | 159 | span.linkdescr { 160 | font-style: italic; 161 | padding-top: 5px; 162 | font-size: 90%; 163 | } 164 | 165 | /* -- general index --------------------------------------------------------- */ 166 | 167 | table.indextable { 168 | width: 100%; 169 | } 170 | 171 | table.indextable td { 172 | text-align: left; 173 | vertical-align: top; 174 | } 175 | 176 | table.indextable ul { 177 | margin-top: 0; 178 | margin-bottom: 0; 179 | list-style-type: none; 180 | } 181 | 182 | table.indextable > tbody > tr > td > ul { 183 | padding-left: 0em; 184 | } 185 | 186 | table.indextable tr.pcap { 187 | height: 10px; 188 | } 189 | 190 | table.indextable tr.cap { 191 | margin-top: 10px; 192 | background-color: #f2f2f2; 193 | } 194 | 195 | img.toggler { 196 | margin-right: 3px; 197 | margin-top: 3px; 198 | cursor: pointer; 199 | } 200 | 201 | div.modindex-jumpbox { 202 | border-top: 1px solid #ddd; 203 | border-bottom: 1px solid #ddd; 204 | margin: 1em 0 1em 0; 205 | padding: 0.4em; 206 | } 207 | 208 | div.genindex-jumpbox { 209 | border-top: 1px solid #ddd; 210 | border-bottom: 1px solid #ddd; 211 | margin: 1em 0 1em 0; 212 | padding: 0.4em; 213 | } 214 | 215 | /* -- domain module index --------------------------------------------------- */ 216 | 217 | table.modindextable td { 218 | padding: 2px; 219 | border-collapse: collapse; 220 | } 221 | 222 | /* -- general body styles --------------------------------------------------- */ 223 | 224 | div.body { 225 | min-width: 450px; 226 | max-width: 800px; 227 | } 228 | 229 | div.body p, div.body dd, div.body li, div.body blockquote { 230 | -moz-hyphens: auto; 231 | -ms-hyphens: auto; 232 | -webkit-hyphens: auto; 233 | hyphens: auto; 234 | } 235 | 236 | a.headerlink { 237 | visibility: hidden; 238 | } 239 | 240 | a.brackets:before, 241 | span.brackets > a:before{ 242 | content: "["; 243 | } 244 | 245 | a.brackets:after, 246 | span.brackets > a:after { 247 | content: "]"; 248 | } 249 | 250 | h1:hover > a.headerlink, 251 | h2:hover > a.headerlink, 252 | h3:hover > a.headerlink, 253 | h4:hover > a.headerlink, 254 | h5:hover > a.headerlink, 255 | h6:hover > a.headerlink, 256 | dt:hover > a.headerlink, 257 | caption:hover > a.headerlink, 258 | p.caption:hover > a.headerlink, 259 | div.code-block-caption:hover > a.headerlink { 260 | visibility: visible; 261 | } 262 | 263 | div.body p.caption { 264 | text-align: inherit; 265 | } 266 | 267 | div.body td { 268 | text-align: left; 269 | } 270 | 271 | .first { 272 | margin-top: 0 !important; 273 | } 274 | 275 | p.rubric { 276 | margin-top: 30px; 277 | font-weight: bold; 278 | } 279 | 280 | img.align-left, .figure.align-left, object.align-left { 281 | clear: left; 282 | float: left; 283 | margin-right: 1em; 284 | } 285 | 286 | img.align-right, .figure.align-right, object.align-right { 287 | clear: right; 288 | float: right; 289 | margin-left: 1em; 290 | } 291 | 292 | img.align-center, .figure.align-center, object.align-center { 293 | display: block; 294 | margin-left: auto; 295 | margin-right: auto; 296 | } 297 | 298 | img.align-default, .figure.align-default { 299 | display: block; 300 | margin-left: auto; 301 | margin-right: auto; 302 | } 303 | 304 | .align-left { 305 | text-align: left; 306 | } 307 | 308 | .align-center { 309 | text-align: center; 310 | } 311 | 312 | .align-default { 313 | text-align: center; 314 | } 315 | 316 | .align-right { 317 | text-align: right; 318 | } 319 | 320 | /* -- sidebars -------------------------------------------------------------- */ 321 | 322 | div.sidebar { 323 | margin: 0 0 0.5em 1em; 324 | border: 1px solid #ddb; 325 | padding: 7px; 326 | background-color: #ffe; 327 | width: 40%; 328 | float: right; 329 | clear: right; 330 | overflow-x: auto; 331 | } 332 | 333 | p.sidebar-title { 334 | font-weight: bold; 335 | } 336 | 337 | div.admonition, div.topic, blockquote { 338 | clear: left; 339 | } 340 | 341 | /* -- topics ---------------------------------------------------------------- */ 342 | 343 | div.topic { 344 | border: 1px solid #ccc; 345 | padding: 7px; 346 | margin: 10px 0 10px 0; 347 | } 348 | 349 | p.topic-title { 350 | font-size: 1.1em; 351 | font-weight: bold; 352 | margin-top: 10px; 353 | } 354 | 355 | /* -- admonitions ----------------------------------------------------------- */ 356 | 357 | div.admonition { 358 | margin-top: 10px; 359 | margin-bottom: 10px; 360 | padding: 7px; 361 | } 362 | 363 | div.admonition dt { 364 | font-weight: bold; 365 | } 366 | 367 | p.admonition-title { 368 | margin: 0px 10px 5px 0px; 369 | font-weight: bold; 370 | } 371 | 372 | div.body p.centered { 373 | text-align: center; 374 | margin-top: 25px; 375 | } 376 | 377 | /* -- content of sidebars/topics/admonitions -------------------------------- */ 378 | 379 | div.sidebar > :last-child, 380 | div.topic > :last-child, 381 | div.admonition > :last-child { 382 | margin-bottom: 0; 383 | } 384 | 385 | div.sidebar::after, 386 | div.topic::after, 387 | div.admonition::after, 388 | blockquote::after { 389 | display: block; 390 | content: ''; 391 | clear: both; 392 | } 393 | 394 | /* -- tables ---------------------------------------------------------------- */ 395 | 396 | table.docutils { 397 | margin-top: 10px; 398 | margin-bottom: 10px; 399 | border: 0; 400 | border-collapse: collapse; 401 | } 402 | 403 | table.align-center { 404 | margin-left: auto; 405 | margin-right: auto; 406 | } 407 | 408 | table.align-default { 409 | margin-left: auto; 410 | margin-right: auto; 411 | } 412 | 413 | table caption span.caption-number { 414 | font-style: italic; 415 | } 416 | 417 | table caption span.caption-text { 418 | } 419 | 420 | table.docutils td, table.docutils th { 421 | padding: 1px 8px 1px 5px; 422 | border-top: 0; 423 | border-left: 0; 424 | border-right: 0; 425 | border-bottom: 1px solid #aaa; 426 | } 427 | 428 | table.footnote td, table.footnote th { 429 | border: 0 !important; 430 | } 431 | 432 | th { 433 | text-align: left; 434 | padding-right: 5px; 435 | } 436 | 437 | table.citation { 438 | border-left: solid 1px gray; 439 | margin-left: 1px; 440 | } 441 | 442 | table.citation td { 443 | border-bottom: none; 444 | } 445 | 446 | th > :first-child, 447 | td > :first-child { 448 | margin-top: 0px; 449 | } 450 | 451 | th > :last-child, 452 | td > :last-child { 453 | margin-bottom: 0px; 454 | } 455 | 456 | /* -- figures --------------------------------------------------------------- */ 457 | 458 | div.figure { 459 | margin: 0.5em; 460 | padding: 0.5em; 461 | } 462 | 463 | div.figure p.caption { 464 | padding: 0.3em; 465 | } 466 | 467 | div.figure p.caption span.caption-number { 468 | font-style: italic; 469 | } 470 | 471 | div.figure p.caption span.caption-text { 472 | } 473 | 474 | /* -- field list styles ----------------------------------------------------- */ 475 | 476 | table.field-list td, table.field-list th { 477 | border: 0 !important; 478 | } 479 | 480 | .field-list ul { 481 | margin: 0; 482 | padding-left: 1em; 483 | } 484 | 485 | .field-list p { 486 | margin: 0; 487 | } 488 | 489 | .field-name { 490 | -moz-hyphens: manual; 491 | -ms-hyphens: manual; 492 | -webkit-hyphens: manual; 493 | hyphens: manual; 494 | } 495 | 496 | /* -- hlist styles ---------------------------------------------------------- */ 497 | 498 | table.hlist { 499 | margin: 1em 0; 500 | } 501 | 502 | table.hlist td { 503 | vertical-align: top; 504 | } 505 | 506 | 507 | /* -- other body styles ----------------------------------------------------- */ 508 | 509 | ol.arabic { 510 | list-style: decimal; 511 | } 512 | 513 | ol.loweralpha { 514 | list-style: lower-alpha; 515 | } 516 | 517 | ol.upperalpha { 518 | list-style: upper-alpha; 519 | } 520 | 521 | ol.lowerroman { 522 | list-style: lower-roman; 523 | } 524 | 525 | ol.upperroman { 526 | list-style: upper-roman; 527 | } 528 | 529 | :not(li) > ol > li:first-child > :first-child, 530 | :not(li) > ul > li:first-child > :first-child { 531 | margin-top: 0px; 532 | } 533 | 534 | :not(li) > ol > li:last-child > :last-child, 535 | :not(li) > ul > li:last-child > :last-child { 536 | margin-bottom: 0px; 537 | } 538 | 539 | ol.simple ol p, 540 | ol.simple ul p, 541 | ul.simple ol p, 542 | ul.simple ul p { 543 | margin-top: 0; 544 | } 545 | 546 | ol.simple > li:not(:first-child) > p, 547 | ul.simple > li:not(:first-child) > p { 548 | margin-top: 0; 549 | } 550 | 551 | ol.simple p, 552 | ul.simple p { 553 | margin-bottom: 0; 554 | } 555 | 556 | dl.footnote > dt, 557 | dl.citation > dt { 558 | float: left; 559 | margin-right: 0.5em; 560 | } 561 | 562 | dl.footnote > dd, 563 | dl.citation > dd { 564 | margin-bottom: 0em; 565 | } 566 | 567 | dl.footnote > dd:after, 568 | dl.citation > dd:after { 569 | content: ""; 570 | clear: both; 571 | } 572 | 573 | dl.field-list { 574 | display: grid; 575 | grid-template-columns: fit-content(30%) auto; 576 | } 577 | 578 | dl.field-list > dt { 579 | font-weight: bold; 580 | word-break: break-word; 581 | padding-left: 0.5em; 582 | padding-right: 5px; 583 | } 584 | 585 | dl.field-list > dt:after { 586 | content: ":"; 587 | } 588 | 589 | dl.field-list > dd { 590 | padding-left: 0.5em; 591 | margin-top: 0em; 592 | margin-left: 0em; 593 | margin-bottom: 0em; 594 | } 595 | 596 | dl { 597 | margin-bottom: 15px; 598 | } 599 | 600 | dd > :first-child { 601 | margin-top: 0px; 602 | } 603 | 604 | dd ul, dd table { 605 | margin-bottom: 10px; 606 | } 607 | 608 | dd { 609 | margin-top: 3px; 610 | margin-bottom: 10px; 611 | margin-left: 30px; 612 | } 613 | 614 | dl > dd:last-child, 615 | dl > dd:last-child > :last-child { 616 | margin-bottom: 0; 617 | } 618 | 619 | dt:target, span.highlighted { 620 | background-color: #fbe54e; 621 | } 622 | 623 | rect.highlighted { 624 | fill: #fbe54e; 625 | } 626 | 627 | dl.glossary dt { 628 | font-weight: bold; 629 | font-size: 1.1em; 630 | } 631 | 632 | .optional { 633 | font-size: 1.3em; 634 | } 635 | 636 | .sig-paren { 637 | font-size: larger; 638 | } 639 | 640 | .versionmodified { 641 | font-style: italic; 642 | } 643 | 644 | .system-message { 645 | background-color: #fda; 646 | padding: 5px; 647 | border: 3px solid red; 648 | } 649 | 650 | .footnote:target { 651 | background-color: #ffa; 652 | } 653 | 654 | .line-block { 655 | display: block; 656 | margin-top: 1em; 657 | margin-bottom: 1em; 658 | } 659 | 660 | .line-block .line-block { 661 | margin-top: 0; 662 | margin-bottom: 0; 663 | margin-left: 1.5em; 664 | } 665 | 666 | .guilabel, .menuselection { 667 | font-family: sans-serif; 668 | } 669 | 670 | .accelerator { 671 | text-decoration: underline; 672 | } 673 | 674 | .classifier { 675 | font-style: oblique; 676 | } 677 | 678 | .classifier:before { 679 | font-style: normal; 680 | margin: 0.5em; 681 | content: ":"; 682 | } 683 | 684 | abbr, acronym { 685 | border-bottom: dotted 1px; 686 | cursor: help; 687 | } 688 | 689 | /* -- code displays --------------------------------------------------------- */ 690 | 691 | pre { 692 | overflow: auto; 693 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 694 | } 695 | 696 | pre, div[class*="highlight-"] { 697 | clear: both; 698 | } 699 | 700 | span.pre { 701 | -moz-hyphens: none; 702 | -ms-hyphens: none; 703 | -webkit-hyphens: none; 704 | hyphens: none; 705 | } 706 | 707 | div[class*="highlight-"] { 708 | margin: 1em 0; 709 | } 710 | 711 | td.linenos pre { 712 | border: 0; 713 | background-color: transparent; 714 | color: #aaa; 715 | } 716 | 717 | table.highlighttable { 718 | display: block; 719 | } 720 | 721 | table.highlighttable tbody { 722 | display: block; 723 | } 724 | 725 | table.highlighttable tr { 726 | display: flex; 727 | } 728 | 729 | table.highlighttable td { 730 | margin: 0; 731 | padding: 0; 732 | } 733 | 734 | table.highlighttable td.linenos { 735 | padding-right: 0.5em; 736 | } 737 | 738 | table.highlighttable td.code { 739 | flex: 1; 740 | overflow: hidden; 741 | } 742 | 743 | .highlight .hll { 744 | display: block; 745 | } 746 | 747 | div.highlight pre, 748 | table.highlighttable pre { 749 | margin: 0; 750 | } 751 | 752 | div.code-block-caption + div { 753 | margin-top: 0; 754 | } 755 | 756 | div.code-block-caption { 757 | margin-top: 1em; 758 | padding: 2px 5px; 759 | font-size: small; 760 | } 761 | 762 | div.code-block-caption code { 763 | background-color: transparent; 764 | } 765 | 766 | table.highlighttable td.linenos, 767 | div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */ 768 | user-select: none; 769 | } 770 | 771 | div.code-block-caption span.caption-number { 772 | padding: 0.1em 0.3em; 773 | font-style: italic; 774 | } 775 | 776 | div.code-block-caption span.caption-text { 777 | } 778 | 779 | div.literal-block-wrapper { 780 | margin: 1em 0; 781 | } 782 | 783 | code.descname { 784 | background-color: transparent; 785 | font-weight: bold; 786 | font-size: 1.2em; 787 | } 788 | 789 | code.descclassname { 790 | background-color: transparent; 791 | } 792 | 793 | code.xref, a code { 794 | background-color: transparent; 795 | font-weight: bold; 796 | } 797 | 798 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 799 | background-color: transparent; 800 | } 801 | 802 | .viewcode-link { 803 | float: right; 804 | } 805 | 806 | .viewcode-back { 807 | float: right; 808 | font-family: sans-serif; 809 | } 810 | 811 | div.viewcode-block:target { 812 | margin: -1px -10px; 813 | padding: 0 10px; 814 | } 815 | 816 | /* -- math display ---------------------------------------------------------- */ 817 | 818 | img.math { 819 | vertical-align: middle; 820 | } 821 | 822 | div.body div.math p { 823 | text-align: center; 824 | } 825 | 826 | span.eqno { 827 | float: right; 828 | } 829 | 830 | span.eqno a.headerlink { 831 | position: absolute; 832 | z-index: 1; 833 | } 834 | 835 | div.math:hover a.headerlink { 836 | visibility: visible; 837 | } 838 | 839 | /* -- printout stylesheet --------------------------------------------------- */ 840 | 841 | @media print { 842 | div.document, 843 | div.documentwrapper, 844 | div.bodywrapper { 845 | margin: 0 !important; 846 | width: 100%; 847 | } 848 | 849 | div.sphinxsidebar, 850 | div.related, 851 | div.footer, 852 | #top-link { 853 | display: none; 854 | } 855 | } -------------------------------------------------------------------------------- /docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && 74 | !jQuery(node.parentNode).hasClass(className) && 75 | !jQuery(node.parentNode).hasClass("nohighlight")) { 76 | var span; 77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 78 | if (isInSVG) { 79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 80 | } else { 81 | span = document.createElement("span"); 82 | span.className = className; 83 | } 84 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 86 | document.createTextNode(val.substr(pos + text.length)), 87 | node.nextSibling)); 88 | node.nodeValue = val.substr(0, pos); 89 | if (isInSVG) { 90 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 91 | var bbox = node.parentElement.getBBox(); 92 | rect.x.baseVal.value = bbox.x; 93 | rect.y.baseVal.value = bbox.y; 94 | rect.width.baseVal.value = bbox.width; 95 | rect.height.baseVal.value = bbox.height; 96 | rect.setAttribute('class', className); 97 | addItems.push({ 98 | "parent": node.parentNode, 99 | "target": rect}); 100 | } 101 | } 102 | } 103 | else if (!jQuery(node).is("button, select, textarea")) { 104 | jQuery.each(node.childNodes, function() { 105 | highlight(this, addItems); 106 | }); 107 | } 108 | } 109 | var addItems = []; 110 | var result = this.each(function() { 111 | highlight(this, addItems); 112 | }); 113 | for (var i = 0; i < addItems.length; ++i) { 114 | jQuery(addItems[i].parent).before(addItems[i].target); 115 | } 116 | return result; 117 | }; 118 | 119 | /* 120 | * backward compatibility for jQuery.browser 121 | * This will be supported until firefox bug is fixed. 122 | */ 123 | if (!jQuery.browser) { 124 | jQuery.uaMatch = function(ua) { 125 | ua = ua.toLowerCase(); 126 | 127 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 128 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 129 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 130 | /(msie) ([\w.]+)/.exec(ua) || 131 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 132 | []; 133 | 134 | return { 135 | browser: match[ 1 ] || "", 136 | version: match[ 2 ] || "0" 137 | }; 138 | }; 139 | jQuery.browser = {}; 140 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 141 | } 142 | 143 | /** 144 | * Small JavaScript module for the documentation. 145 | */ 146 | var Documentation = { 147 | 148 | init : function() { 149 | this.fixFirefoxAnchorBug(); 150 | this.highlightSearchWords(); 151 | this.initIndexTable(); 152 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { 153 | this.initOnKeyListeners(); 154 | } 155 | }, 156 | 157 | /** 158 | * i18n support 159 | */ 160 | TRANSLATIONS : {}, 161 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 162 | LOCALE : 'unknown', 163 | 164 | // gettext and ngettext don't access this so that the functions 165 | // can safely bound to a different name (_ = Documentation.gettext) 166 | gettext : function(string) { 167 | var translated = Documentation.TRANSLATIONS[string]; 168 | if (typeof translated === 'undefined') 169 | return string; 170 | return (typeof translated === 'string') ? translated : translated[0]; 171 | }, 172 | 173 | ngettext : function(singular, plural, n) { 174 | var translated = Documentation.TRANSLATIONS[singular]; 175 | if (typeof translated === 'undefined') 176 | return (n == 1) ? singular : plural; 177 | return translated[Documentation.PLURALEXPR(n)]; 178 | }, 179 | 180 | addTranslations : function(catalog) { 181 | for (var key in catalog.messages) 182 | this.TRANSLATIONS[key] = catalog.messages[key]; 183 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 184 | this.LOCALE = catalog.locale; 185 | }, 186 | 187 | /** 188 | * add context elements like header anchor links 189 | */ 190 | addContextElements : function() { 191 | $('div[id] > :header:first').each(function() { 192 | $('\u00B6'). 193 | attr('href', '#' + this.id). 194 | attr('title', _('Permalink to this headline')). 195 | appendTo(this); 196 | }); 197 | $('dt[id]').each(function() { 198 | $('\u00B6'). 199 | attr('href', '#' + this.id). 200 | attr('title', _('Permalink to this definition')). 201 | appendTo(this); 202 | }); 203 | }, 204 | 205 | /** 206 | * workaround a firefox stupidity 207 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 208 | */ 209 | fixFirefoxAnchorBug : function() { 210 | if (document.location.hash && $.browser.mozilla) 211 | window.setTimeout(function() { 212 | document.location.href += ''; 213 | }, 10); 214 | }, 215 | 216 | /** 217 | * highlight the search words provided in the url in the text 218 | */ 219 | highlightSearchWords : function() { 220 | var params = $.getQueryParameters(); 221 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 222 | if (terms.length) { 223 | var body = $('div.body'); 224 | if (!body.length) { 225 | body = $('body'); 226 | } 227 | window.setTimeout(function() { 228 | $.each(terms, function() { 229 | body.highlightText(this.toLowerCase(), 'highlighted'); 230 | }); 231 | }, 10); 232 | $('') 234 | .appendTo($('#searchbox')); 235 | } 236 | }, 237 | 238 | /** 239 | * init the domain index toggle buttons 240 | */ 241 | initIndexTable : function() { 242 | var togglers = $('img.toggler').click(function() { 243 | var src = $(this).attr('src'); 244 | var idnum = $(this).attr('id').substr(7); 245 | $('tr.cg-' + idnum).toggle(); 246 | if (src.substr(-9) === 'minus.png') 247 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 248 | else 249 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 250 | }).css('display', ''); 251 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 252 | togglers.click(); 253 | } 254 | }, 255 | 256 | /** 257 | * helper function to hide the search marks again 258 | */ 259 | hideSearchWords : function() { 260 | $('#searchbox .highlight-link').fadeOut(300); 261 | $('span.highlighted').removeClass('highlighted'); 262 | }, 263 | 264 | /** 265 | * make the url absolute 266 | */ 267 | makeURL : function(relativeURL) { 268 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 269 | }, 270 | 271 | /** 272 | * get the current relative url 273 | */ 274 | getCurrentURL : function() { 275 | var path = document.location.pathname; 276 | var parts = path.split(/\//); 277 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 278 | if (this === '..') 279 | parts.pop(); 280 | }); 281 | var url = parts.join('/'); 282 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 283 | }, 284 | 285 | initOnKeyListeners: function() { 286 | $(document).keydown(function(event) { 287 | var activeElementType = document.activeElement.tagName; 288 | // don't navigate when in search box or textarea 289 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' 290 | && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) { 291 | switch (event.keyCode) { 292 | case 37: // left 293 | var prevHref = $('link[rel="prev"]').prop('href'); 294 | if (prevHref) { 295 | window.location.href = prevHref; 296 | return false; 297 | } 298 | case 39: // right 299 | var nextHref = $('link[rel="next"]').prop('href'); 300 | if (nextHref) { 301 | window.location.href = nextHref; 302 | return false; 303 | } 304 | } 305 | } 306 | }); 307 | } 308 | }; 309 | 310 | // quick alias for translations 311 | _ = Documentation.gettext; 312 | 313 | $(document).ready(function() { 314 | Documentation.init(); 315 | }); 316 | -------------------------------------------------------------------------------- /docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '3.0.0', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | LINK_SUFFIX: '.html', 9 | HAS_SOURCE: true, 10 | SOURCELINK_SUFFIX: '.txt', 11 | NAVIGATION_WITH_KEYS: false 12 | }; -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * language_data.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * This script contains the language-specific data used by searchtools.js, 6 | * namely the list of stopwords, stemmer, scorer and splitter. 7 | * 8 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; 14 | 15 | 16 | /* Non-minified version JS is _stemmer.js if file is provided */ 17 | /** 18 | * Porter Stemmer 19 | */ 20 | var Stemmer = function() { 21 | 22 | var step2list = { 23 | ational: 'ate', 24 | tional: 'tion', 25 | enci: 'ence', 26 | anci: 'ance', 27 | izer: 'ize', 28 | bli: 'ble', 29 | alli: 'al', 30 | entli: 'ent', 31 | eli: 'e', 32 | ousli: 'ous', 33 | ization: 'ize', 34 | ation: 'ate', 35 | ator: 'ate', 36 | alism: 'al', 37 | iveness: 'ive', 38 | fulness: 'ful', 39 | ousness: 'ous', 40 | aliti: 'al', 41 | iviti: 'ive', 42 | biliti: 'ble', 43 | logi: 'log' 44 | }; 45 | 46 | var step3list = { 47 | icate: 'ic', 48 | ative: '', 49 | alize: 'al', 50 | iciti: 'ic', 51 | ical: 'ic', 52 | ful: '', 53 | ness: '' 54 | }; 55 | 56 | var c = "[^aeiou]"; // consonant 57 | var v = "[aeiouy]"; // vowel 58 | var C = c + "[^aeiouy]*"; // consonant sequence 59 | var V = v + "[aeiou]*"; // vowel sequence 60 | 61 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 62 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 63 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 64 | var s_v = "^(" + C + ")?" + v; // vowel in stem 65 | 66 | this.stemWord = function (w) { 67 | var stem; 68 | var suffix; 69 | var firstch; 70 | var origword = w; 71 | 72 | if (w.length < 3) 73 | return w; 74 | 75 | var re; 76 | var re2; 77 | var re3; 78 | var re4; 79 | 80 | firstch = w.substr(0,1); 81 | if (firstch == "y") 82 | w = firstch.toUpperCase() + w.substr(1); 83 | 84 | // Step 1a 85 | re = /^(.+?)(ss|i)es$/; 86 | re2 = /^(.+?)([^s])s$/; 87 | 88 | if (re.test(w)) 89 | w = w.replace(re,"$1$2"); 90 | else if (re2.test(w)) 91 | w = w.replace(re2,"$1$2"); 92 | 93 | // Step 1b 94 | re = /^(.+?)eed$/; 95 | re2 = /^(.+?)(ed|ing)$/; 96 | if (re.test(w)) { 97 | var fp = re.exec(w); 98 | re = new RegExp(mgr0); 99 | if (re.test(fp[1])) { 100 | re = /.$/; 101 | w = w.replace(re,""); 102 | } 103 | } 104 | else if (re2.test(w)) { 105 | var fp = re2.exec(w); 106 | stem = fp[1]; 107 | re2 = new RegExp(s_v); 108 | if (re2.test(stem)) { 109 | w = stem; 110 | re2 = /(at|bl|iz)$/; 111 | re3 = new RegExp("([^aeiouylsz])\\1$"); 112 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 113 | if (re2.test(w)) 114 | w = w + "e"; 115 | else if (re3.test(w)) { 116 | re = /.$/; 117 | w = w.replace(re,""); 118 | } 119 | else if (re4.test(w)) 120 | w = w + "e"; 121 | } 122 | } 123 | 124 | // Step 1c 125 | re = /^(.+?)y$/; 126 | if (re.test(w)) { 127 | var fp = re.exec(w); 128 | stem = fp[1]; 129 | re = new RegExp(s_v); 130 | if (re.test(stem)) 131 | w = stem + "i"; 132 | } 133 | 134 | // Step 2 135 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 136 | if (re.test(w)) { 137 | var fp = re.exec(w); 138 | stem = fp[1]; 139 | suffix = fp[2]; 140 | re = new RegExp(mgr0); 141 | if (re.test(stem)) 142 | w = stem + step2list[suffix]; 143 | } 144 | 145 | // Step 3 146 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 147 | if (re.test(w)) { 148 | var fp = re.exec(w); 149 | stem = fp[1]; 150 | suffix = fp[2]; 151 | re = new RegExp(mgr0); 152 | if (re.test(stem)) 153 | w = stem + step3list[suffix]; 154 | } 155 | 156 | // Step 4 157 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 158 | re2 = /^(.+?)(s|t)(ion)$/; 159 | if (re.test(w)) { 160 | var fp = re.exec(w); 161 | stem = fp[1]; 162 | re = new RegExp(mgr1); 163 | if (re.test(stem)) 164 | w = stem; 165 | } 166 | else if (re2.test(w)) { 167 | var fp = re2.exec(w); 168 | stem = fp[1] + fp[2]; 169 | re2 = new RegExp(mgr1); 170 | if (re2.test(stem)) 171 | w = stem; 172 | } 173 | 174 | // Step 5 175 | re = /^(.+?)e$/; 176 | if (re.test(w)) { 177 | var fp = re.exec(w); 178 | stem = fp[1]; 179 | re = new RegExp(mgr1); 180 | re2 = new RegExp(meq1); 181 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 182 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 183 | w = stem; 184 | } 185 | re = /ll$/; 186 | re2 = new RegExp(mgr1); 187 | if (re.test(w) && re2.test(w)) { 188 | re = /.$/; 189 | w = w.replace(re,""); 190 | } 191 | 192 | // and turn initial Y back to y 193 | if (firstch == "y") 194 | w = firstch.toLowerCase() + w.substr(1); 195 | return w; 196 | } 197 | } 198 | 199 | 200 | 201 | 202 | 203 | var splitChars = (function() { 204 | var result = {}; 205 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, 206 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, 207 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, 208 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, 209 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, 210 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, 211 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, 212 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, 213 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, 214 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; 215 | var i, j, start, end; 216 | for (i = 0; i < singles.length; i++) { 217 | result[singles[i]] = true; 218 | } 219 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], 220 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], 221 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], 222 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], 223 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], 224 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], 225 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], 226 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], 227 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], 228 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], 229 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], 230 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], 231 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], 232 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], 233 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], 234 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], 235 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], 236 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], 237 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], 238 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], 239 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], 240 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], 241 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], 242 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], 243 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], 244 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], 245 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], 246 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], 247 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], 248 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], 249 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], 250 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], 251 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], 252 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], 253 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], 254 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], 255 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], 256 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], 257 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], 258 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], 259 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], 260 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], 261 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], 262 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], 263 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], 264 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], 265 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], 266 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], 267 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; 268 | for (i = 0; i < ranges.length; i++) { 269 | start = ranges[i][0]; 270 | end = ranges[i][1]; 271 | for (j = start; j <= end; j++) { 272 | result[j] = true; 273 | } 274 | } 275 | return result; 276 | })(); 277 | 278 | function splitQuery(query) { 279 | var result = []; 280 | var start = -1; 281 | for (var i = 0; i < query.length; i++) { 282 | if (splitChars[query.charCodeAt(i)]) { 283 | if (start !== -1) { 284 | result.push(query.slice(start, i)); 285 | start = -1; 286 | } 287 | } else if (start === -1) { 288 | start = i; 289 | } 290 | } 291 | if (start !== -1) { 292 | result.push(query.slice(start)); 293 | } 294 | return result; 295 | } 296 | 297 | 298 | -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_build/html/_static/solar.css: -------------------------------------------------------------------------------- 1 | /* solar.css 2 | * Modified from sphinxdoc.css of the sphinxdoc theme. 3 | */ 4 | 5 | @import url("basic.css"); 6 | 7 | /* -- page layout ----------------------------------------------------------- */ 8 | 9 | body { 10 | font-family: 'Open Sans', sans-serif; 11 | font-size: 14px; 12 | line-height: 150%; 13 | text-align: center; 14 | color: #002b36; 15 | padding: 0; 16 | margin: 0px 80px 0px 80px; 17 | min-width: 740px; 18 | -moz-box-shadow: 0px 0px 10px #93a1a1; 19 | -webkit-box-shadow: 0px 0px 10px #93a1a1; 20 | box-shadow: 0px 0px 10px #93a1a1; 21 | background: url("subtle_dots.png") repeat; 22 | 23 | } 24 | 25 | div.document { 26 | background-color: #fcfcfc; 27 | text-align: left; 28 | background-repeat: repeat-x; 29 | } 30 | 31 | div.bodywrapper { 32 | margin: 0 240px 0 0; 33 | border-right: 1px dotted #eee8d5; 34 | } 35 | 36 | div.body { 37 | background-color: white; 38 | margin: 0; 39 | padding: 0.5em 20px 20px 20px; 40 | } 41 | 42 | div.related { 43 | font-size: 1em; 44 | background: #002b36; 45 | color: #839496; 46 | padding: 5px 0px; 47 | } 48 | 49 | div.related ul { 50 | height: 2em; 51 | margin: 2px; 52 | } 53 | 54 | div.related ul li { 55 | margin: 0; 56 | padding: 0; 57 | height: 2em; 58 | float: left; 59 | } 60 | 61 | div.related ul li.right { 62 | float: right; 63 | margin-right: 5px; 64 | } 65 | 66 | div.related ul li a { 67 | margin: 0; 68 | padding: 2px 5px; 69 | line-height: 2em; 70 | text-decoration: none; 71 | color: #839496; 72 | } 73 | 74 | div.related ul li a:hover { 75 | background-color: #073642; 76 | -webkit-border-radius: 2px; 77 | -moz-border-radius: 2px; 78 | border-radius: 2px; 79 | } 80 | 81 | div.sphinxsidebarwrapper { 82 | padding: 0; 83 | } 84 | 85 | div.sphinxsidebar { 86 | margin: 0; 87 | padding: 0.5em 15px 15px 0; 88 | width: 210px; 89 | float: right; 90 | font-size: 0.9em; 91 | text-align: left; 92 | } 93 | 94 | div.sphinxsidebar h3, div.sphinxsidebar h4 { 95 | margin: 1em 0 0.5em 0; 96 | font-size: 1em; 97 | padding: 0.7em; 98 | background-color: #eeeff1; 99 | } 100 | 101 | div.sphinxsidebar h3 a { 102 | color: #2E3436; 103 | } 104 | 105 | div.sphinxsidebar ul { 106 | padding-left: 1.5em; 107 | margin-top: 7px; 108 | padding: 0; 109 | line-height: 150%; 110 | color: #586e75; 111 | } 112 | 113 | div.sphinxsidebar ul ul { 114 | margin-left: 20px; 115 | } 116 | 117 | div.sphinxsidebar input { 118 | border: 1px solid #eee8d5; 119 | } 120 | 121 | div.footer { 122 | background-color: #93a1a1; 123 | color: #eee; 124 | padding: 3px 8px 3px 0; 125 | clear: both; 126 | font-size: 0.8em; 127 | text-align: right; 128 | } 129 | 130 | div.footer a { 131 | color: #eee; 132 | text-decoration: none; 133 | } 134 | 135 | /* -- body styles ----------------------------------------------------------- */ 136 | 137 | p { 138 | margin: 0.8em 0 0.5em 0; 139 | } 140 | 141 | div.body a, div.sphinxsidebarwrapper a { 142 | color: #268bd2; 143 | text-decoration: none; 144 | } 145 | 146 | div.body a:hover, div.sphinxsidebarwrapper a:hover { 147 | border-bottom: 1px solid #268bd2; 148 | } 149 | 150 | h1, h2, h3, h4, h5, h6 { 151 | font-family: "Open Sans", sans-serif; 152 | font-weight: 300; 153 | } 154 | 155 | h1 { 156 | margin: 0; 157 | padding: 0.7em 0 0.3em 0; 158 | line-height: 1.2em; 159 | color: #002b36; 160 | text-shadow: #eee 0.1em 0.1em 0.1em; 161 | } 162 | 163 | h2 { 164 | margin: 1.3em 0 0.2em 0; 165 | padding: 0 0 10px 0; 166 | color: #073642; 167 | border-bottom: 1px solid #eee; 168 | } 169 | 170 | h3 { 171 | margin: 1em 0 -0.3em 0; 172 | padding-bottom: 5px; 173 | } 174 | 175 | h3, h4, h5, h6 { 176 | color: #073642; 177 | border-bottom: 1px dotted #eee; 178 | } 179 | 180 | div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { 181 | color: #657B83!important; 182 | } 183 | 184 | h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { 185 | display: none; 186 | margin: 0 0 0 0.3em; 187 | padding: 0 0.2em 0 0.2em; 188 | color: #aaa!important; 189 | } 190 | 191 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, 192 | h5:hover a.anchor, h6:hover a.anchor { 193 | display: inline; 194 | } 195 | 196 | h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, 197 | h5 a.anchor:hover, h6 a.anchor:hover { 198 | color: #777; 199 | background-color: #eee; 200 | } 201 | 202 | a.headerlink { 203 | color: #c60f0f!important; 204 | font-size: 1em; 205 | margin-left: 6px; 206 | padding: 0 4px 0 4px; 207 | text-decoration: none!important; 208 | } 209 | 210 | a.headerlink:hover { 211 | background-color: #ccc; 212 | color: white!important; 213 | } 214 | 215 | 216 | cite, code, tt { 217 | font-family: 'Source Code Pro', monospace; 218 | font-size: 0.9em; 219 | letter-spacing: 0.01em; 220 | background-color: #eeeff2; 221 | font-style: normal; 222 | } 223 | 224 | hr { 225 | border: 1px solid #eee; 226 | margin: 2em; 227 | } 228 | 229 | .highlight { 230 | -webkit-border-radius: 2px; 231 | -moz-border-radius: 2px; 232 | border-radius: 2px; 233 | } 234 | 235 | pre { 236 | font-family: 'Source Code Pro', monospace; 237 | font-style: normal; 238 | font-size: 0.9em; 239 | letter-spacing: 0.015em; 240 | line-height: 120%; 241 | padding: 0.7em; 242 | white-space: pre-wrap; /* css-3 */ 243 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 244 | white-space: -pre-wrap; /* Opera 4-6 */ 245 | white-space: -o-pre-wrap; /* Opera 7 */ 246 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 247 | } 248 | 249 | pre a { 250 | color: inherit; 251 | text-decoration: underline; 252 | } 253 | 254 | td.linenos pre { 255 | padding: 0.5em 0; 256 | } 257 | 258 | div.quotebar { 259 | background-color: #f8f8f8; 260 | max-width: 250px; 261 | float: right; 262 | padding: 2px 7px; 263 | border: 1px solid #ccc; 264 | } 265 | 266 | div.topic { 267 | background-color: #f8f8f8; 268 | } 269 | 270 | table { 271 | border-collapse: collapse; 272 | margin: 0 -0.5em 0 -0.5em; 273 | } 274 | 275 | table td, table th { 276 | padding: 0.2em 0.5em 0.2em 0.5em; 277 | } 278 | 279 | div.admonition { 280 | font-size: 0.9em; 281 | margin: 1em 0 1em 0; 282 | border: 1px solid #eee; 283 | background-color: #f7f7f7; 284 | padding: 0; 285 | -moz-box-shadow: 0px 8px 6px -8px #93a1a1; 286 | -webkit-box-shadow: 0px 8px 6px -8px #93a1a1; 287 | box-shadow: 0px 8px 6px -8px #93a1a1; 288 | } 289 | 290 | div.admonition p { 291 | margin: 0.5em 1em 0.5em 1em; 292 | padding: 0.2em; 293 | } 294 | 295 | div.admonition pre { 296 | margin: 0.4em 1em 0.4em 1em; 297 | } 298 | 299 | div.admonition p.admonition-title 300 | { 301 | margin: 0; 302 | padding: 0.2em 0 0.2em 0.6em; 303 | color: white; 304 | border-bottom: 1px solid #eee8d5; 305 | font-weight: bold; 306 | background-color: #268bd2; 307 | } 308 | 309 | div.warning p.admonition-title, 310 | div.important p.admonition-title { 311 | background-color: #cb4b16; 312 | } 313 | 314 | div.hint p.admonition-title, 315 | div.tip p.admonition-title { 316 | background-color: #859900; 317 | } 318 | 319 | div.caution p.admonition-title, 320 | div.attention p.admonition-title, 321 | div.danger p.admonition-title, 322 | div.error p.admonition-title { 323 | background-color: #dc322f; 324 | } 325 | 326 | div.admonition ul, div.admonition ol { 327 | margin: 0.1em 0.5em 0.5em 3em; 328 | padding: 0; 329 | } 330 | 331 | div.versioninfo { 332 | margin: 1em 0 0 0; 333 | border: 1px solid #eee; 334 | background-color: #DDEAF0; 335 | padding: 8px; 336 | line-height: 1.3em; 337 | font-size: 0.9em; 338 | } 339 | 340 | div.viewcode-block:target { 341 | background-color: #f4debf; 342 | border-top: 1px solid #eee; 343 | border-bottom: 1px solid #eee; 344 | } 345 | -------------------------------------------------------------------------------- /docs/_build/html/_static/solarized-dark.css: -------------------------------------------------------------------------------- 1 | /* solarized dark style for solar theme */ 2 | 3 | /*style pre scrollbar*/ 4 | pre::-webkit-scrollbar, .highlight::-webkit-scrollbar { 5 | height: 0.5em; 6 | background: #073642; 7 | } 8 | 9 | pre::-webkit-scrollbar-thumb { 10 | border-radius: 1em; 11 | background: #93a1a1; 12 | } 13 | 14 | /* pygments style */ 15 | .highlight .hll { background-color: #ffffcc } 16 | .highlight { background: #002B36!important; color: #93A1A1 } 17 | .highlight .c { color: #586E75 } /* Comment */ 18 | .highlight .err { color: #93A1A1 } /* Error */ 19 | .highlight .g { color: #93A1A1 } /* Generic */ 20 | .highlight .k { color: #859900 } /* Keyword */ 21 | .highlight .l { color: #93A1A1 } /* Literal */ 22 | .highlight .n { color: #93A1A1 } /* Name */ 23 | .highlight .o { color: #859900 } /* Operator */ 24 | .highlight .x { color: #CB4B16 } /* Other */ 25 | .highlight .p { color: #93A1A1 } /* Punctuation */ 26 | .highlight .cm { color: #586E75 } /* Comment.Multiline */ 27 | .highlight .cp { color: #859900 } /* Comment.Preproc */ 28 | .highlight .c1 { color: #586E75 } /* Comment.Single */ 29 | .highlight .cs { color: #859900 } /* Comment.Special */ 30 | .highlight .gd { color: #2AA198 } /* Generic.Deleted */ 31 | .highlight .ge { color: #93A1A1; font-style: italic } /* Generic.Emph */ 32 | .highlight .gr { color: #DC322F } /* Generic.Error */ 33 | .highlight .gh { color: #CB4B16 } /* Generic.Heading */ 34 | .highlight .gi { color: #859900 } /* Generic.Inserted */ 35 | .highlight .go { color: #93A1A1 } /* Generic.Output */ 36 | .highlight .gp { color: #93A1A1 } /* Generic.Prompt */ 37 | .highlight .gs { color: #93A1A1; font-weight: bold } /* Generic.Strong */ 38 | .highlight .gu { color: #CB4B16 } /* Generic.Subheading */ 39 | .highlight .gt { color: #93A1A1 } /* Generic.Traceback */ 40 | .highlight .kc { color: #CB4B16 } /* Keyword.Constant */ 41 | .highlight .kd { color: #268BD2 } /* Keyword.Declaration */ 42 | .highlight .kn { color: #859900 } /* Keyword.Namespace */ 43 | .highlight .kp { color: #859900 } /* Keyword.Pseudo */ 44 | .highlight .kr { color: #268BD2 } /* Keyword.Reserved */ 45 | .highlight .kt { color: #DC322F } /* Keyword.Type */ 46 | .highlight .ld { color: #93A1A1 } /* Literal.Date */ 47 | .highlight .m { color: #2AA198 } /* Literal.Number */ 48 | .highlight .s { color: #2AA198 } /* Literal.String */ 49 | .highlight .na { color: #93A1A1 } /* Name.Attribute */ 50 | .highlight .nb { color: #B58900 } /* Name.Builtin */ 51 | .highlight .nc { color: #268BD2 } /* Name.Class */ 52 | .highlight .no { color: #CB4B16 } /* Name.Constant */ 53 | .highlight .nd { color: #268BD2 } /* Name.Decorator */ 54 | .highlight .ni { color: #CB4B16 } /* Name.Entity */ 55 | .highlight .ne { color: #CB4B16 } /* Name.Exception */ 56 | .highlight .nf { color: #268BD2 } /* Name.Function */ 57 | .highlight .nl { color: #93A1A1 } /* Name.Label */ 58 | .highlight .nn { color: #93A1A1 } /* Name.Namespace */ 59 | .highlight .nx { color: #93A1A1 } /* Name.Other */ 60 | .highlight .py { color: #93A1A1 } /* Name.Property */ 61 | .highlight .nt { color: #268BD2 } /* Name.Tag */ 62 | .highlight .nv { color: #268BD2 } /* Name.Variable */ 63 | .highlight .ow { color: #859900 } /* Operator.Word */ 64 | .highlight .w { color: #93A1A1 } /* Text.Whitespace */ 65 | .highlight .mf { color: #2AA198 } /* Literal.Number.Float */ 66 | .highlight .mh { color: #2AA198 } /* Literal.Number.Hex */ 67 | .highlight .mi { color: #2AA198 } /* Literal.Number.Integer */ 68 | .highlight .mo { color: #2AA198 } /* Literal.Number.Oct */ 69 | .highlight .sb { color: #586E75 } /* Literal.String.Backtick */ 70 | .highlight .sc { color: #2AA198 } /* Literal.String.Char */ 71 | .highlight .sd { color: #93A1A1 } /* Literal.String.Doc */ 72 | .highlight .s2 { color: #2AA198 } /* Literal.String.Double */ 73 | .highlight .se { color: #CB4B16 } /* Literal.String.Escape */ 74 | .highlight .sh { color: #93A1A1 } /* Literal.String.Heredoc */ 75 | .highlight .si { color: #2AA198 } /* Literal.String.Interpol */ 76 | .highlight .sx { color: #2AA198 } /* Literal.String.Other */ 77 | .highlight .sr { color: #DC322F } /* Literal.String.Regex */ 78 | .highlight .s1 { color: #2AA198 } /* Literal.String.Single */ 79 | .highlight .ss { color: #2AA198 } /* Literal.String.Symbol */ 80 | .highlight .bp { color: #268BD2 } /* Name.Builtin.Pseudo */ 81 | .highlight .vc { color: #268BD2 } /* Name.Variable.Class */ 82 | .highlight .vg { color: #268BD2 } /* Name.Variable.Global */ 83 | .highlight .vi { color: #268BD2 } /* Name.Variable.Instance */ 84 | .highlight .il { color: #2AA198 } /* Literal.Number.Integer.Long */ 85 | -------------------------------------------------------------------------------- /docs/_build/html/_static/subtle_dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/html/_static/subtle_dots.png -------------------------------------------------------------------------------- /docs/_build/html/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/_build/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Python Module Index — Googletrans 3.0.0 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 31 | 45 | 46 |
47 |
48 |
49 |
50 | 51 | 52 |

Python Module Index

53 | 54 |
55 | g 56 |
57 | 58 | 59 | 60 | 62 | 63 | 65 | 68 | 69 | 70 | 73 | 74 | 75 | 78 |
 
61 | g
66 | googletrans 67 |
    71 | googletrans.gtoken 72 |
    76 | googletrans.models 77 |
79 | 80 | 81 |
82 |
83 |
84 |
85 | 86 | 87 |
88 |
89 | 99 | 103 | 104 | -------------------------------------------------------------------------------- /docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Search — Googletrans 3.0.0 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 33 | 37 | 38 |
39 |
40 |
41 |
42 | 43 |

Search

44 |
45 | 46 |

47 | Please activate JavaScript to enable the search 48 | functionality. 49 |

50 |
51 |

52 | Searching for multiple words only shows matches that contain 53 | all words. 54 |

55 |
56 | 57 | 58 | 59 |
60 | 61 |
62 | 63 |
64 | 65 |
66 |
67 |
68 |
69 | 70 | 71 |
72 |
73 | 83 | 87 | 88 | -------------------------------------------------------------------------------- /docs/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["index.rst"],objects:{"googletrans.Translator":{detect:[0,1,1,""],translate:[0,1,1,""]},"googletrans.gtoken":{TokenAcquirer:[0,0,1,""]},"googletrans.models":{Detected:[0,0,1,""],Translated:[0,0,1,""]},googletrans:{Translator:[0,0,1,""],gtoken:[0,2,0,"-"],models:[0,2,0,"-"]}},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","module","Python module"]},objtypes:{"0":"py:class","1":"py:method","2":"py:module"},terms:{"043500196":0,"10538048":0,"15k":0,"22348526":0,"27041003":0,"3128":0,"4012":0,"577246":0,"5xx":0,"64889508":0,"744915":0,"856682":0,"92929292":0,"950629":0,"96954316":0,"\u3053\u306e\u6587\u7ae0\u306f\u65e5\u672c\u8a9e\u3067\u66f8\u304b\u308c\u307e\u3057\u305f":0,"\u3053\u3093\u306b\u3061\u306f":0,"\u65e5\u672c\u8a9e":0,"\uac08\uc0c9":0,"\uac1c":0,"\uac8c\uc73c\ub978":0,"\ubb38\uc7a5\uc740":0,"\ube60\ub978":0,"\uc4f0\uc5ec\uc84c\uc2b5\ub2c8\ub2e4":0,"\uc548\ub155\ud558\uc138\uc694":0,"\uc5ec\uc6b0":0,"\uc774":0,"\uc774\uc0c1":0,"\uc810\ud504":0,"\ud55c\uad6d\uc5b4":0,"\ud55c\uae00\ub85c":0,"boolean":0,"class":0,"default":0,"final":0,"fran\u00e7ai":0,"import":0,"return":0,"true":0,For:0,The:0,Will:0,_client:0,_config:0,_sync:0,about:0,abov:0,access:0,acquir:0,addit:0,address:0,advantag:0,afrikaan:0,agent:0,ajax:0,albanian:0,all:0,also:0,amhar:0,anoth:0,arab:0,armenian:0,arrai:0,attempt:0,author:0,auto:0,automat:0,avail:0,azerbaijani:0,ban:0,bar:0,base:0,basqu:0,batch:0,becaus:0,belarusian:0,bengali:0,bosnian:0,both:0,brown:0,bulgarian:0,burmes:0,call:0,can:0,care:0,cat:[],catalan:0,caus:0,ceb:0,cebuano:0,charact:0,check:0,chichewa:0,chines:0,choos:0,client:0,code:0,com:0,combin:0,confid:0,configur:0,connect:0,const_valu:[],constant:[],corsican:0,countri:0,creat:0,creol:0,croatian:0,current:0,customiz:0,czech:0,danish:0,deal:0,default_raise_except:[],definit:0,dest:0,destin:0,dict:0,dictionari:0,doe:0,dog:0,domain:0,don:0,doubl:0,due:0,dummy_data:[],dutch:0,engin:0,english:0,error:0,esperanto:0,esta:0,estonian:0,even:0,everi:0,everyon:0,exact:0,exampl:0,except:0,extra_data:0,fals:0,fast:0,faster:0,filipino:0,finnish:0,foo:0,fox:0,frazo:0,french:0,frisian:0,from:0,gaelic:0,galician:0,gener:0,georgian:0,german:0,get:0,given:0,good:0,great:0,greek:0,guarante:0,gujarati:0,haitian:0,has:0,hausa:0,have:0,haw:0,hawaiian:0,header:0,hebrew:0,highli:0,hindi:0,hmn:0,hmong:0,host:0,hour:0,http2:0,httpcore:0,httpx:0,hungarian:0,hyper:0,iceland:0,identifi:0,igbo:0,implement:0,impli:0,includ:0,indonesian:0,initi:0,input:0,instal:0,instanc:0,intern:0,irish:0,iso639:0,italian:0,item:[],iter:0,its:0,japanes:0,javanes:0,jump:0,kannada:0,kazakh:0,khmer:0,kon:0,korean:0,kurdish:0,kurmanji:0,kwarg:0,kyrgyz:0,lang:0,langcod:0,lao:0,latin:0,latvian:0,lazi:0,light:0,like:0,limit:0,line:[],lineno:[],list:0,lithuanian:0,lux:0,luxembourgish:0,macedonian:0,make:0,malagasi:0,malai:0,malayalam:0,maltes:0,maori:0,map:0,marathi:0,math:0,maximum:0,mea:0,method:0,minifi:0,mongolian:0,mozilla:0,multipl:0,myanmar:0,name:0,nepali:0,network:0,nichiwa:0,none:0,norwegian:0,number:0,obfusc:0,object:0,odia:0,offici:0,onc:0,one:0,onli:0,oper:0,order:0,origin:0,over:0,packag:0,pai:0,paramet:0,pashto:0,pass:0,per:0,persian:0,pip:0,pleas:0,polish:0,pool:0,portugues:0,print:0,probabl:0,pronunci:0,properli:0,protocol:0,provid:0,proxi:0,punjabi:0,pypi:0,quick:0,rais:0,raise_except:0,randomli:0,recommend:0,reliabl:0,request:0,result:0,revers:0,romanian:0,russian:0,same:0,samoan:0,scot:0,seed:0,send:0,sentenc:0,sequenc:0,serbian:0,server:0,service_url:0,sesotho:0,session:0,shona:0,should:0,shown:0,simplifi:0,sindhi:0,singl:0,sinhala:0,skribita:0,slovak:0,slovenian:0,smth:0,somali:0,some:0,sourc:0,spanish:0,special_cas:0,specifi:0,src:0,stabil:0,stabl:0,str:0,strang:0,string:0,sundanes:0,swahili:0,swedish:0,synchttptransport:0,system:0,tajik:0,tamil:0,telugu:0,test:0,text:0,thai:0,thi:0,time:0,timeout:0,tiu:0,tkk:0,token:0,tokenacquir:0,tradit:0,truth:0,tupl:0,turkish:0,type:0,ukrainian:0,unicod:0,updat:0,urdu:0,use:0,used:0,user:0,user_ag:0,uses:0,using:0,utf:0,uyghur:0,uzbek:0,valid:0,valu:0,verita:0,version:0,via:0,vietnames:0,want:0,web:0,well:0,welsh:0,when:0,which:0,whose:0,win64:0,window:0,work:0,would:0,written:0,wrong:0,x64:0,xhosa:0,yiddish:0,yoruba:0,you:0,your:0,zulu:0},titles:["Googletrans: Free and Unlimited Google translate API for Python"],titleterms:{advanc:0,api:0,basic:0,bulk:0,custom:0,default_service_url:0,detect:0,featur:0,free:0,googl:0,googletran:0,gtoken:0,guid:0,http:0,languag:0,librari:0,model:0,note:0,python:0,quickstart:0,servic:0,special_cas:[],support:0,translat:0,unlimit:0,url:0,usag:0}}) -------------------------------------------------------------------------------- /docs/_themes/solar/NEWS.txt: -------------------------------------------------------------------------------- 1 | News 2 | ==== 3 | 4 | 1.3 5 | --- 6 | * Release date: 2012-11-01. 7 | * Source Code Pro is now used for code samples. 8 | * Reduced font size of pre elements. 9 | * Horizontal rule for header elements. 10 | * HTML pre contents are now wrapped (no scrollbars). 11 | * Changed permalink color from black to a lighter one. 12 | 13 | 1.2 14 | --- 15 | * Release date: 2012-10-03. 16 | * Style additional admonition levels. 17 | * Increase padding for navigation links (minor). 18 | * Add shadow for admonition items (minor). 19 | 20 | 1.1 21 | --- 22 | * Release date: 2012-09-05. 23 | * Add a new background. 24 | * Revert font of headings to Open Sans Light. 25 | * Darker color for h3 - h6. 26 | * Removed dependency on solarized dark pygments style. 27 | * Nice looking scrollbars for pre element. 28 | 29 | 1.0 30 | --- 31 | * Release date: 2012-08-24. 32 | * Initial release. 33 | -------------------------------------------------------------------------------- /docs/_themes/solar/README.rst: -------------------------------------------------------------------------------- 1 | Solar theme for Python Sphinx 2 | ============================= 3 | Solar is an attempt to create a theme for Sphinx based on the `Solarized `_ color scheme. 4 | 5 | Preview 6 | ------- 7 | http://vimalkumar.in/sphinx-themes/solar 8 | 9 | Download 10 | -------- 11 | Released versions are available from http://github.com/vkvn/sphinx-themes/downloads 12 | 13 | Installation 14 | ------------ 15 | #. Extract the archive. 16 | #. Modify ``conf.py`` of an existing Sphinx project or create new project using ``sphinx-quickstart``. 17 | #. Change the ``html_theme`` parameter to ``solar``. 18 | #. Change the ``html_theme_path`` to the location containing the extracted archive. 19 | 20 | License 21 | ------- 22 | `GNU General Public License `_. 23 | 24 | Credits 25 | ------- 26 | Modified from the default Sphinx theme -- Sphinxdoc 27 | 28 | Background pattern from http://subtlepatterns.com. 29 | -------------------------------------------------------------------------------- /docs/_themes/solar/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | 3 | {%- block doctype -%} 4 | 5 | {%- endblock -%} 6 | 7 | {%- block extrahead -%} 8 | 9 | 10 | {%- endblock -%} 11 | 12 | {# put the sidebar before the body #} 13 | {% block sidebar1 %}{{ sidebar() }}{% endblock %} 14 | {% block sidebar2 %} 15 | 16 | {% endblock %} 17 | 18 | {%- block footer %} 19 | 34 | {%- endblock %} 35 | -------------------------------------------------------------------------------- /docs/_themes/solar/static/solar.css: -------------------------------------------------------------------------------- 1 | /* solar.css 2 | * Modified from sphinxdoc.css of the sphinxdoc theme. 3 | */ 4 | 5 | @import url("basic.css"); 6 | 7 | /* -- page layout ----------------------------------------------------------- */ 8 | 9 | body { 10 | font-family: 'Open Sans', sans-serif; 11 | font-size: 14px; 12 | line-height: 150%; 13 | text-align: center; 14 | color: #002b36; 15 | padding: 0; 16 | margin: 0px 80px 0px 80px; 17 | min-width: 740px; 18 | -moz-box-shadow: 0px 0px 10px #93a1a1; 19 | -webkit-box-shadow: 0px 0px 10px #93a1a1; 20 | box-shadow: 0px 0px 10px #93a1a1; 21 | background: url("subtle_dots.png") repeat; 22 | 23 | } 24 | 25 | div.document { 26 | background-color: #fcfcfc; 27 | text-align: left; 28 | background-repeat: repeat-x; 29 | } 30 | 31 | div.bodywrapper { 32 | margin: 0 240px 0 0; 33 | border-right: 1px dotted #eee8d5; 34 | } 35 | 36 | div.body { 37 | background-color: white; 38 | margin: 0; 39 | padding: 0.5em 20px 20px 20px; 40 | } 41 | 42 | div.related { 43 | font-size: 1em; 44 | background: #002b36; 45 | color: #839496; 46 | padding: 5px 0px; 47 | } 48 | 49 | div.related ul { 50 | height: 2em; 51 | margin: 2px; 52 | } 53 | 54 | div.related ul li { 55 | margin: 0; 56 | padding: 0; 57 | height: 2em; 58 | float: left; 59 | } 60 | 61 | div.related ul li.right { 62 | float: right; 63 | margin-right: 5px; 64 | } 65 | 66 | div.related ul li a { 67 | margin: 0; 68 | padding: 2px 5px; 69 | line-height: 2em; 70 | text-decoration: none; 71 | color: #839496; 72 | } 73 | 74 | div.related ul li a:hover { 75 | background-color: #073642; 76 | -webkit-border-radius: 2px; 77 | -moz-border-radius: 2px; 78 | border-radius: 2px; 79 | } 80 | 81 | div.sphinxsidebarwrapper { 82 | padding: 0; 83 | } 84 | 85 | div.sphinxsidebar { 86 | margin: 0; 87 | padding: 0.5em 15px 15px 0; 88 | width: 210px; 89 | float: right; 90 | font-size: 0.9em; 91 | text-align: left; 92 | } 93 | 94 | div.sphinxsidebar h3, div.sphinxsidebar h4 { 95 | margin: 1em 0 0.5em 0; 96 | font-size: 1em; 97 | padding: 0.7em; 98 | background-color: #eeeff1; 99 | } 100 | 101 | div.sphinxsidebar h3 a { 102 | color: #2E3436; 103 | } 104 | 105 | div.sphinxsidebar ul { 106 | padding-left: 1.5em; 107 | margin-top: 7px; 108 | padding: 0; 109 | line-height: 150%; 110 | color: #586e75; 111 | } 112 | 113 | div.sphinxsidebar ul ul { 114 | margin-left: 20px; 115 | } 116 | 117 | div.sphinxsidebar input { 118 | border: 1px solid #eee8d5; 119 | } 120 | 121 | div.footer { 122 | background-color: #93a1a1; 123 | color: #eee; 124 | padding: 3px 8px 3px 0; 125 | clear: both; 126 | font-size: 0.8em; 127 | text-align: right; 128 | } 129 | 130 | div.footer a { 131 | color: #eee; 132 | text-decoration: none; 133 | } 134 | 135 | /* -- body styles ----------------------------------------------------------- */ 136 | 137 | p { 138 | margin: 0.8em 0 0.5em 0; 139 | } 140 | 141 | div.body a, div.sphinxsidebarwrapper a { 142 | color: #268bd2; 143 | text-decoration: none; 144 | } 145 | 146 | div.body a:hover, div.sphinxsidebarwrapper a:hover { 147 | border-bottom: 1px solid #268bd2; 148 | } 149 | 150 | h1, h2, h3, h4, h5, h6 { 151 | font-family: "Open Sans", sans-serif; 152 | font-weight: 300; 153 | } 154 | 155 | h1 { 156 | margin: 0; 157 | padding: 0.7em 0 0.3em 0; 158 | line-height: 1.2em; 159 | color: #002b36; 160 | text-shadow: #eee 0.1em 0.1em 0.1em; 161 | } 162 | 163 | h2 { 164 | margin: 1.3em 0 0.2em 0; 165 | padding: 0 0 10px 0; 166 | color: #073642; 167 | border-bottom: 1px solid #eee; 168 | } 169 | 170 | h3 { 171 | margin: 1em 0 -0.3em 0; 172 | padding-bottom: 5px; 173 | } 174 | 175 | h3, h4, h5, h6 { 176 | color: #073642; 177 | border-bottom: 1px dotted #eee; 178 | } 179 | 180 | div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { 181 | color: #657B83!important; 182 | } 183 | 184 | h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { 185 | display: none; 186 | margin: 0 0 0 0.3em; 187 | padding: 0 0.2em 0 0.2em; 188 | color: #aaa!important; 189 | } 190 | 191 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, 192 | h5:hover a.anchor, h6:hover a.anchor { 193 | display: inline; 194 | } 195 | 196 | h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, 197 | h5 a.anchor:hover, h6 a.anchor:hover { 198 | color: #777; 199 | background-color: #eee; 200 | } 201 | 202 | a.headerlink { 203 | color: #c60f0f!important; 204 | font-size: 1em; 205 | margin-left: 6px; 206 | padding: 0 4px 0 4px; 207 | text-decoration: none!important; 208 | } 209 | 210 | a.headerlink:hover { 211 | background-color: #ccc; 212 | color: white!important; 213 | } 214 | 215 | 216 | cite, code, tt { 217 | font-family: 'Source Code Pro', monospace; 218 | font-size: 0.9em; 219 | letter-spacing: 0.01em; 220 | background-color: #eeeff2; 221 | font-style: normal; 222 | } 223 | 224 | hr { 225 | border: 1px solid #eee; 226 | margin: 2em; 227 | } 228 | 229 | .highlight { 230 | -webkit-border-radius: 2px; 231 | -moz-border-radius: 2px; 232 | border-radius: 2px; 233 | } 234 | 235 | pre { 236 | font-family: 'Source Code Pro', monospace; 237 | font-style: normal; 238 | font-size: 0.9em; 239 | letter-spacing: 0.015em; 240 | line-height: 120%; 241 | padding: 0.7em; 242 | white-space: pre-wrap; /* css-3 */ 243 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 244 | white-space: -pre-wrap; /* Opera 4-6 */ 245 | white-space: -o-pre-wrap; /* Opera 7 */ 246 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 247 | } 248 | 249 | pre a { 250 | color: inherit; 251 | text-decoration: underline; 252 | } 253 | 254 | td.linenos pre { 255 | padding: 0.5em 0; 256 | } 257 | 258 | div.quotebar { 259 | background-color: #f8f8f8; 260 | max-width: 250px; 261 | float: right; 262 | padding: 2px 7px; 263 | border: 1px solid #ccc; 264 | } 265 | 266 | div.topic { 267 | background-color: #f8f8f8; 268 | } 269 | 270 | table { 271 | border-collapse: collapse; 272 | margin: 0 -0.5em 0 -0.5em; 273 | } 274 | 275 | table td, table th { 276 | padding: 0.2em 0.5em 0.2em 0.5em; 277 | } 278 | 279 | div.admonition { 280 | font-size: 0.9em; 281 | margin: 1em 0 1em 0; 282 | border: 1px solid #eee; 283 | background-color: #f7f7f7; 284 | padding: 0; 285 | -moz-box-shadow: 0px 8px 6px -8px #93a1a1; 286 | -webkit-box-shadow: 0px 8px 6px -8px #93a1a1; 287 | box-shadow: 0px 8px 6px -8px #93a1a1; 288 | } 289 | 290 | div.admonition p { 291 | margin: 0.5em 1em 0.5em 1em; 292 | padding: 0.2em; 293 | } 294 | 295 | div.admonition pre { 296 | margin: 0.4em 1em 0.4em 1em; 297 | } 298 | 299 | div.admonition p.admonition-title 300 | { 301 | margin: 0; 302 | padding: 0.2em 0 0.2em 0.6em; 303 | color: white; 304 | border-bottom: 1px solid #eee8d5; 305 | font-weight: bold; 306 | background-color: #268bd2; 307 | } 308 | 309 | div.warning p.admonition-title, 310 | div.important p.admonition-title { 311 | background-color: #cb4b16; 312 | } 313 | 314 | div.hint p.admonition-title, 315 | div.tip p.admonition-title { 316 | background-color: #859900; 317 | } 318 | 319 | div.caution p.admonition-title, 320 | div.attention p.admonition-title, 321 | div.danger p.admonition-title, 322 | div.error p.admonition-title { 323 | background-color: #dc322f; 324 | } 325 | 326 | div.admonition ul, div.admonition ol { 327 | margin: 0.1em 0.5em 0.5em 3em; 328 | padding: 0; 329 | } 330 | 331 | div.versioninfo { 332 | margin: 1em 0 0 0; 333 | border: 1px solid #eee; 334 | background-color: #DDEAF0; 335 | padding: 8px; 336 | line-height: 1.3em; 337 | font-size: 0.9em; 338 | } 339 | 340 | div.viewcode-block:target { 341 | background-color: #f4debf; 342 | border-top: 1px solid #eee; 343 | border-bottom: 1px solid #eee; 344 | } 345 | -------------------------------------------------------------------------------- /docs/_themes/solar/static/solarized-dark.css: -------------------------------------------------------------------------------- 1 | /* solarized dark style for solar theme */ 2 | 3 | /*style pre scrollbar*/ 4 | pre::-webkit-scrollbar, .highlight::-webkit-scrollbar { 5 | height: 0.5em; 6 | background: #073642; 7 | } 8 | 9 | pre::-webkit-scrollbar-thumb { 10 | border-radius: 1em; 11 | background: #93a1a1; 12 | } 13 | 14 | /* pygments style */ 15 | .highlight .hll { background-color: #ffffcc } 16 | .highlight { background: #002B36!important; color: #93A1A1 } 17 | .highlight .c { color: #586E75 } /* Comment */ 18 | .highlight .err { color: #93A1A1 } /* Error */ 19 | .highlight .g { color: #93A1A1 } /* Generic */ 20 | .highlight .k { color: #859900 } /* Keyword */ 21 | .highlight .l { color: #93A1A1 } /* Literal */ 22 | .highlight .n { color: #93A1A1 } /* Name */ 23 | .highlight .o { color: #859900 } /* Operator */ 24 | .highlight .x { color: #CB4B16 } /* Other */ 25 | .highlight .p { color: #93A1A1 } /* Punctuation */ 26 | .highlight .cm { color: #586E75 } /* Comment.Multiline */ 27 | .highlight .cp { color: #859900 } /* Comment.Preproc */ 28 | .highlight .c1 { color: #586E75 } /* Comment.Single */ 29 | .highlight .cs { color: #859900 } /* Comment.Special */ 30 | .highlight .gd { color: #2AA198 } /* Generic.Deleted */ 31 | .highlight .ge { color: #93A1A1; font-style: italic } /* Generic.Emph */ 32 | .highlight .gr { color: #DC322F } /* Generic.Error */ 33 | .highlight .gh { color: #CB4B16 } /* Generic.Heading */ 34 | .highlight .gi { color: #859900 } /* Generic.Inserted */ 35 | .highlight .go { color: #93A1A1 } /* Generic.Output */ 36 | .highlight .gp { color: #93A1A1 } /* Generic.Prompt */ 37 | .highlight .gs { color: #93A1A1; font-weight: bold } /* Generic.Strong */ 38 | .highlight .gu { color: #CB4B16 } /* Generic.Subheading */ 39 | .highlight .gt { color: #93A1A1 } /* Generic.Traceback */ 40 | .highlight .kc { color: #CB4B16 } /* Keyword.Constant */ 41 | .highlight .kd { color: #268BD2 } /* Keyword.Declaration */ 42 | .highlight .kn { color: #859900 } /* Keyword.Namespace */ 43 | .highlight .kp { color: #859900 } /* Keyword.Pseudo */ 44 | .highlight .kr { color: #268BD2 } /* Keyword.Reserved */ 45 | .highlight .kt { color: #DC322F } /* Keyword.Type */ 46 | .highlight .ld { color: #93A1A1 } /* Literal.Date */ 47 | .highlight .m { color: #2AA198 } /* Literal.Number */ 48 | .highlight .s { color: #2AA198 } /* Literal.String */ 49 | .highlight .na { color: #93A1A1 } /* Name.Attribute */ 50 | .highlight .nb { color: #B58900 } /* Name.Builtin */ 51 | .highlight .nc { color: #268BD2 } /* Name.Class */ 52 | .highlight .no { color: #CB4B16 } /* Name.Constant */ 53 | .highlight .nd { color: #268BD2 } /* Name.Decorator */ 54 | .highlight .ni { color: #CB4B16 } /* Name.Entity */ 55 | .highlight .ne { color: #CB4B16 } /* Name.Exception */ 56 | .highlight .nf { color: #268BD2 } /* Name.Function */ 57 | .highlight .nl { color: #93A1A1 } /* Name.Label */ 58 | .highlight .nn { color: #93A1A1 } /* Name.Namespace */ 59 | .highlight .nx { color: #93A1A1 } /* Name.Other */ 60 | .highlight .py { color: #93A1A1 } /* Name.Property */ 61 | .highlight .nt { color: #268BD2 } /* Name.Tag */ 62 | .highlight .nv { color: #268BD2 } /* Name.Variable */ 63 | .highlight .ow { color: #859900 } /* Operator.Word */ 64 | .highlight .w { color: #93A1A1 } /* Text.Whitespace */ 65 | .highlight .mf { color: #2AA198 } /* Literal.Number.Float */ 66 | .highlight .mh { color: #2AA198 } /* Literal.Number.Hex */ 67 | .highlight .mi { color: #2AA198 } /* Literal.Number.Integer */ 68 | .highlight .mo { color: #2AA198 } /* Literal.Number.Oct */ 69 | .highlight .sb { color: #586E75 } /* Literal.String.Backtick */ 70 | .highlight .sc { color: #2AA198 } /* Literal.String.Char */ 71 | .highlight .sd { color: #93A1A1 } /* Literal.String.Doc */ 72 | .highlight .s2 { color: #2AA198 } /* Literal.String.Double */ 73 | .highlight .se { color: #CB4B16 } /* Literal.String.Escape */ 74 | .highlight .sh { color: #93A1A1 } /* Literal.String.Heredoc */ 75 | .highlight .si { color: #2AA198 } /* Literal.String.Interpol */ 76 | .highlight .sx { color: #2AA198 } /* Literal.String.Other */ 77 | .highlight .sr { color: #DC322F } /* Literal.String.Regex */ 78 | .highlight .s1 { color: #2AA198 } /* Literal.String.Single */ 79 | .highlight .ss { color: #2AA198 } /* Literal.String.Symbol */ 80 | .highlight .bp { color: #268BD2 } /* Name.Builtin.Pseudo */ 81 | .highlight .vc { color: #268BD2 } /* Name.Variable.Class */ 82 | .highlight .vg { color: #268BD2 } /* Name.Variable.Global */ 83 | .highlight .vi { color: #268BD2 } /* Name.Variable.Instance */ 84 | .highlight .il { color: #2AA198 } /* Literal.Number.Integer.Long */ 85 | -------------------------------------------------------------------------------- /docs/_themes/solar/static/subtle_dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/docs/_themes/solar/static/subtle_dots.png -------------------------------------------------------------------------------- /docs/_themes/solar/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = solar.css 4 | pygments_style = none 5 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Googletrans documentation build configuration file, created by 5 | # sphinx-quickstart on Fri Jun 5 17:51:30 2015. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import datetime 17 | import sys 18 | 19 | sys.path.append("..") 20 | import googletrans 21 | 22 | # If extensions (or modules to document with autodoc) are in another directory, 23 | # add these directories to sys.path here. If the directory is relative to the 24 | # documentation root, use os.path.abspath to make it absolute, like shown here. 25 | # sys.path.insert(0, os.path.abspath('.')) 26 | 27 | # -- General configuration ------------------------------------------------ 28 | 29 | # If your documentation needs a minimal Sphinx version, state it here. 30 | # needs_sphinx = '1.0' 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = [ 36 | "sphinx.ext.autodoc", 37 | "sphinx.ext.intersphinx", 38 | # 'sphinx.ext.viewcode', 39 | ] 40 | 41 | # Add any paths that contain templates here, relative to this directory. 42 | templates_path = ["_templates"] 43 | 44 | # The suffix(es) of source filenames. 45 | # You can specify multiple suffix as a list of string: 46 | # source_suffix = ['.rst', '.md'] 47 | source_suffix = ".rst" 48 | 49 | # The encoding of source files. 50 | # source_encoding = 'utf-8-sig' 51 | 52 | # The master toctree document. 53 | master_doc = "index" 54 | 55 | # General information about the project. 56 | project = "Googletrans" 57 | copyright = str(datetime.date.today().year) + ", SuHun Han (ssut)" 58 | author = "SuHun Han (ssut)" 59 | 60 | # The version info for the project you're documenting, acts as replacement for 61 | # |version| and |release|, also used in various other places throughout the 62 | # built documents. 63 | # 64 | # The short X.Y version. 65 | version = googletrans.__version__ 66 | # The full version, including alpha/beta/rc tags. 67 | release = version 68 | 69 | # The language for content autogenerated by Sphinx. Refer to documentation 70 | # for a list of supported languages. 71 | # 72 | # This is also used if you do content translation via gettext catalogs. 73 | # Usually you set "language" from the command line for these cases. 74 | language = None 75 | 76 | # There are two options for replacing |today|: either, you set today to some 77 | # non-false value, then it is used: 78 | # today = '' 79 | # Else, today_fmt is used as the format for a strftime call. 80 | # today_fmt = '%B %d, %Y' 81 | 82 | # List of patterns, relative to source directory, that match files and 83 | # directories to ignore when looking for source files. 84 | exclude_patterns = ["_build", "_themes"] 85 | 86 | # The reST default role (used for this markup: `text`) to use for all 87 | # documents. 88 | # default_role = None 89 | 90 | # If true, '()' will be appended to :func: etc. cross-reference text. 91 | # add_function_parentheses = True 92 | 93 | # If true, the current module name will be prepended to all description 94 | # unit titles (such as .. function::). 95 | # add_module_names = True 96 | 97 | # If true, sectionauthor and moduleauthor directives will be shown in the 98 | # output. They are ignored by default. 99 | # show_authors = False 100 | 101 | # The name of the Pygments (syntax highlighting) style to use. 102 | pygments_style = "sphinx" 103 | 104 | # A list of ignored prefixes for module index sorting. 105 | # modindex_common_prefix = [] 106 | 107 | # If true, keep warnings as "system message" paragraphs in the built documents. 108 | # keep_warnings = False 109 | 110 | # If true, `todo` and `todoList` produce output, else they produce nothing. 111 | todo_include_todos = False 112 | 113 | suppress_warnings = ["image.nonlocal_uri"] 114 | 115 | 116 | # -- Options for HTML output ---------------------------------------------- 117 | 118 | # The theme to use for HTML and HTML Help pages. See the documentation for 119 | # a list of builtin themes. 120 | html_theme = "solar" 121 | 122 | # Theme options are theme-specific and customize the look and feel of a theme 123 | # further. For a list of options available for each theme, see the 124 | # documentation. 125 | # html_theme_options = {} 126 | 127 | # Add any paths that contain custom themes here, relative to this directory. 128 | html_theme_path = ["_themes"] 129 | 130 | # The name for this set of Sphinx documents. If None, it defaults to 131 | # " v documentation". 132 | # html_title = None 133 | 134 | # A shorter title for the navigation bar. Default is the same as html_title. 135 | # html_short_title = None 136 | 137 | # The name of an image file (relative to this directory) to place at the top 138 | # of the sidebar. 139 | # html_logo = None 140 | 141 | # The name of an image file (within the static path) to use as favicon of the 142 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 143 | # pixels large. 144 | # html_favicon = None 145 | 146 | # Add any paths that contain custom static files (such as style sheets) here, 147 | # relative to this directory. They are copied after the builtin static files, 148 | # so a file named "default.css" will overwrite the builtin "default.css". 149 | html_static_path = [] 150 | 151 | # Add any extra paths that contain custom files (such as robots.txt or 152 | # .htaccess) here, relative to this directory. These files are copied 153 | # directly to the root of the documentation. 154 | # html_extra_path = [] 155 | 156 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 157 | # using the given strftime format. 158 | # html_last_updated_fmt = '%b %d, %Y' 159 | 160 | # If true, SmartyPants will be used to convert quotes and dashes to 161 | # typographically correct entities. 162 | # html_use_smartypants = True 163 | 164 | # Custom sidebar templates, maps document names to template names. 165 | # html_sidebars = {} 166 | 167 | # Additional templates that should be rendered to pages, maps page names to 168 | # template names. 169 | # html_additional_pages = {} 170 | 171 | # If false, no module index is generated. 172 | # html_domain_indices = True 173 | 174 | # If false, no index is generated. 175 | html_use_index = False 176 | 177 | # If true, the index is split into individual pages for each letter. 178 | # html_split_index = False 179 | 180 | # If true, links to the reST sources are added to the pages. 181 | html_show_sourcelink = True 182 | 183 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 184 | # html_show_sphinx = True 185 | 186 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 187 | # html_show_copyright = True 188 | 189 | # If true, an OpenSearch description file will be output, and all pages will 190 | # contain a tag referring to it. The value of this option must be the 191 | # base URL from which the finished HTML is served. 192 | # html_use_opensearch = '' 193 | 194 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 195 | # html_file_suffix = None 196 | 197 | # Language to be used for generating the HTML full-text search index. 198 | # Sphinx supports the following languages: 199 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 200 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' 201 | # html_search_language = 'en' 202 | 203 | # A dictionary with options for the search language support, empty by default. 204 | # Now only 'ja' uses this config value 205 | # html_search_options = {'type': 'default'} 206 | 207 | # The name of a javascript file (relative to the configuration directory) that 208 | # implements a search results scorer. If empty, the default will be used. 209 | # html_search_scorer = 'scorer.js' 210 | 211 | # Output file base name for HTML help builder. 212 | htmlhelp_basename = "Googletransdoc" 213 | 214 | # -- Options for LaTeX output --------------------------------------------- 215 | 216 | latex_elements = { 217 | # The paper size ('letterpaper' or 'a4paper'). 218 | #'papersize': 'letterpaper', 219 | # The font size ('10pt', '11pt' or '12pt'). 220 | #'pointsize': '10pt', 221 | # Additional stuff for the LaTeX preamble. 222 | #'preamble': '', 223 | # Latex figure (float) alignment 224 | #'figure_align': 'htbp', 225 | } 226 | 227 | # Grouping the document tree into LaTeX files. List of tuples 228 | # (source start file, target name, title, 229 | # author, documentclass [howto, manual, or own class]). 230 | latex_documents = [ 231 | ( 232 | master_doc, 233 | "Googletrans.tex", 234 | "Googletrans Documentation", 235 | "SuHun Han (ssut)", 236 | "manual", 237 | ), 238 | ] 239 | 240 | # The name of an image file (relative to this directory) to place at the top of 241 | # the title page. 242 | # latex_logo = None 243 | 244 | # For "manual" documents, if this is true, then toplevel headings are parts, 245 | # not chapters. 246 | # latex_use_parts = False 247 | 248 | # If true, show page references after internal links. 249 | # latex_show_pagerefs = False 250 | 251 | # If true, show URL addresses after external links. 252 | # latex_show_urls = False 253 | 254 | # Documents to append as an appendix to all manuals. 255 | # latex_appendices = [] 256 | 257 | # If false, no module index is generated. 258 | # latex_domain_indices = True 259 | 260 | 261 | # -- Options for manual page output --------------------------------------- 262 | 263 | # One entry per manual page. List of tuples 264 | # (source start file, name, description, authors, manual section). 265 | man_pages = [(master_doc, "Googletrans", "Googletrans Documentation", [author], 1)] 266 | 267 | # If true, show URL addresses after external links. 268 | # man_show_urls = False 269 | 270 | intersphinx_mapping = {"http://docs.python.org/": None} 271 | 272 | 273 | # -- Options for Texinfo output ------------------------------------------- 274 | 275 | # Grouping the document tree into Texinfo files. List of tuples 276 | # (source start file, target name, title, author, 277 | # dir menu entry, description, category) 278 | texinfo_documents = [ 279 | ( 280 | master_doc, 281 | "Googletrans", 282 | "Googletrans Documentation", 283 | author, 284 | "Googletrans", 285 | "One line description of project.", 286 | "Miscellaneous", 287 | ), 288 | ] 289 | 290 | # Documents to append as an appendix to all manuals. 291 | # texinfo_appendices = [] 292 | 293 | # If false, no module index is generated. 294 | # texinfo_domain_indices = True 295 | 296 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 297 | # texinfo_show_urls = 'footnote' 298 | 299 | # If true, do not generate a @detailmenu in the "Top" node's menu. 300 | # texinfo_no_detailmenu = False 301 | 302 | autodoc_member_order = "bysource" 303 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | =============================================================== 2 | Googletrans: Free and Unlimited Google translate API for Python 3 | =============================================================== 4 | 5 | .. image:: https://img.shields.io/github/license/mashape/apistatus.svg 6 | :target: http://opensource.org/licenses/MIT 7 | .. image:: https://travis-ci.org/ssut/py-googletrans.svg?branch=master 8 | :target: https://travis-ci.org/ssut/py-googletrans 9 | .. image:: https://readthedocs.org/projects/py-googletrans/badge/?version=latest 10 | :target: https://readthedocs.org/projects/py-googletrans/?badge=latest 11 | .. image:: https://badge.fury.io/py/googletrans.svg 12 | :target: http://badge.fury.io/py/googletrans 13 | .. image:: https://coveralls.io/repos/github/ssut/py-googletrans/badge.svg 14 | :target: https://coveralls.io/github/ssut/py-googletrans 15 | .. image:: https://codeclimate.com/github/ssut/py-googletrans/badges/gpa.svg 16 | :target: https://codeclimate.com/github/ssut/py-googletrans 17 | 18 | Googletrans is a **free** and **unlimited** python library that 19 | implemented Google Translate API. This uses the `Google Translate Ajax 20 | API `__ to make calls to such methods as 21 | detect and translate. 22 | 23 | -------- 24 | Features 25 | -------- 26 | 27 | - Fast and reliable - it uses the same servers that 28 | translate.google.com uses 29 | - Auto language detection 30 | - Bulk translations 31 | - Customizable service URL 32 | - Connection pooling (the advantage of using requests.Session) 33 | - HTTP/2 support 34 | 35 | ~~~~~~~~~~~~~~~~~~~~~ 36 | Note on library usage 37 | ~~~~~~~~~~~~~~~~~~~~~ 38 | 39 | - The maximum character limit on a single text is 15k. 40 | 41 | - Due to limitations of the web version of google translate, this API 42 | does not guarantee that the library would work properly at all times. 43 | (so please use this library if you don't care about stability.) 44 | 45 | - If you want to use a stable API, I highly recommend you to use 46 | `Google's official translate 47 | API `__. 48 | 49 | - If you get HTTP 5xx error or errors like #6, it's probably because 50 | Google has banned your client IP address. 51 | 52 | ---------- 53 | Quickstart 54 | ---------- 55 | 56 | You can install it from PyPI_: 57 | 58 | .. sourcecode:: bash 59 | 60 | $ pip install googletrans 61 | 62 | .. _PyPI: https://pypi.python.org/pypi/googletrans 63 | 64 | ~~~~~~~~~~~~~~ 65 | HTTP/2 support 66 | ~~~~~~~~~~~~~~ 67 | 68 | This is a great deal for everyone! (up to 2x times faster in my test) If 69 | you want to get googletrans faster you should install 70 | `hyper `__ package. Googletrans will 71 | automatically detect if hyper is installed and if so, it will be used 72 | for http networking. 73 | 74 | ~~~~~~~~~~~ 75 | Basic Usage 76 | ~~~~~~~~~~~ 77 | 78 | If source language is not given, google translate attempts to detect the 79 | source language. 80 | 81 | .. code-block:: python 82 | 83 | >>> from googletrans import Translator 84 | >>> translator = Translator() 85 | >>> translator.translate('안녕하세요.') 86 | # 87 | 88 | >>> translator.translate('안녕하세요.', dest='ja') 89 | # 90 | 91 | >>> translator.translate('veritas lux mea', src='la') 92 | # 93 | 94 | ~~~~~~~~~~~~~~~~~~~~~ 95 | Customize service URL 96 | ~~~~~~~~~~~~~~~~~~~~~ 97 | 98 | You can use another google translate domain for translation. If multiple 99 | URLs are provided it then randomly chooses a domain. 100 | 101 | .. code:: python 102 | 103 | >>> from googletrans import Translator 104 | >>> translator = Translator(service_urls=[ 105 | 'translate.google.com', 106 | 'translate.google.co.kr', 107 | ]) 108 | 109 | ~~~~~~~~~~~~~~~~~~~~~ 110 | Advanced Usage (Bulk) 111 | ~~~~~~~~~~~~~~~~~~~~~ 112 | 113 | Array can be used to translate a batch of strings in a single method 114 | call and a single HTTP session. The exact same method shown above work 115 | for arrays as well. 116 | 117 | .. code:: python 118 | 119 | >>> translations = translator.translate(['The quick brown fox', 'jumps over', 'the lazy dog'], dest='ko') 120 | >>> for translation in translations: 121 | ... print(translation.origin, ' -> ', translation.text) 122 | # The quick brown fox -> 빠른 갈색 여우 123 | # jumps over -> 이상 점프 124 | # the lazy dog -> 게으른 개 125 | 126 | ~~~~~~~~~~~~~~~~~~ 127 | Language detection 128 | ~~~~~~~~~~~~~~~~~~ 129 | 130 | The detect method, as its name implies, identifies the language used in 131 | a given sentence. 132 | 133 | .. code:: python 134 | 135 | >>> translator.detect('이 문장은 한글로 쓰여졌습니다.') 136 | # 137 | >>> translator.detect('この文章は日本語で書かれました。') 138 | # 139 | >>> translator.detect('This sentence is written in English.') 140 | # 141 | >>> translator.detect('Tiu frazo estas skribita en Esperanto.') 142 | # 143 | 144 | --------- 145 | API Guide 146 | --------- 147 | 148 | 149 | ====================== 150 | googletrans.Translator 151 | ====================== 152 | 153 | .. autoclass:: googletrans.Translator 154 | :members: 155 | 156 | ================== 157 | googletrans.models 158 | ================== 159 | 160 | .. automodule:: googletrans.models 161 | :members: 162 | 163 | ================== 164 | googletrans.gtoken 165 | ================== 166 | 167 | .. hint:: 168 | 169 | This is for internal use only to generate a valid token to access 170 | translate.google.com ajax API. 171 | 172 | .. automodule:: googletrans.gtoken 173 | :members: 174 | 175 | ===================== 176 | googletrans.LANGUAGES 177 | ===================== 178 | 179 | .. hint:: 180 | 181 | iso639-1 language codes for 182 | `supported languages `_ 183 | for translation. Some language codes also include a country code, like zh-CN or zh-TW. 184 | 185 | .. literalinclude:: ../googletrans/constants.py 186 | :language: python 187 | :lines: 70-182 188 | :linenos: 189 | 190 | ================================ 191 | googletrans.DEFAULT_SERVICE_URLS 192 | ================================ 193 | 194 | .. hint:: 195 | 196 | `DEFAULT_SERVICE_URLS `_ is the list of current available Google Translation service urls. 197 | 198 | For using these service urls, please check `Customize service URL`_. -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | echo. coverage to run coverage check of the documentation if enabled 41 | goto end 42 | ) 43 | 44 | if "%1" == "clean" ( 45 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 46 | del /q /s %BUILDDIR%\* 47 | goto end 48 | ) 49 | 50 | 51 | REM Check if sphinx-build is available and fallback to Python version if any 52 | %SPHINXBUILD% 2> nul 53 | if errorlevel 9009 goto sphinx_python 54 | goto sphinx_ok 55 | 56 | :sphinx_python 57 | 58 | set SPHINXBUILD=python -m sphinx.__init__ 59 | %SPHINXBUILD% 2> nul 60 | if errorlevel 9009 ( 61 | echo. 62 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 63 | echo.installed, then set the SPHINXBUILD environment variable to point 64 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 65 | echo.may add the Sphinx directory to PATH. 66 | echo. 67 | echo.If you don't have Sphinx installed, grab it from 68 | echo.http://sphinx-doc.org/ 69 | exit /b 1 70 | ) 71 | 72 | :sphinx_ok 73 | 74 | 75 | if "%1" == "html" ( 76 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 80 | goto end 81 | ) 82 | 83 | if "%1" == "dirhtml" ( 84 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 88 | goto end 89 | ) 90 | 91 | if "%1" == "singlehtml" ( 92 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 93 | if errorlevel 1 exit /b 1 94 | echo. 95 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 96 | goto end 97 | ) 98 | 99 | if "%1" == "pickle" ( 100 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 101 | if errorlevel 1 exit /b 1 102 | echo. 103 | echo.Build finished; now you can process the pickle files. 104 | goto end 105 | ) 106 | 107 | if "%1" == "json" ( 108 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 109 | if errorlevel 1 exit /b 1 110 | echo. 111 | echo.Build finished; now you can process the JSON files. 112 | goto end 113 | ) 114 | 115 | if "%1" == "htmlhelp" ( 116 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 117 | if errorlevel 1 exit /b 1 118 | echo. 119 | echo.Build finished; now you can run HTML Help Workshop with the ^ 120 | .hhp project file in %BUILDDIR%/htmlhelp. 121 | goto end 122 | ) 123 | 124 | if "%1" == "qthelp" ( 125 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 129 | .qhcp project file in %BUILDDIR%/qthelp, like this: 130 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\py-googletrans.qhcp 131 | echo.To view the help file: 132 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\py-googletrans.ghc 133 | goto end 134 | ) 135 | 136 | if "%1" == "devhelp" ( 137 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. 141 | goto end 142 | ) 143 | 144 | if "%1" == "epub" ( 145 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 149 | goto end 150 | ) 151 | 152 | if "%1" == "latex" ( 153 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 157 | goto end 158 | ) 159 | 160 | if "%1" == "latexpdf" ( 161 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 162 | cd %BUILDDIR%/latex 163 | make all-pdf 164 | cd %~dp0 165 | echo. 166 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 167 | goto end 168 | ) 169 | 170 | if "%1" == "latexpdfja" ( 171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 172 | cd %BUILDDIR%/latex 173 | make all-pdf-ja 174 | cd %~dp0 175 | echo. 176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 177 | goto end 178 | ) 179 | 180 | if "%1" == "text" ( 181 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 182 | if errorlevel 1 exit /b 1 183 | echo. 184 | echo.Build finished. The text files are in %BUILDDIR%/text. 185 | goto end 186 | ) 187 | 188 | if "%1" == "man" ( 189 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 190 | if errorlevel 1 exit /b 1 191 | echo. 192 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 193 | goto end 194 | ) 195 | 196 | if "%1" == "texinfo" ( 197 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 198 | if errorlevel 1 exit /b 1 199 | echo. 200 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 201 | goto end 202 | ) 203 | 204 | if "%1" == "gettext" ( 205 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 206 | if errorlevel 1 exit /b 1 207 | echo. 208 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 209 | goto end 210 | ) 211 | 212 | if "%1" == "changes" ( 213 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 214 | if errorlevel 1 exit /b 1 215 | echo. 216 | echo.The overview file is in %BUILDDIR%/changes. 217 | goto end 218 | ) 219 | 220 | if "%1" == "linkcheck" ( 221 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 222 | if errorlevel 1 exit /b 1 223 | echo. 224 | echo.Link check complete; look for any errors in the above output ^ 225 | or in %BUILDDIR%/linkcheck/output.txt. 226 | goto end 227 | ) 228 | 229 | if "%1" == "doctest" ( 230 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 231 | if errorlevel 1 exit /b 1 232 | echo. 233 | echo.Testing of doctests in the sources finished, look at the ^ 234 | results in %BUILDDIR%/doctest/output.txt. 235 | goto end 236 | ) 237 | 238 | if "%1" == "coverage" ( 239 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 240 | if errorlevel 1 exit /b 1 241 | echo. 242 | echo.Testing of coverage in the sources finished, look at the ^ 243 | results in %BUILDDIR%/coverage/python.txt. 244 | goto end 245 | ) 246 | 247 | if "%1" == "xml" ( 248 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 249 | if errorlevel 1 exit /b 1 250 | echo. 251 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 252 | goto end 253 | ) 254 | 255 | if "%1" == "pseudoxml" ( 256 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 257 | if errorlevel 1 exit /b 1 258 | echo. 259 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 260 | goto end 261 | ) 262 | 263 | :end 264 | -------------------------------------------------------------------------------- /example/translate_word_doc.py: -------------------------------------------------------------------------------- 1 | from docx import Document 2 | from googletrans import Translator 3 | 4 | 5 | def translate_doc(filename, destination="zh-CN", mix=True): 6 | """ 7 | translate a word document type of file and save the result as document and keep the exactly same file format. 8 | :param filename: word doc file 9 | :param destination='zh-CN': 10 | :param mix=True: if True, will have original language and target language into the same doc. paragraphs by paragraphs. 11 | """ 12 | 13 | def tx(t): 14 | return Translator().translate(t, dest=destination).text 15 | 16 | doc = Document(filename) 17 | for p in doc.paragraphs: 18 | txd = tx(p.text) 19 | 20 | p.text = p.text + ("\n" + txd if mix else "") 21 | 22 | for table in doc.tables: 23 | for row in table.rows: 24 | for cell in row.cells: 25 | txd = tx(cell.text) 26 | p.text = cell.text + ("\n" + txd if mix else "") 27 | 28 | f = filename.replace(".doc", destination.lower() + ".doc") 29 | doc.save(f) 30 | 31 | 32 | if __name__ == "__main__": 33 | filename = "p1.docx" 34 | translate_doc(filename) 35 | -------------------------------------------------------------------------------- /googletrans/__init__.py: -------------------------------------------------------------------------------- 1 | """Free Google Translate API for Python. Translates totally free of charge.""" 2 | 3 | __all__ = ("Translator",) 4 | __version__ = "3.4.0" 5 | 6 | 7 | from googletrans.client import Translator 8 | from googletrans.constants import LANGCODES, LANGUAGES # noqa 9 | -------------------------------------------------------------------------------- /googletrans/client.py: -------------------------------------------------------------------------------- 1 | """ 2 | A Translation module. 3 | 4 | You can translate text using this module. 5 | """ 6 | 7 | import asyncio 8 | import random 9 | import re 10 | import typing 11 | 12 | import httpx 13 | from httpx import Response, Timeout 14 | from httpx._types import ProxyTypes 15 | 16 | from googletrans import urls, utils 17 | from googletrans.constants import ( 18 | DEFAULT_CLIENT_SERVICE_URLS, 19 | DEFAULT_RAISE_EXCEPTION, 20 | DEFAULT_USER_AGENT, 21 | DUMMY_DATA, 22 | LANGCODES, 23 | LANGUAGES, 24 | SPECIAL_CASES, 25 | ) 26 | from googletrans.gtoken import TokenAcquirer 27 | from googletrans.models import Detected, Translated 28 | 29 | EXCLUDES = ("en", "ca", "fr") 30 | 31 | 32 | class Translator: 33 | """Google Translate ajax API implementation class 34 | 35 | You have to create an instance of Translator to use this API 36 | 37 | :param service_urls: google translate url list. URLs will be used randomly. 38 | For example ``['translate.google.com', 'translate.google.co.kr']`` 39 | To preferably use the non webapp api, service url should be translate.googleapis.com 40 | :type service_urls: a sequence of strings 41 | 42 | :param user_agent: the User-Agent header to send when making requests. 43 | :type user_agent: :class:`str` 44 | 45 | :param proxy: httpx proxy configuration. 46 | 47 | :param timeout: Definition of timeout for httpx library. 48 | Will be used for every request. 49 | :type timeout: number or a double of numbers 50 | :param raise_exception: if `True` then raise exception if smth will go wrong 51 | :type raise_exception: boolean 52 | """ 53 | 54 | def __init__( 55 | self, 56 | service_urls: typing.Sequence[str] = DEFAULT_CLIENT_SERVICE_URLS, 57 | user_agent: str = DEFAULT_USER_AGENT, 58 | raise_exception: bool = DEFAULT_RAISE_EXCEPTION, 59 | proxy: typing.Optional[ProxyTypes] = None, 60 | timeout: typing.Optional[Timeout] = None, 61 | http2: bool = True, 62 | list_operation_max_concurrency: int = 2, 63 | ): 64 | self.client = httpx.AsyncClient( 65 | http2=http2, 66 | proxy=proxy, 67 | headers={ 68 | "User-Agent": user_agent, 69 | }, 70 | ) 71 | 72 | self.service_urls = ["translate.google.com"] 73 | self.client_type = "webapp" 74 | self.token_acquirer = TokenAcquirer( 75 | client=self.client, host=self.service_urls[0] 76 | ) 77 | 78 | if timeout is not None: 79 | self.client.timeout = timeout 80 | 81 | if service_urls: 82 | # default way of working: use the defined values from user app 83 | self.service_urls = service_urls 84 | self.client_type = "webapp" 85 | self.token_acquirer = TokenAcquirer( 86 | client=self.client, host=self.service_urls[0] 87 | ) 88 | 89 | # if we have a service url pointing to client api we force the use of it as defaut client 90 | for t in enumerate(service_urls): 91 | api_type = re.search("googleapis", service_urls[0]) 92 | if api_type: 93 | self.service_urls = ["translate.googleapis.com"] 94 | self.client_type = "gtx" 95 | break 96 | 97 | self.raise_exception = raise_exception 98 | self.list_operation_max_concurrency = list_operation_max_concurrency 99 | 100 | def _pick_service_url(self) -> str: 101 | if len(self.service_urls) == 1: 102 | return self.service_urls[0] 103 | return random.choice(self.service_urls) 104 | 105 | async def __aenter__(self): 106 | return self 107 | 108 | async def __aexit__(self, exc_type, exc_val, exc_tb): 109 | await self.client.aclose() 110 | 111 | async def _translate( 112 | self, text: str, dest: str, src: str, override: typing.Dict[str, typing.Any] 113 | ) -> typing.Tuple[typing.List[typing.Any], Response]: 114 | token = "xxxx" # dummy default value here as it is not used by api client 115 | if self.client_type == "webapp": 116 | token = await self.token_acquirer.do(text) 117 | 118 | params = utils.build_params( 119 | client=self.client_type, 120 | query=text, 121 | src=src, 122 | dest=dest, 123 | token=token, 124 | override=override, 125 | ) 126 | 127 | url = urls.TRANSLATE.format(host=self._pick_service_url()) 128 | r = await self.client.get(url, params=params) 129 | 130 | if r.status_code == 200: 131 | data = utils.format_json(r.text) 132 | if not isinstance(data, list): 133 | data = [data] # Convert dict to list to match return type 134 | return data, r 135 | 136 | if self.raise_exception: 137 | raise Exception( 138 | 'Unexpected status code "{}" from {}'.format( 139 | r.status_code, self.service_urls 140 | ) 141 | ) 142 | 143 | DUMMY_DATA[0][0][0] = text 144 | return DUMMY_DATA, r 145 | 146 | async def build_request( 147 | self, text: str, dest: str, src: str, override: typing.Dict[str, typing.Any] 148 | ) -> httpx.Request: 149 | """Async helper for making the translation request""" 150 | token = "xxxx" # dummy default value here as it is not used by api client 151 | if self.client_type == "webapp": 152 | token = await self.token_acquirer.do(text) 153 | 154 | params = utils.build_params( 155 | client=self.client_type, 156 | query=text, 157 | src=src, 158 | dest=dest, 159 | token=token, 160 | override=override, 161 | ) 162 | 163 | url = urls.TRANSLATE.format(host=self._pick_service_url()) 164 | 165 | return self.client.build_request("GET", url, params=params) 166 | 167 | def _parse_extra_data( 168 | self, data: typing.List[typing.Any] 169 | ) -> typing.Dict[str, typing.Any]: 170 | response_parts_name_mapping = { 171 | 0: "translation", 172 | 1: "all-translations", 173 | 2: "original-language", 174 | 5: "possible-translations", 175 | 6: "confidence", 176 | 7: "possible-mistakes", 177 | 8: "language", 178 | 11: "synonyms", 179 | 12: "definitions", 180 | 13: "examples", 181 | 14: "see-also", 182 | } 183 | 184 | extra = {} 185 | 186 | for index, category in response_parts_name_mapping.items(): 187 | extra[category] = ( 188 | data[index] if (index < len(data) and data[index]) else None 189 | ) 190 | 191 | return extra 192 | 193 | @typing.overload 194 | async def translate( 195 | self, text: str, dest: str = ..., src: str = ..., **kwargs: typing.Any 196 | ) -> Translated: ... 197 | 198 | @typing.overload 199 | async def translate( 200 | self, 201 | text: typing.List[str], 202 | dest: str = ..., 203 | src: str = ..., 204 | **kwargs: typing.Any, 205 | ) -> typing.List[Translated]: ... 206 | 207 | async def translate( 208 | self, 209 | text: typing.Union[str, typing.List[str]], 210 | dest: str = "en", 211 | src: str = "auto", 212 | **kwargs: typing.Any, 213 | ) -> typing.Union[Translated, typing.List[Translated]]: 214 | """Translate text from source language to destination language 215 | 216 | :param text: The source text(s) to be translated. Batch translation is supported via sequence input. 217 | :type text: UTF-8 :class:`str`; :class:`unicode`; string sequence (list, tuple, iterator, generator) 218 | 219 | :param dest: The language to translate the source text into. 220 | The value should be one of the language codes listed in :const:`googletrans.LANGUAGES` 221 | or one of the language names listed in :const:`googletrans.LANGCODES`. 222 | :param dest: :class:`str`; :class:`unicode` 223 | 224 | :param src: The language of the source text. 225 | The value should be one of the language codes listed in :const:`googletrans.LANGUAGES` 226 | or one of the language names listed in :const:`googletrans.LANGCODES`. 227 | If a language is not specified, 228 | the system will attempt to identify the source language automatically. 229 | :param src: :class:`str`; :class:`unicode` 230 | 231 | :rtype: Translated 232 | :rtype: :class:`list` (when a list is passed) 233 | 234 | Basic usage: 235 | >>> from googletrans import Translator 236 | >>> translator = Translator() 237 | >>> translator.translate('안녕하세요.') 238 | 239 | >>> translator.translate('안녕하세요.', dest='ja') 240 | 241 | >>> translator.translate('veritas lux mea', src='la') 242 | 243 | 244 | Advanced usage: 245 | >>> translations = translator.translate(['The quick brown fox', 'jumps over', 'the lazy dog'], dest='ko') 246 | >>> for translation in translations: 247 | ... print(translation.origin, ' -> ', translation.text) 248 | The quick brown fox -> 빠른 갈색 여우 249 | jumps over -> 이상 점프 250 | the lazy dog -> 게으른 개 251 | """ 252 | dest = dest.lower().split("_", 1)[0] 253 | src = src.lower().split("_", 1)[0] 254 | 255 | if src != "auto" and src not in LANGUAGES: 256 | if src in SPECIAL_CASES: 257 | src = SPECIAL_CASES[src] 258 | elif src in LANGCODES: 259 | src = LANGCODES[src] 260 | else: 261 | raise ValueError("invalid source language") 262 | 263 | if dest not in LANGUAGES: 264 | if dest in SPECIAL_CASES: 265 | dest = SPECIAL_CASES[dest] 266 | elif dest in LANGCODES: 267 | dest = LANGCODES[dest] 268 | else: 269 | raise ValueError("invalid destination language") 270 | 271 | if isinstance(text, list): 272 | concurrency_limit = kwargs.pop( 273 | "list_operation_max_concurrency", self.list_operation_max_concurrency 274 | ) 275 | semaphore = asyncio.Semaphore(concurrency_limit) 276 | 277 | async def translate_with_semaphore(item): 278 | async with semaphore: 279 | return await self.translate(item, dest=dest, src=src, **kwargs) 280 | 281 | tasks = [translate_with_semaphore(item) for item in text] 282 | result = await asyncio.gather(*tasks) 283 | return result 284 | 285 | origin = text 286 | data, response = await self._translate(text, dest, src, kwargs) 287 | 288 | # this code will be updated when the format is changed. 289 | translated = "".join([d[0] if d[0] else "" for d in data[0]]) 290 | 291 | extra_data = self._parse_extra_data(data) 292 | 293 | # actual source language that will be recognized by Google Translator when the 294 | # src passed is equal to auto. 295 | try: 296 | src = data[2] 297 | except Exception: # pragma: nocover 298 | pass 299 | 300 | pron = origin 301 | try: 302 | pron = data[0][1][-2] 303 | except Exception: # pragma: nocover 304 | pass 305 | 306 | if pron is None: 307 | try: 308 | pron = data[0][1][2] 309 | except: # pragma: nocover # noqa: E722 310 | pass 311 | 312 | if dest in EXCLUDES and pron == origin: 313 | pron = translated 314 | 315 | # put final values into a new Translated object 316 | result = Translated( 317 | src=src, 318 | dest=dest, 319 | origin=origin, 320 | text=translated, 321 | pronunciation=pron, 322 | extra_data=extra_data, 323 | response=response, 324 | ) 325 | 326 | return result 327 | 328 | @typing.overload 329 | async def detect(self, text: str, **kwargs: typing.Any) -> Detected: ... 330 | 331 | @typing.overload 332 | async def detect( 333 | self, text: typing.List[str], **kwargs: typing.Any 334 | ) -> typing.List[Detected]: ... 335 | 336 | async def detect( 337 | self, text: typing.Union[str, typing.List[str]], **kwargs: typing.Any 338 | ) -> typing.Union[Detected, typing.List[Detected]]: 339 | """Detect language of the input text 340 | 341 | :param text: The source text(s) whose language you want to identify. 342 | Batch detection is supported via sequence input. 343 | :type text: UTF-8 :class:`str`; :class:`unicode`; string sequence (list, tuple, iterator, generator) 344 | 345 | :rtype: Detected 346 | :rtype: :class:`list` (when a list is passed) 347 | 348 | Basic usage: 349 | >>> from googletrans import Translator 350 | >>> translator = Translator() 351 | >>> translator.detect('이 문장은 한글로 쓰여졌습니다.') 352 | 353 | >>> translator.detect('この文章は日本語で書かれました。') 354 | 355 | >>> translator.detect('This sentence is written in English.') 356 | 357 | >>> translator.detect('Tiu frazo estas skribita en Esperanto.') 358 | 359 | 360 | Advanced usage: 361 | >>> langs = translator.detect(['한국어', '日本語', 'English', 'le français']) 362 | >>> for lang in langs: 363 | ... print(lang.lang, lang.confidence) 364 | ko 1 365 | ja 0.92929292 366 | en 0.96954316 367 | fr 0.043500196 368 | """ 369 | if isinstance(text, list): 370 | concurrency_limit = kwargs.pop( 371 | "list_operation_max_concurrency", self.list_operation_max_concurrency 372 | ) 373 | semaphore = asyncio.Semaphore(concurrency_limit) 374 | 375 | async def detect_with_semaphore(item): 376 | async with semaphore: 377 | return await self.detect(item, **kwargs) 378 | 379 | tasks = [detect_with_semaphore(item) for item in text] 380 | result = await asyncio.gather(*tasks) 381 | return result 382 | 383 | data, response = await self._translate(text, "en", "auto", kwargs) 384 | 385 | # actual source language that will be recognized by Google Translator when the 386 | # src passed is equal to auto. 387 | src = "" 388 | confidence = 0.0 389 | try: 390 | if len(data[8][0]) > 1: 391 | src = data[8][0] 392 | confidence = data[8][-2] 393 | else: 394 | src = "".join(data[8][0]) 395 | confidence = data[8][-2][0] 396 | except Exception: # pragma: nocover 397 | pass 398 | result = Detected(lang=src, confidence=confidence, response=response) 399 | 400 | return result 401 | -------------------------------------------------------------------------------- /googletrans/constants.py: -------------------------------------------------------------------------------- 1 | DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" 2 | 3 | DEFAULT_CLIENT_SERVICE_URLS = ("translate.googleapis.com",) 4 | 5 | DEFAULT_SERVICE_URLS = ( 6 | "translate.google.ac", 7 | "translate.google.ad", 8 | "translate.google.ae", 9 | "translate.google.al", 10 | "translate.google.am", 11 | "translate.google.as", 12 | "translate.google.at", 13 | "translate.google.az", 14 | "translate.google.ba", 15 | "translate.google.be", 16 | "translate.google.bf", 17 | "translate.google.bg", 18 | "translate.google.bi", 19 | "translate.google.bj", 20 | "translate.google.bs", 21 | "translate.google.bt", 22 | "translate.google.by", 23 | "translate.google.ca", 24 | "translate.google.cat", 25 | "translate.google.cc", 26 | "translate.google.cd", 27 | "translate.google.cf", 28 | "translate.google.cg", 29 | "translate.google.ch", 30 | "translate.google.ci", 31 | "translate.google.cl", 32 | "translate.google.cm", 33 | "translate.google.cn", 34 | "translate.google.co.ao", 35 | "translate.google.co.bw", 36 | "translate.google.co.ck", 37 | "translate.google.co.cr", 38 | "translate.google.co.id", 39 | "translate.google.co.il", 40 | "translate.google.co.in", 41 | "translate.google.co.jp", 42 | "translate.google.co.ke", 43 | "translate.google.co.kr", 44 | "translate.google.co.ls", 45 | "translate.google.co.ma", 46 | "translate.google.co.mz", 47 | "translate.google.co.nz", 48 | "translate.google.co.th", 49 | "translate.google.co.tz", 50 | "translate.google.co.ug", 51 | "translate.google.co.uk", 52 | "translate.google.co.uz", 53 | "translate.google.co.ve", 54 | "translate.google.co.vi", 55 | "translate.google.co.za", 56 | "translate.google.co.zm", 57 | "translate.google.co.zw", 58 | "translate.google.com.af", 59 | "translate.google.com.ag", 60 | "translate.google.com.ai", 61 | "translate.google.com.ar", 62 | "translate.google.com.au", 63 | "translate.google.com.bd", 64 | "translate.google.com.bh", 65 | "translate.google.com.bn", 66 | "translate.google.com.bo", 67 | "translate.google.com.br", 68 | "translate.google.com.bz", 69 | "translate.google.com.co", 70 | "translate.google.com.cu", 71 | "translate.google.com.cy", 72 | "translate.google.com.do", 73 | "translate.google.com.ec", 74 | "translate.google.com.eg", 75 | "translate.google.com.et", 76 | "translate.google.com.fj", 77 | "translate.google.com.gh", 78 | "translate.google.com.gi", 79 | "translate.google.com.gt", 80 | "translate.google.com.hk", 81 | "translate.google.com.jm", 82 | "translate.google.com.kh", 83 | "translate.google.com.kw", 84 | "translate.google.com.lb", 85 | "translate.google.com.ly", 86 | "translate.google.com.mm", 87 | "translate.google.com.mt", 88 | "translate.google.com.mx", 89 | "translate.google.com.my", 90 | "translate.google.com.na", 91 | "translate.google.com.ng", 92 | "translate.google.com.ni", 93 | "translate.google.com.np", 94 | "translate.google.com.om", 95 | "translate.google.com.pa", 96 | "translate.google.com.pe", 97 | "translate.google.com.pg", 98 | "translate.google.com.ph", 99 | "translate.google.com.pk", 100 | "translate.google.com.pr", 101 | "translate.google.com.py", 102 | "translate.google.com.qa", 103 | "translate.google.com.sa", 104 | "translate.google.com.sb", 105 | "translate.google.com.sg", 106 | "translate.google.com.sl", 107 | "translate.google.com.sv", 108 | "translate.google.com.tj", 109 | "translate.google.com.tr", 110 | "translate.google.com.tw", 111 | "translate.google.com.ua", 112 | "translate.google.com.uy", 113 | "translate.google.com.vc", 114 | "translate.google.com.vn", 115 | "translate.google.com", 116 | "translate.google.cv", 117 | "translate.google.cz", 118 | "translate.google.de", 119 | "translate.google.dj", 120 | "translate.google.dk", 121 | "translate.google.dm", 122 | "translate.google.dz", 123 | "translate.google.ee", 124 | "translate.google.es", 125 | "translate.google.eu", 126 | "translate.google.fi", 127 | "translate.google.fm", 128 | "translate.google.fr", 129 | "translate.google.ga", 130 | "translate.google.ge", 131 | "translate.google.gf", 132 | "translate.google.gg", 133 | "translate.google.gl", 134 | "translate.google.gm", 135 | "translate.google.gp", 136 | "translate.google.gr", 137 | "translate.google.gy", 138 | "translate.google.hn", 139 | "translate.google.hr", 140 | "translate.google.ht", 141 | "translate.google.hu", 142 | "translate.google.ie", 143 | "translate.google.im", 144 | "translate.google.io", 145 | "translate.google.iq", 146 | "translate.google.is", 147 | "translate.google.it", 148 | "translate.google.je", 149 | "translate.google.jo", 150 | "translate.google.kg", 151 | "translate.google.ki", 152 | "translate.google.kz", 153 | "translate.google.la", 154 | "translate.google.li", 155 | "translate.google.lk", 156 | "translate.google.lt", 157 | "translate.google.lu", 158 | "translate.google.lv", 159 | "translate.google.md", 160 | "translate.google.me", 161 | "translate.google.mg", 162 | "translate.google.mk", 163 | "translate.google.ml", 164 | "translate.google.mn", 165 | "translate.google.ms", 166 | "translate.google.mu", 167 | "translate.google.mv", 168 | "translate.google.mw", 169 | "translate.google.ne", 170 | "translate.google.nf", 171 | "translate.google.nl", 172 | "translate.google.no", 173 | "translate.google.nr", 174 | "translate.google.nu", 175 | "translate.google.pl", 176 | "translate.google.pn", 177 | "translate.google.ps", 178 | "translate.google.pt", 179 | "translate.google.ro", 180 | "translate.google.rs", 181 | "translate.google.ru", 182 | "translate.google.rw", 183 | "translate.google.sc", 184 | "translate.google.se", 185 | "translate.google.sh", 186 | "translate.google.si", 187 | "translate.google.sk", 188 | "translate.google.sm", 189 | "translate.google.sn", 190 | "translate.google.so", 191 | "translate.google.sr", 192 | "translate.google.st", 193 | "translate.google.td", 194 | "translate.google.tg", 195 | "translate.google.tk", 196 | "translate.google.tl", 197 | "translate.google.tm", 198 | "translate.google.tn", 199 | "translate.google.to", 200 | "translate.google.tt", 201 | "translate.google.us", 202 | "translate.google.vg", 203 | "translate.google.vu", 204 | "translate.google.ws", 205 | ) 206 | 207 | SPECIAL_CASES = { 208 | "ee": "et", 209 | } 210 | 211 | LANGUAGES = { 212 | "abk": "abkhaz", 213 | "ace": "acehnese", 214 | "ach": "acholi", 215 | "aar": "afar", 216 | "af": "afrikaans", 217 | "sq": "albanian", 218 | "alz": "alur", 219 | "am": "amharic", 220 | "ar": "arabic", 221 | "hy": "armenian", 222 | "as": "assamese", 223 | "ava": "avar", 224 | "awa": "awadhi", 225 | "ay": "aymara", 226 | "az": "azerbaijani", 227 | "ban": "balinese", 228 | "bal": "baluchi", 229 | "bm": "bambara", 230 | "bci": "baoulé", 231 | "bak": "bashkir", 232 | "eu": "basque", 233 | "btx": "batak karo", 234 | "bts": "batak simalungun", 235 | "bbc": "batak toba", 236 | "be": "belarusian", 237 | "bem": "bemba", 238 | "bn": "bengali", 239 | "bew": "betawi", 240 | "bho": "bhojpuri", 241 | "bik": "bikol", 242 | "bs": "bosnian", 243 | "bre": "breton", 244 | "bg": "bulgarian", 245 | "bua": "buryat", 246 | "yue": "cantonese", 247 | "ca": "catalan", 248 | "ceb": "cebuano", 249 | "cha": "chamorro", 250 | "che": "chechen", 251 | "zh": "chinese", 252 | "zh-cn": "chinese (simplified)", 253 | "zh-tw": "chinese (traditional)", 254 | "chk": "chuukese", 255 | "chv": "chuvash", 256 | "co": "corsican", 257 | "crh": "crimean tatar", 258 | "hr": "croatian", 259 | "cs": "czech", 260 | "da": "danish", 261 | "fa-af": "dari", 262 | "dv": "dhivehi", 263 | "din": "dinka", 264 | "doi": "dogri", 265 | "dom": "dombe", 266 | "nl": "dutch", 267 | "dyu": "dyula", 268 | "dzo": "dzongkha", 269 | "en": "english", 270 | "eo": "esperanto", 271 | "et": "estonian", 272 | "fao": "faroese", 273 | "fij": "fijian", 274 | "fil": "filipino (tagalog)", 275 | "fi": "finnish", 276 | "fon": "fon", 277 | "fr": "french", 278 | "fy": "frisian", 279 | "fur": "friulian", 280 | "ful": "fulani", 281 | "gaa": "ga", 282 | "gl": "galician", 283 | "ka": "georgian", 284 | "de": "german", 285 | "el": "greek", 286 | "gn": "guarani", 287 | "gu": "gujarati", 288 | "ht": "haitian creole", 289 | "cnh": "hakha chin", 290 | "ha": "hausa", 291 | "haw": "hawaiian", 292 | "he": "hebrew", 293 | "iw": "hebrew", 294 | "hil": "hiligaynon", 295 | "hi": "hindi", 296 | "hmn": "hmong", 297 | "hu": "hungarian", 298 | "hrx": "hunsrik", 299 | "iba": "iban", 300 | "is": "icelandic", 301 | "ig": "igbo", 302 | "ilo": "ilocano", 303 | "id": "indonesian", 304 | "ga": "irish", 305 | "it": "italian", 306 | "jam": "jamaican patois", 307 | "ja": "japanese", 308 | "jv": "javanese", 309 | "jw": "javanese", 310 | "kac": "jingpo", 311 | "kal": "kalaallisut", 312 | "kn": "kannada", 313 | "kau": "kanuri", 314 | "pam": "kapampangan", 315 | "kk": "kazakh", 316 | "kha": "khasi", 317 | "km": "khmer", 318 | "cgg": "kiga", 319 | "kik": "kikongo", 320 | "rw": "kinyarwanda", 321 | "ktu": "kituba", 322 | "trp": "kokborok", 323 | "kom": "komi", 324 | "gom": "konkani", 325 | "ko": "korean", 326 | "kri": "krio", 327 | "ku": "kurdish", 328 | "ckb": "kurdish (sorani)", 329 | "ky": "kyrgyz", 330 | "lo": "lao", 331 | "ltg": "latgalian", 332 | "la": "latin", 333 | "lv": "latvian", 334 | "lij": "ligurian", 335 | "lim": "limburgish", 336 | "ln": "lingala", 337 | "lt": "lithuanian", 338 | "lmo": "lombard", 339 | "lg": "luganda", 340 | "luo": "luo", 341 | "lb": "luxembourgish", 342 | "mk": "macedonian", 343 | "mad": "madurese", 344 | "mai": "maithili", 345 | "mak": "makassar", 346 | "mg": "malagasy", 347 | "ms": "malay", 348 | "ms-arab": "malay (jawi)", 349 | "ml": "malayalam", 350 | "mt": "maltese", 351 | "mam": "mam", 352 | "glv": "manx", 353 | "mi": "maori", 354 | "mr": "marathi", 355 | "mah": "marshallese", 356 | "mwr": "marwadi", 357 | "mfe": "mauritian creole", 358 | "mhr": "meadow mari", 359 | "mni-mtei": "meiteilon (manipuri)", 360 | "min": "minang", 361 | "lus": "mizo", 362 | "mn": "mongolian", 363 | "my": "myanmar (burmese)", 364 | "nhe": "nahuatl (eastern huasteca)", 365 | "ndc-zw": "ndau", 366 | "nde": "ndebele (south)", 367 | "new": "nepalbhasa (newari)", 368 | "ne": "nepali", 369 | #'bm-nkoo': 'nko', 370 | "no": "norwegian", 371 | "nus": "nuer", 372 | "ny": "nyanja (chichewa)", 373 | "oci": "occitan", 374 | "or": "odia (oriya)", 375 | "om": "oromo", 376 | "oss": "ossetian", 377 | "pag": "pangasinan", 378 | "pap": "papiamento", 379 | "ps": "pashto", 380 | "fa": "persian", 381 | "pl": "polish", 382 | "por": "portuguese (portugal)", 383 | "pt": "portuguese (portugal, brazil)", 384 | "pa": "punjabi", 385 | "pa-arab": "punjabi (shahmukhi)", 386 | "kek": "q'eqchi'", 387 | "qu": "quechua", 388 | "rom": "romani", 389 | "ro": "romanian", 390 | "run": "rundi", 391 | "ru": "russian", 392 | "sme": "sami (north)", 393 | "sm": "samoan", 394 | "sag": "sango", 395 | "sa": "sanskrit", 396 | "sat": "santali", 397 | "gd": "scots gaelic", 398 | "nso": "sepedi", 399 | "sr": "serbian", 400 | "st": "sesotho", 401 | "crs": "seychellois creole", 402 | "shn": "shan", 403 | "sn": "shona", 404 | "scn": "sicilian", 405 | "szl": "silesian", 406 | "sd": "sindhi", 407 | "si": "sinhala (sinhalese)", 408 | "sk": "slovak", 409 | "sl": "slovenian", 410 | "so": "somali", 411 | "es": "spanish", 412 | "su": "sundanese", 413 | "sus": "susu", 414 | "sw": "swahili", 415 | "ssw": "swati", 416 | "sv": "swedish", 417 | "tl": "tagalog (filipino)", 418 | "tah": "tahitian", 419 | "tg": "tajik", 420 | "ber-latn": "tamazight", 421 | "ber": "tamazight (tifinagh)", 422 | "ta": "tamil", 423 | "tt": "tatar", 424 | "te": "telugu", 425 | "tet": "tetum", 426 | "th": "thai", 427 | "bod": "tibetan", 428 | "ti": "tigrinya", 429 | "tiv": "tiv", 430 | "tpi": "tok pisin", 431 | "ton": "tongan", 432 | "ts": "tsonga", 433 | "tsn": "tswana", 434 | "tcy": "tulu", 435 | "tum": "tumbuka", 436 | "tr": "turkish", 437 | "tk": "turkmen", 438 | "tuk": "tuvan", 439 | "ak": "twi (akan)", 440 | "udm": "udmurt", 441 | "uk": "ukrainian", 442 | "ur": "urdu", 443 | "ug": "uyghur", 444 | "uz": "uzbek", 445 | "ven": "venda", 446 | "vec": "venetian", 447 | "vi": "vietnamese", 448 | "war": "waray", 449 | "cy": "welsh", 450 | "wol": "wolof", 451 | "xh": "xhosa", 452 | "sah": "yakut", 453 | "yi": "yiddish", 454 | "yo": "yoruba", 455 | "yua": "yucatec maya", 456 | "zap": "zapotec", 457 | "zu": "zulu", 458 | } 459 | 460 | LANGCODES = {v: k for k, v in LANGUAGES.items()} 461 | DEFAULT_RAISE_EXCEPTION = False 462 | DUMMY_DATA = [ 463 | [["", None, None, 0]], 464 | None, 465 | "en", 466 | None, 467 | None, 468 | None, 469 | 1, 470 | None, 471 | [["en"], None, [1], ["en"]], 472 | ] 473 | -------------------------------------------------------------------------------- /googletrans/gtoken.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import ast 3 | import math 4 | import re 5 | import time 6 | from typing import Any, Callable, Dict, List 7 | 8 | import httpx 9 | 10 | from googletrans.utils import rshift 11 | 12 | 13 | class TokenAcquirer: 14 | """Google Translate API token generator 15 | 16 | translate.google.com uses a token to authorize the requests. If you are 17 | not Google, you do have this token and will have to pay for use. 18 | This class is the result of reverse engineering on the obfuscated and 19 | minified code used by Google to generate such token. 20 | 21 | The token is based on a seed which is updated once per hour and on the 22 | text that will be translated. 23 | Both are combined - by some strange math - in order to generate a final 24 | token (e.g. 744915.856682) which is used by the API to validate the 25 | request. 26 | 27 | This operation will cause an additional request to get an initial 28 | token from translate.google.com. 29 | 30 | Example usage: 31 | >>> from googletrans.gtoken import TokenAcquirer 32 | >>> acquirer = TokenAcquirer() 33 | >>> text = 'test' 34 | >>> tk = acquirer.do(text) 35 | >>> tk 36 | 950629.577246 37 | """ 38 | 39 | RE_TKK = re.compile(r"tkk:\'(.+?)\'", re.DOTALL) 40 | RE_RAWTKK = re.compile(r"tkk:\'(.+?)\'", re.DOTALL) 41 | 42 | def __init__( 43 | self, 44 | client: httpx.AsyncClient, 45 | tkk: str = "0", 46 | host: str = "translate.google.com", 47 | ) -> None: 48 | self.client = client 49 | self.tkk = tkk 50 | self.host = host if "http" in host else "https://" + host 51 | 52 | async def _update(self) -> None: 53 | """update tkk""" 54 | # we don't need to update the base TKK value when it is still valid 55 | now = math.floor(int(time.time() * 1000) / 3600000.0) 56 | if self.tkk and int(self.tkk.split(".")[0]) == now: 57 | return 58 | 59 | r = await self.client.get(self.host) 60 | 61 | raw_tkk = self.RE_TKK.search(r.text) 62 | if raw_tkk: 63 | self.tkk = raw_tkk.group(1) 64 | return 65 | 66 | code = self.RE_TKK.search(r.text) 67 | 68 | if code is not None: 69 | # this will be the same as python code after stripping out a reserved word 'var' 70 | code = code.group(1).replace("var ", "") 71 | # unescape special ascii characters such like a \x3d(=) 72 | code = code.encode().decode("unicode-escape") 73 | 74 | if code: 75 | tree = ast.parse(code) 76 | visit_return = False 77 | operator = "+" 78 | n: int = 0 79 | keys: Dict[str, int] = dict(a=0, b=0) 80 | for node in ast.walk(tree): 81 | if isinstance(node, ast.Assign): 82 | name = None 83 | if isinstance(node.targets[0], ast.Name): 84 | name = node.targets[0].id 85 | if name in keys: 86 | if isinstance(node.value, ast.Constant): 87 | keys[name] = int(node.value.value) 88 | # the value can sometimes be negative 89 | elif isinstance(node.value, ast.UnaryOp) and isinstance( 90 | node.value.op, ast.USub 91 | ): # pragma: nocover 92 | if isinstance(node.value.operand, ast.Constant): 93 | keys[name] = -int(node.value.operand.value) 94 | elif isinstance(node, ast.Return): 95 | # parameters should be set after this point 96 | visit_return = True 97 | elif visit_return and isinstance(node, ast.Constant): 98 | n = int(node.value) 99 | elif visit_return and isinstance(n, int) and n > 0: 100 | # the default operator is '+' but implement some more for 101 | # all possible scenarios 102 | if isinstance(node, ast.Add): # pragma: nocover 103 | pass 104 | elif isinstance(node, ast.Sub): # pragma: nocover 105 | operator = "-" 106 | elif isinstance(node, ast.Mult): # pragma: nocover 107 | operator = "*" 108 | elif isinstance(node, ast.Pow): # pragma: nocover 109 | operator = "**" 110 | elif isinstance(node, ast.BitXor): # pragma: nocover 111 | operator = "^" 112 | # a safety way to avoid Exceptions 113 | clause = compile( 114 | "{1}{0}{2}".format(operator, keys["a"], keys["b"]), "", "eval" 115 | ) 116 | value = eval(clause, dict(__builtin__={})) 117 | result = "{}.{}".format(n, value) 118 | 119 | self.tkk = result 120 | 121 | def _lazy(self, value: Any) -> Callable[[], Any]: 122 | """like lazy evaluation, this method returns a lambda function that 123 | returns value given. 124 | We won't be needing this because this seems to have been built for 125 | code obfuscation. 126 | 127 | the original code of this method is as follows: 128 | 129 | ... code-block: javascript 130 | 131 | var ek = function(a) { 132 | return function() { 133 | return a; 134 | }; 135 | } 136 | """ 137 | return lambda: value 138 | 139 | def _xr(self, a: int, b: str) -> int: 140 | size_b = len(b) 141 | c = 0 142 | while c < size_b - 2: 143 | d = b[c + 2] 144 | d = ord(d[0]) - 87 if "a" <= d else int(d) 145 | d = rshift(a, d) if "+" == b[c + 1] else a << d 146 | a = a + d & 4294967295 if "+" == b[c] else a ^ d 147 | 148 | c += 3 149 | return a 150 | 151 | def acquire(self, text: str) -> str: 152 | a: List[int] = [] 153 | # Convert text to ints 154 | for i in text: 155 | val = ord(i) 156 | if val < 0x10000: 157 | a += [val] 158 | else: 159 | # Python doesn't natively use Unicode surrogates, so account for those 160 | a += [ 161 | math.floor((val - 0x10000) / 0x400 + 0xD800), 162 | math.floor((val - 0x10000) % 0x400 + 0xDC00), 163 | ] 164 | 165 | b = self.tkk if self.tkk != "0" else "" 166 | d = b.split(".") 167 | b_val = int(d[0]) if len(d) > 1 else 0 168 | 169 | # assume e means char code array 170 | e: List[int] = [] 171 | g = 0 172 | size = len(a) 173 | while g < size: 174 | l = a[g] # noqa: E741 175 | # just append if l is less than 128(ascii: DEL) 176 | if l < 128: 177 | e.append(l) 178 | # append calculated value if l is less than 2048 179 | else: 180 | if l < 2048: 181 | e.append(l >> 6 | 192) 182 | else: 183 | # append calculated value if l matches special condition 184 | if ( 185 | (l & 64512) == 55296 186 | and g + 1 < size 187 | and a[g + 1] & 64512 == 56320 188 | ): 189 | g += 1 190 | l = ( # noqa: E741 191 | 65536 + ((l & 1023) << 10) + (a[g] & 1023) 192 | ) # This bracket is important 193 | e.append(l >> 18 | 240) 194 | e.append(l >> 12 & 63 | 128) 195 | else: 196 | e.append(l >> 12 | 224) 197 | e.append(l >> 6 & 63 | 128) 198 | e.append(l & 63 | 128) 199 | g += 1 200 | a_val = b_val 201 | for value in e: 202 | a_val += value 203 | a_val = self._xr(a_val, "+-a^+6") 204 | a_val = self._xr(a_val, "+-3^+b+-f") 205 | a_val ^= int(d[1]) if len(d) > 1 else 0 206 | if a_val < 0: # pragma: nocover 207 | a_val = (a_val & 2147483647) + 2147483648 208 | a_val %= 1000000 # int(1E6) 209 | 210 | return "{}.{}".format(a_val, a_val ^ b_val) 211 | 212 | async def do(self, text: str) -> str: 213 | await self._update() 214 | tk = self.acquire(text) 215 | return tk 216 | -------------------------------------------------------------------------------- /googletrans/models.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from httpx import Response 4 | 5 | 6 | class Base: 7 | def __init__(self, response: Optional[Response] = None): 8 | self._response = response 9 | 10 | 11 | class Translated(Base): 12 | """Translate result object 13 | 14 | :param src: source language (default: auto) 15 | :param dest: destination language (default: en) 16 | :param origin: original text 17 | :param text: translated text 18 | :param pronunciation: pronunciation 19 | """ 20 | 21 | def __init__( 22 | self, 23 | src: str, 24 | dest: str, 25 | origin: str, 26 | text: str, 27 | pronunciation: str, 28 | extra_data: Optional[dict] = None, 29 | **kwargs, 30 | ): 31 | super().__init__(**kwargs) 32 | self.src = src 33 | self.dest = dest 34 | self.origin = origin 35 | self.text = text 36 | self.pronunciation = pronunciation 37 | self.extra_data = extra_data 38 | 39 | def __str__(self): # pragma: nocover 40 | return self.__unicode__() 41 | 42 | def __unicode__(self): # pragma: nocover 43 | return ( 44 | f"Translated(src={self.src}, dest={self.dest}, text={self.text}, " 45 | f"pronunciation={self.pronunciation}, " 46 | f'extra_data="{repr(self.extra_data)[:10]}...")' 47 | ) 48 | 49 | 50 | class Detected(Base): 51 | """Language detection result object 52 | 53 | :param lang: detected language 54 | :param confidence: the confidence of detection result (0.00 to 1.00) 55 | """ 56 | 57 | def __init__(self, lang: str, confidence: float, **kwargs): 58 | super().__init__(**kwargs) 59 | self.lang = lang 60 | self.confidence = confidence 61 | 62 | def __str__(self): # pragma: nocover 63 | return self.__unicode__() 64 | 65 | def __unicode__(self): # pragma: nocover 66 | return f"Detected(lang={self.lang}, confidence={self.confidence})" 67 | -------------------------------------------------------------------------------- /googletrans/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Predefined URLs used to make google translate requests. 4 | """ 5 | 6 | BASE = "https://translate.google.com" 7 | TRANSLATE = "https://{host}/translate_a/single" 8 | -------------------------------------------------------------------------------- /googletrans/utils.py: -------------------------------------------------------------------------------- 1 | """A conversion module for googletrans""" 2 | 3 | import json 4 | import re 5 | from typing import Any, Dict, Iterator, List, Optional, Tuple 6 | 7 | 8 | def build_params( 9 | client: str, 10 | query: str, 11 | src: str, 12 | dest: str, 13 | token: str, 14 | override: Optional[Dict[str, Any]] = None, 15 | ) -> Dict[str, Any]: 16 | params: Dict[str, Any] = { 17 | "client": client, 18 | "sl": src, 19 | "tl": dest, 20 | "hl": dest, 21 | "dt": ["at", "bd", "ex", "ld", "md", "qca", "rw", "rm", "ss", "t"], 22 | "ie": "UTF-8", 23 | "oe": "UTF-8", 24 | "otf": 1, 25 | "ssel": 0, 26 | "tsel": 0, 27 | "tk": token, 28 | "q": query, 29 | } 30 | 31 | if override is not None: 32 | for key, value in get_items(override): 33 | params[key] = value 34 | 35 | return params 36 | 37 | 38 | def legacy_format_json(original: str) -> Dict[str, Any]: 39 | # save state 40 | states: List[Tuple[int, str]] = [] 41 | text: str = original 42 | 43 | # save position for double-quoted texts 44 | for i, pos in enumerate(re.finditer('"', text)): 45 | # pos.start() is a double-quote 46 | p: int = pos.start() + 1 47 | if i % 2 == 0: 48 | nxt: int = text.find('"', p) 49 | states.append((p, text[p:nxt])) 50 | 51 | # replace all wiered characters in text 52 | while text.find(",,") > -1: 53 | text = text.replace(",,", ",null,") 54 | while text.find("[,") > -1: 55 | text = text.replace("[,", "[null,") 56 | 57 | # recover state 58 | for i, pos in enumerate(re.finditer('"', text)): 59 | p: int = pos.start() + 1 60 | if i % 2 == 0: 61 | j: int = int(i / 2) 62 | nxt: int = text.find('"', p) 63 | # replacing a portion of a string 64 | # use slicing to extract those parts of the original string to be kept 65 | text = text[:p] + states[j][1] + text[nxt:] 66 | 67 | converted: Dict[str, Any] = json.loads(text) 68 | return converted 69 | 70 | 71 | def get_items(dict_object: Dict[str, Any]) -> Iterator[Tuple[Any, Any]]: 72 | for key in dict_object: 73 | yield key, dict_object[key] 74 | 75 | 76 | def format_json(original: str) -> Dict[str, Any]: 77 | try: 78 | converted: Dict[str, Any] = json.loads(original) 79 | except ValueError: 80 | converted = legacy_format_json(original) 81 | 82 | return converted 83 | 84 | 85 | def rshift(val: int, n: int) -> int: 86 | """python port for '>>>'(right shift with padding)""" 87 | return (val % 0x100000000) >> n 88 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "googletrans" 3 | version = "4.0.2" 4 | description = "An unofficial Google Translate API for Python" 5 | readme = "README.rst" 6 | requires-python = ">=3.8" 7 | dependencies = ["httpx[http2]>=0.27.2"] 8 | classifiers = [ 9 | "Development Status :: 5 - Production/Stable", 10 | "Intended Audience :: Education", 11 | "Intended Audience :: End Users/Desktop", 12 | "License :: OSI Approved :: MIT License", 13 | "Operating System :: POSIX", 14 | "Operating System :: Microsoft :: Windows", 15 | "Operating System :: MacOS :: MacOS X", 16 | "Topic :: Education", 17 | "Programming Language :: Python", 18 | "Programming Language :: Python :: 3.8", 19 | "Programming Language :: Python :: 3.9", 20 | "Programming Language :: Python :: 3.10", 21 | "Programming Language :: Python :: 3.11", 22 | "Programming Language :: Python :: 3.12", 23 | ] 24 | 25 | [project.optional-dependencies] 26 | dev = ["pytest", "pytest-asyncio", "pytest-cov", "ruff>=0.7"] 27 | 28 | [tool.setuptools] 29 | license-files = ["LICENSE"] 30 | 31 | [tool.uv] 32 | dev-dependencies = ["pytest", "pytest-asyncio", "pytest-cov", "ruff>=0.7"] 33 | 34 | [project.scripts] 35 | translate = "googletrans:translate" 36 | 37 | [project.urls] 38 | homepage = "https://github.com/ssut/py-googletrans" 39 | 40 | [[project.authors]] 41 | name = "Suhun Han" 42 | email = "suhunhankr@gmail.com" 43 | 44 | [build-system] 45 | requires = ["hatchling"] 46 | build-backend = "hatchling.build" 47 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = -v --asyncio-mode=auto 3 | omit = 4 | tests/* 5 | asyncio_default_fixture_loop_scope = function 6 | 7 | [run] 8 | include = googletrans/* 9 | 10 | [report] 11 | exclude_lines = 12 | pragma: no cover 13 | def __repr__ 14 | if self.debug: 15 | if settings.DEBUG 16 | raise AssertionError 17 | raise NotImplementedError 18 | if 0: 19 | if __name__ == .__main__.: 20 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by uv via the following command: 2 | # uv pip compile pyproject.toml -o requirements.txt 3 | anyio==4.6.2.post1 4 | # via httpx 5 | certifi==2024.8.30 6 | # via 7 | # httpcore 8 | # httpx 9 | h11==0.16.0 10 | # via httpcore 11 | h2==4.1.0 12 | # via httpx 13 | hpack==4.0.0 14 | # via h2 15 | httpcore==1.0.7 16 | # via httpx 17 | httpx==0.27.2 18 | # via py-googletrans (pyproject.toml) 19 | hyperframe==6.0.1 20 | # via h2 21 | idna==3.10 22 | # via 23 | # anyio 24 | # httpx 25 | sniffio==1.3.1 26 | # via 27 | # anyio 28 | # httpx 29 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | coveralls==1.1 2 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssut/py-googletrans/db0567f89d3201b787074cc1c53418763d5e6bcc/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import httpx 2 | import pytest 3 | 4 | from googletrans import Translator, gtoken 5 | 6 | 7 | @pytest.fixture(scope="function") 8 | async def translator(): 9 | async with Translator() as t: 10 | yield t 11 | 12 | 13 | @pytest.fixture(scope="function") 14 | async def acquirer(): 15 | async with httpx.AsyncClient(http2=True) as client: 16 | yield gtoken.TokenAcquirer(client=client) 17 | -------------------------------------------------------------------------------- /tests/test_client.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import patch 2 | 3 | import pytest 4 | from httpcore import TimeoutException 5 | from httpcore._exceptions import ConnectError 6 | from httpx import Client, ConnectTimeout, Timeout 7 | from pytest import raises 8 | 9 | from googletrans import Translator 10 | 11 | 12 | @pytest.mark.asyncio 13 | async def test_bind_multiple_service_urls(): 14 | service_urls = [ 15 | "translate.google.com", 16 | "translate.google.co.kr", 17 | ] 18 | 19 | translator = Translator(service_urls=service_urls) 20 | assert translator.service_urls == service_urls 21 | 22 | assert await translator.translate("test", dest="ko") 23 | assert await translator.detect("Hello") 24 | 25 | 26 | @pytest.mark.asyncio 27 | async def test_api_service_urls(): 28 | service_urls = ["translate.googleapis.com"] 29 | 30 | translator = Translator(service_urls=service_urls) 31 | assert translator.service_urls == service_urls 32 | 33 | assert await translator.translate("test", dest="ko") 34 | assert await translator.detect("Hello") 35 | 36 | 37 | @pytest.mark.asyncio 38 | async def test_source_language(translator: Translator): 39 | result = await translator.translate("안녕하세요.") 40 | assert result.src == "ko" 41 | 42 | 43 | @pytest.mark.asyncio 44 | async def test_pronunciation(translator: Translator): 45 | result = await translator.translate("안녕하세요.", dest="ja") 46 | assert result.pronunciation == "Kon'nichiwa." 47 | 48 | 49 | @pytest.mark.asyncio 50 | async def test_pronunciation_issue_175(translator: Translator): 51 | result = await translator.translate("Hello", src="en", dest="ru") 52 | assert result.pronunciation is not None 53 | 54 | 55 | @pytest.mark.asyncio 56 | async def test_latin_to_english(translator: Translator): 57 | result = await translator.translate("veritas lux mea", src="la", dest="en") 58 | assert result.text == "truth is my light" 59 | 60 | 61 | @pytest.mark.asyncio 62 | async def test_unicode(translator: Translator): 63 | result = await translator.translate("안녕하세요.", src="ko", dest="ja") 64 | assert result.text == "こんにちは。" 65 | 66 | 67 | @pytest.mark.asyncio 68 | async def test_emoji(translator: Translator): 69 | result = await translator.translate("😀") 70 | assert result.text == "😀" 71 | 72 | 73 | @pytest.mark.asyncio 74 | async def test_language_name(translator: Translator): 75 | result = await translator.translate("Hello", src="ENGLISH", dest="iRiSh") 76 | assert result.text == "Dia duit" 77 | 78 | 79 | @pytest.mark.asyncio 80 | async def test_language_name_with_space(translator: Translator): 81 | result = await translator.translate("Hello", src="en", dest="chinese (simplified)") 82 | assert result.dest == "zh-cn" 83 | 84 | 85 | @pytest.mark.asyncio 86 | async def test_language_rfc1766(translator: Translator): 87 | result = await translator.translate("luna", src="it_ch@euro", dest="en") 88 | assert result.text == "moon" 89 | 90 | 91 | @pytest.mark.asyncio 92 | async def test_special_chars(translator: Translator): 93 | text = "©×《》" 94 | result = await translator.translate(text, src="en", dest="en") 95 | assert result.text == text 96 | 97 | 98 | @pytest.mark.asyncio 99 | async def test_translate_list(translator: Translator): 100 | args = (["test", "exam", "exam paper"], "ko", "en") 101 | translations = await translator.translate(*args) 102 | assert translations[0].text == "시험" 103 | assert translations[1].text == "시험" 104 | assert translations[2].text == "시험지" 105 | 106 | 107 | @pytest.mark.asyncio 108 | async def test_detect_language(translator: Translator): 109 | ko = await translator.detect("한국어") 110 | en = await translator.detect("English") 111 | rubg = await translator.detect("летóво") 112 | russ = await translator.detect("привет") 113 | 114 | assert ko.lang == "ko" 115 | assert en.lang == "en" 116 | assert rubg.lang == "bg" 117 | assert russ.lang == "ru" 118 | 119 | 120 | @pytest.mark.asyncio 121 | async def test_detect_list(translator: Translator): 122 | items = ["한국어", " English", "летóво", "привет"] 123 | result = await translator.detect(items) 124 | 125 | assert result[0].lang == "ko" 126 | assert result[1].lang == "en" 127 | assert result[2].lang == "bg" 128 | assert result[3].lang == "ru" 129 | 130 | 131 | @pytest.mark.asyncio 132 | async def test_src_in_special_cases(translator: Translator): 133 | args = ("tere", "en", "ee") 134 | result = await translator.translate(*args) 135 | assert result.text in ("hello", "hi,") 136 | 137 | 138 | @pytest.mark.asyncio 139 | async def test_src_not_in_supported_languages(translator: Translator): 140 | args = ("Hello", "en", "zzz") 141 | with raises(ValueError): 142 | await translator.translate(*args) 143 | 144 | 145 | @pytest.mark.asyncio 146 | async def test_dest_in_special_cases(translator: Translator): 147 | args = ("hello", "ee", "en") 148 | result = await translator.translate(*args) 149 | assert result.text == "tere" 150 | 151 | 152 | @pytest.mark.asyncio 153 | async def test_dest_not_in_supported_languages(translator: Translator): 154 | args = ("Hello", "zzz", "en") 155 | with raises(ValueError): 156 | await translator.translate(*args) 157 | 158 | 159 | @pytest.mark.asyncio 160 | async def test_timeout(): 161 | # httpx will raise ConnectError in some conditions 162 | with raises((TimeoutException, ConnectError, ConnectTimeout)): 163 | translator = Translator(timeout=Timeout(0.0001)) 164 | await translator.translate("안녕하세요.") 165 | 166 | 167 | class MockResponse: 168 | def __init__(self, status_code): 169 | self.status_code = status_code 170 | self.text = "tkk:'translation'" 171 | 172 | 173 | @pytest.mark.asyncio 174 | @patch.object(Client, "get", return_value=MockResponse("403")) 175 | async def test_403_error(session_mock): 176 | translator = Translator() 177 | assert await translator.translate("test", dest="ko") 178 | -------------------------------------------------------------------------------- /tests/test_gtoken.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Callable 2 | 3 | import pytest 4 | 5 | from googletrans import gtoken 6 | 7 | 8 | @pytest.mark.asyncio 9 | async def test_acquire_token(acquirer: gtoken.TokenAcquirer) -> None: 10 | text: str = "test" 11 | 12 | result: str = await acquirer.do(text) 13 | 14 | assert result 15 | 16 | 17 | @pytest.mark.asyncio 18 | async def test_acquire_token_ascii_less_than_2048( 19 | acquirer: gtoken.TokenAcquirer, 20 | ) -> None: 21 | text: str = "Ѐ" 22 | 23 | result: str = await acquirer.do(text) 24 | 25 | assert result 26 | 27 | 28 | @pytest.mark.asyncio 29 | async def test_acquire_token_ascii_matches_special_condition( 30 | acquirer: gtoken.TokenAcquirer, 31 | ) -> None: 32 | def unichar(i: int) -> str: 33 | return chr(i) 34 | 35 | text: str = unichar(55296) + unichar(56320) 36 | 37 | result: str = await acquirer.do(text) 38 | 39 | assert result 40 | 41 | 42 | @pytest.mark.asyncio 43 | async def test_acquire_token_ascii_else(acquirer: gtoken.TokenAcquirer) -> None: 44 | text: str = "가" 45 | 46 | result: str = await acquirer.do(text) 47 | 48 | assert result 49 | 50 | 51 | @pytest.mark.asyncio 52 | async def test_reuse_valid_token(acquirer: gtoken.TokenAcquirer) -> None: 53 | text: str = "test" 54 | 55 | first: str = await acquirer.do(text) 56 | second: str = await acquirer.do(text) 57 | 58 | assert first == second 59 | 60 | 61 | def test_map_lazy_return(acquirer: gtoken.TokenAcquirer) -> None: 62 | value: bool = True 63 | 64 | func: Callable[[], Any] = acquirer._lazy(value) 65 | 66 | assert callable(func) 67 | assert func() == value 68 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | from googletrans import utils 2 | from pytest import raises 3 | 4 | 5 | def test_format_json(): 6 | text = '[,,"en",,,,0.96954316,,[["en"],,[0.96954316]]]' 7 | 8 | result = utils.format_json(text) 9 | 10 | assert result == [ 11 | None, 12 | None, 13 | "en", 14 | None, 15 | None, 16 | None, 17 | 0.96954316, 18 | None, 19 | [["en"], None, [0.96954316]], 20 | ] 21 | 22 | 23 | def test_format_malformed_json(): 24 | text = '[,,"en",,,,0.96954316,,[["en"],,0.96954316]]]' 25 | 26 | with raises(ValueError): 27 | utils.format_json(text) 28 | 29 | 30 | def test_rshift(): 31 | value, n = 1000, 3 32 | 33 | result = utils.rshift(value, n) 34 | 35 | assert result == 125 36 | 37 | 38 | def test_build_params_with_override(): 39 | params = utils.build_params( 40 | client="", 41 | query="", 42 | src="", 43 | dest="", 44 | token="", 45 | override={ 46 | "otf": "3", 47 | }, 48 | ) 49 | 50 | assert params["otf"] == "3" 51 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py36,py37,py38,pypy3,py39,py311,py312 3 | 4 | [gh-actions] 5 | python = 6 | 3.7: py37 7 | 3.8: py38 8 | 3.9: py39 9 | 3.10: py310 10 | 3.11: py311 11 | 3.12: py312 12 | 13 | [testenv] 14 | deps= 15 | pytest 16 | pytest-cov 17 | mock 18 | commands= 19 | py.test --cov-report= --cov={envsitepackagesdir}/googletrans {posargs:} 20 | 21 | [pytest] 22 | addopts = -v 23 | testpaths = googletrans/ tests/ 24 | 25 | [flake8] 26 | exclude = .tox 27 | -------------------------------------------------------------------------------- /translate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argparse 3 | 4 | from googletrans import Translator 5 | 6 | 7 | def main(): 8 | parser = argparse.ArgumentParser( 9 | description="Python Google Translator as a command-line tool" 10 | ) 11 | parser.add_argument("text", help="The text you want to translate.") 12 | parser.add_argument( 13 | "-d", 14 | "--dest", 15 | default="en", 16 | help="The destination language you want to translate. (Default: en)", 17 | ) 18 | parser.add_argument( 19 | "-s", 20 | "--src", 21 | default="auto", 22 | help="The source language you want to translate. (Default: auto)", 23 | ) 24 | parser.add_argument("-c", "--detect", action="store_true", default=False, help="") 25 | args = parser.parse_args() 26 | translator = Translator() 27 | 28 | if args.detect: 29 | result = translator.detect(args.text) 30 | result = f""" 31 | [{result.lang}, {result.confidence}] {args.text} 32 | """.strip() 33 | print(result) 34 | return 35 | 36 | result = translator.translate(args.text, dest=args.dest, src=args.src) 37 | result = f""" 38 | [{result.src}] {result.origin} 39 | -> 40 | [{result.dest}] {result.text} 41 | [pron.] {result.pronunciation} 42 | """.strip() 43 | print(result) 44 | 45 | 46 | if __name__ == "__main__": 47 | main() 48 | --------------------------------------------------------------------------------