Skip to content

Commit

Permalink
New release: Code refactoring, performance optimizations and bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-oluwa committed Jun 9, 2024
1 parent 5308ac8 commit a84fc13
Show file tree
Hide file tree
Showing 11 changed files with 355 additions and 1,026 deletions.
695 changes: 21 additions & 674 deletions LICENSE

Large diffs are not rendered by default.

104 changes: 49 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## tranzlate

A wrapper around the translators package by UlionTse that enables multilingual translation of text, files, markup and BeautifulSoup objects.
A wrapper around the [`translators`](https://pypi.org/project/translators/) package, providing a simpler interface for the translation of text, files, markup and BeautifulSoup.

## Installation

Expand All @@ -12,17 +12,19 @@ pip install tranzlate

## Usage

### Create a Translator
> Ensure you have `beautifulsoup4` installed if you want to translate markup or BeautifulSoup. Run `pip install beautifulsoup4` in your terminal.
The `Translator` class is the main interface for the package. It can be used to translate text, files, markup and BeautifulSoup objects. To create an instance of the `Translator` class, simply import the `tranzlate` package and instantiate the `Translator` class:
### Create a translator

The `Translator` class is the main interface for the package. It can be used to translate text, bytes, files, markup and BeautifulSoup. To create an instance of the `Translator` class, simply import the `tranzlate` package and instantiate a `Translator`:

```python
import tranzlate

translator = tranzlate.Translator()
```

### Use a Custom Translation Engine
### Use a custom translation engine

By default, the `Translator` class uses Bing Translator as its translation engine. Based on test results, Bing is the most reliable translation engine. However, you can use any translation engine that is supported by the translators package by passing the name of the engine to the `Translator` class on instantiation:

Expand All @@ -31,7 +33,7 @@ In this example, we will use Google Translate as our translation engine:
```python
import tranzlate

translator = tranzlate.Translator('google')
google = tranzlate.Translator('google')
```

To get a list of all supported translation engines:
Expand All @@ -45,148 +47,140 @@ print(tranzlate.Translator.engines())
# ['bing', 'google', 'yandex', 'baidu', 'sogou', 'tencent', 'deepl', 'alibaba', ...]
```

### Detect Language
### Detect language

```python
import tranzlate

translator = tranzlate.Translator()
text = 'Good Morning!'
detected_lang = translator.detect_language(text)
print(detected_lang)
language = tranzlate.Translator.detect_language(text)
print(language)

# Output: en
```

### Translate Text, Markup and BeautifulSoup Objects
### Translate text, bytes, markup and BeautifulSoup

To translate text, markup or a soup, you can use the `translate` method of the `Translator` class. The `translate` method is a general purpose method that can be used to translate text, markup and BeautifulSoup objects.
Translate text, markup or a soup using the `translate` method of the `Translator` class. The `translate` method is a general purpose method that can be used to translate text, bytes and markup.

#### Translate Text
#### Translate text/bytes

```python
import tranzlate

translator = tranzlate.Translator()

bing = tranzlate.Translator("bing")
text = 'Good Morning!'
translation = translator.translate(text, target_lang='yo')
translation = bing.translate(text, target_lang='yo')
print(translation)

# Output: Eku ojumo!
```

#### Translate Markup
#### Translate markup

```python
import tranzlate

translator = tranzlate.Translator()
bing = tranzlate.Translator("bing")

markup = '<p>Good Morning!</p>'
translated_markup = translator.translate(markup, target_lang='yo', is_markup=True)
translated_markup = bing.translate(markup, target_lang='yo', is_markup=True)
print(translated_markup)

# Output: <p>Eku ojumo!</p>
```

#### Translate BeautifulSoup Objects
#### Translate BeautifulSoup

```python
import tranzlate
from bs4 import BeautifulSoup

translator = tranzlate.Translator()

baidu = tranzlate.Translator("baidu")
markup = '<p>Good Morning!</p>'
soup = BeautifulSoup(markup, 'html.parser')
translated_soup = translator.translate(soup, target_lang='yo')
translated_soup = baidu.translate_soup(soup, target_lang='fr')
```

However, there are specialized methods for translating text, markup and BeautifulSoup objects. These methods are `translate_text`, `translate_markup` and `translate_soup` respectively.

### Translate Files
### Translate files

To translate files, we use the `translate_file` method of the `Translator` class.
To translate files, we use the `translate_file` method.

```python
import tranzlate

translator = tranzlate.Translator()
translated_file = translator.translate_file('path/to/file.txt', src_lang="en", target_lang='yo')
bing = tranzlate.Translator() # Bing is used by default
translated_file = bing.translate_file('path/to/file.txt', src_lang="en", target_lang='yo')
```

It is advisable to specify the source language when performing translations as it helps the translation engine to provide more accurate translations.

### Use a Proxy
### Use a proxy

To use a proxy, simply pass the proxy to the `Translator` class on instantiation:
To use a proxy, simply pass your proxies on translation:

```python
import tranzlate

translator = tranzlate.Translator()
deepl = tranzlate.Translator("deepl")
text = 'Good Morning!'
translation = translator.translate(text, target_lang='yo', proxies={'https': 'https://<proxy>:<port>'})
translation = deepl.translate(text, target_lang='yo', proxies={'https': 'https://<proxy>:<port>'})
print(translation)
```

### Other Methods

#### Get Supported Languages

To get a list of all supported (source) languages by the translator's engine:
### Other methods

```python
import tranzlate

translator = tranzlate.Translator()
print(translator.supported_languages)
google = tranzlate.Translator("google")
bing = tranzlate.Translator("bing")
```

#### Check if a Language is Supported
#### Get supported languages

To check if a (source) language is supported by the translator's engine:
Get a list of all supported (source) languages by the translator's engine:

```python
import tranzlate
print(google.supported_languages)
```

translator = tranzlate.Translator()
is_supported = translator.is_supported_language('yo')
#### Check if a language is supported

Check if a (source) language is supported by the translator's engine:

```python
is_supported = google.supports_language('yo')
print(is_supported)

# Output: True
```

#### Check if a Language Pair is Supported
#### Check if a language pair is supported

To check if a language pair is supported by the translator's engine:
Check if a language pair is supported by the translator's engine:

```python
import tranzlate

translator = tranzlate.Translator()
is_supported = translator.is_supported_pair(src_lang='en', target_lang='yo')
is_supported = bing.supports_pair(src_lang='en', target_lang='yo')
print(is_supported)

# Output: True
```

#### Get a List of Supported Target Languages for a Source Language
#### Get a list of supported target languages for a source language

To get a list of supported target languages for a source language:
Get a list of supported target languages for a source language:

```python
import tranzlate

translator = tranzlate.Translator()
supported_target_languages = translator.get_supported_target_languages('en')
supported_target_languages = bing.get_supported_target_languages('en')
print(supported_target_languages)
```

### Testing

To run the tests, simply run the following command in the root directory of your cloned repository:
To run tests, simply run the following command in the root directory of your cloned repository:

```bash
python -m unittest discover tests "test_*.py"
Expand Down
Binary file added dist/tranzlate-0.0.2-py3-none-any.whl
Binary file not shown.
Binary file added dist/tranzlate-0.0.2.tar.gz
Binary file not shown.
10 changes: 3 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,33 @@ authors = [
maintainers = [
{ name="ti-oluwa", email="tioluwa.dev@gmail.com" },
]
description = "Multilingual translation of text, files, markup and BeautifulSoup objects."
description = "Translate text, files, markup and BeautifulSoup."
keywords = [
"translate",
"translation",
"google translate",
"bing translate",
"yandex translate",
"translate text",
"translate files",
"translate markup",
"translate html",
"translate xml",
"translate BeautifulSoup",
"beautifulsoup4",
"detect language",
]
readme = "README.md"
requires-python = ">=3.7"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
"Natural Language :: English",
"Typing :: Typed",
]
dependencies = [
"translators==5.8.9",
"beautifulsoup4==4.12.2",
"simple_file_handler>=0.0.1",
]

Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
translators==5.8.9
beautifulsoup4==4.12.2
simple_file_handler>=0.0.1
19 changes: 19 additions & 0 deletions tests/fixtures/text.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Translation</title>
</head>
<body>
<p>Once upon a time, in a land far, far away, there was a small village nestled among the rolling hills and verdant valleys. The villagers were known for their hard work, kindness, and the vibrant tapestry of stories that wove through their daily lives. One such story was about a wise old woman named Elara who lived on the edge of the village in a quaint little cottage.</p>
<p>Elara was known throughout the land for her vast knowledge and gentle wisdom. People from neighboring villages would travel great distances to seek her counsel. She had a gift for understanding the language of nature and could often be found tending to her garden, where the flowers bloomed more brightly and the herbs grew more fragrant under her care.</p>
<p>One day, a young girl named Mira, who lived in the village, found herself in need of guidance. She had come to a crossroads in her life and felt lost and uncertain about which path to take. Her parents suggested she visit Elara, and so, with a hopeful heart, Mira set off towards the old woman's cottage.</p>
<p>As Mira approached the cottage, she was greeted by the sight of Elara gently coaxing a song from a flute carved from a piece of willow. The music seemed to weave itself into the very air, carrying with it a sense of peace and clarity. Elara looked up and smiled warmly at Mira, inviting her to sit on a bench beneath the shade of an ancient oak tree.</p>
<p>"Tell me, child, what troubles you?" Elara asked, her voice as soothing as the melody she had just played.</p>
<p>Mira took a deep breath and poured out her heart to Elara, explaining her fears and doubts about the future. Elara listened patiently, her eyes never leaving Mira's face. When Mira had finished, Elara nodded thoughtfully.</p>
<p>"Life is much like a garden," Elara began. "It requires patience, care, and the willingness to embrace both the sunshine and the storms. Each path you consider is a seed, full of potential. It is up to you to nurture it, to provide it with the light of your dreams and the water of your efforts. Some seeds will grow into magnificent trees, others into delicate flowers, and some may not grow at all. But each has its place and purpose."</p>
<p>Mira felt a sense of calm wash over her as she listened to Elara's words. She realized that there was no single right path, but rather, a journey of growth and discovery. With newfound resolve, she thanked Elara and made her way back to the village, ready to plant the seeds of her future with hope and determination.</p>
<p>Years passed, and Mira grew into a strong, confident woman. She often thought of Elara and the wisdom she had shared. The village continued to thrive, each generation carrying forward the stories and lessons of those who came before. And so, the tapestry of life in that small village remained vibrant and ever-changing, a testament to the enduring power of wisdom, kindness, and the human spirit.</p>
</body>
</html>
17 changes: 17 additions & 0 deletions tests/fixtures/text.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Once upon a time, in a land far, far away, there was a small village nestled among the rolling hills and verdant valleys. The villagers were known for their hard work, kindness, and the vibrant tapestry of stories that wove through their daily lives. One such story was about a wise old woman named Elara who lived on the edge of the village in a quaint little cottage.

Elara was known throughout the land for her vast knowledge and gentle wisdom. People from neighboring villages would travel great distances to seek her counsel. She had a gift for understanding the language of nature and could often be found tending to her garden, where the flowers bloomed more brightly and the herbs grew more fragrant under her care.

One day, a young girl named Mira, who lived in the village, found herself in need of guidance. She had come to a crossroads in her life and felt lost and uncertain about which path to take. Her parents suggested she visit Elara, and so, with a hopeful heart, Mira set off towards the old woman's cottage.

As Mira approached the cottage, she was greeted by the sight of Elara gently coaxing a song from a flute carved from a piece of willow. The music seemed to weave itself into the very air, carrying with it a sense of peace and clarity. Elara looked up and smiled warmly at Mira, inviting her to sit on a bench beneath the shade of an ancient oak tree.

"Tell me, child, what troubles you?" Elara asked, her voice as soothing as the melody she had just played.

Mira took a deep breath and poured out her heart to Elara, explaining her fears and doubts about the future. Elara listened patiently, her eyes never leaving Mira's face. When Mira had finished, Elara nodded thoughtfully.

"Life is much like a garden," Elara began. "It requires patience, care, and the willingness to embrace both the sunshine and the storms. Each path you consider is a seed, full of potential. It is up to you to nurture it, to provide it with the light of your dreams and the water of your efforts. Some seeds will grow into magnificent trees, others into delicate flowers, and some may not grow at all. But each has its place and purpose."

Mira felt a sense of calm wash over her as she listened to Elara's words. She realized that there was no single right path, but rather, a journey of growth and discovery. With newfound resolve, she thanked Elara and made her way back to the village, ready to plant the seeds of her future with hope and determination.

Years passed, and Mira grew into a strong, confident woman. She often thought of Elara and the wisdom she had shared. The village continued to thrive, each generation carrying forward the stories and lessons of those who came before. And so, the tapestry of life in that small village remained vibrant and ever-changing, a testament to the enduring power of wisdom, kindness, and the human spirit.
33 changes: 14 additions & 19 deletions tests/test_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from tranzlate.exceptions import TranslationError, UnsupportedLanguageError



class TestTranslator(unittest.TestCase):
"""Test case for the Translator class."""
example_text = "Yoruba is a language spoken in West Africa, most prominently Southwestern Nigeria."
Expand Down Expand Up @@ -43,8 +44,6 @@ def test_detect_language_with_empty_text(self):
def test_translate_on_auto(self):
with self.assertRaises(TypeError):
self.translator.translate(None)
with self.assertRaises(ValueError):
self.translator.translate("")
translation = self.translator.translate(self.example_text, target_lang="yo")
self.assertIsInstance(translation, str)
self.assertNotEqual(translation, self.example_text)
Expand All @@ -68,37 +67,33 @@ def test_translate_with_empty_target_language(self):

def test_translate_with_unsupported_source_language(self):
with self.assertRaises(UnsupportedLanguageError):
self.translator.translate(self.example_text, "en-xy", "yo")
self.translator.translate(self.example_text, "xyz", "yo")

def test_translate_with_unsupported_target_language(self):
with self.assertRaises(UnsupportedLanguageError):
self.translator.translate(self.example_text, "en", "yo-xy")
self.translator.translate(self.example_text, "en", "xyz")

def test_translate_with_the_same_source_and_target_language(self):
with self.assertRaises(TranslationError):
with self.assertRaises(ValueError):
self.translator.translate(self.example_text, "en", "en")

def test_is_supported_language(self):
self.assertTrue(self.translator.is_supported_language("en"))
self.assertFalse(self.translator.is_supported_language("en-xy"))
def test_supports_language(self):
self.assertTrue(self.translator.supports_language("en"))
self.assertFalse(self.translator.supports_language("xyz"))
with self.assertRaises(TypeError):
self.translator.is_supported_language(None)
with self.assertRaises(ValueError):
self.translator.is_supported_language("")
self.translator.supports_language(None)

def test_get_supported_target_languages(self):
self.assertIsInstance(self.translator.get_supported_target_languages("en"), list)
self.assertTrue(len(self.translator.get_supported_target_languages("en")) > 0)
self.assertIsInstance(self.translator.get_supported_target_languages("en-xy"), list)
self.assertTrue(len(self.translator.get_supported_target_languages("en-xy")) == 0)
self.assertIsInstance(self.translator.get_supported_target_languages("xyz"), list)
self.assertTrue(len(self.translator.get_supported_target_languages("xyz")) == 0)
with self.assertRaises(TypeError):
self.translator.get_supported_target_languages(None)
with self.assertRaises(ValueError):
self.translator.get_supported_target_languages("")

def test_is_supported_pair(self):
self.assertFalse(self.translator.is_supported_pair("en", "en"))
self.assertTrue(self.translator.is_supported_pair("en", "yo"))
def test_supports_pair(self):
self.assertFalse(self.translator.supports_pair("en", "en"))
self.assertTrue(self.translator.supports_pair("en", "yo"))

def test_properties(self):
self.assertIsInstance(self.translator.server, TranslatorsServer)
Expand Down Expand Up @@ -136,4 +131,4 @@ def test_translate_soup(self):
if "__name__" == "__main__":
unittest.main()

# RUN WITH 'python -m unittest discover tests "test_*.py"' from project's root directory
# Run with 'python -m unittest discover tests "test_*.py"' from project's root directory
Loading

0 comments on commit a84fc13

Please sign in to comment.