# PluralSingular

**PluralSingular** is a Python module that provides functionality to pluralize and singularize words in multiple languages. The module follows a simple interface to make it easy to add support for additional languages.

The goal of this module is to remain lightweight while handling the most common words correctly. It does not aim for 100% accuracy, but instead strives to cover the most frequent and practical use cases.

> **Note:** This is an early release of the module. Contributions, corrections, support for other language backends, and any form of feedback are highly welcome.

> **Note:** Most language backends have been generated by ChatGPT and may need corrections.



## 📦 **Installation**
```bash
pip install pluralsingular
```

---

## 🚀 **Usage**
To use **PluralSingular**, you can import the main functions directly from the package:

```python
from pluralsingular import pluralize, singularize

# Pluralize and singularize in English (default language)
print(pluralize("dog"))  # 'dogs'
print(singularize("dogs"))  # 'dog'

# Pluralize and singularize in Spanish
print(pluralize("flor", lang="es"))  # 'flores'
print(singularize("flores", lang="es"))  # 'flor'

# Pluralize and singularize in French
print(pluralize("cheval", lang="fr"))  # 'chevaux'
print(singularize("chevaux", lang="fr"))  # 'cheval'

# Pluralize and singularize in German
print(pluralize("Mann", lang="de"))  # 'Männer'
print(singularize("Männer", lang="de"))  # 'Mann'

# Pluralize and singularize in Russian
print(pluralize("человек", lang="ru"))  # 'люди'
print(singularize("люди", lang="ru"))  # 'человек'
```

---

## 🔧 **Functions**

### `pluralize(word: str, lang: str = 'en') -> str`
Pluralizes a given word based on the specified language.

**Arguments:**
- `word` (str): The word to be pluralized.
- `lang` (str, optional): The language to be used for pluralization (default is 'en').

**Returns:**
- `str`: The pluralized form of the word.

**Example:**
```python
print(pluralize("dog"))  # 'dogs'
print(pluralize("futbol", lang="es"))  # 'futboles'
```

---

### `singularize(word: str, lang: str = 'en') -> str`
Singularizes a given word based on the specified language.

**Arguments:**
- `word` (str): The word to be singularized.
- `lang` (str, optional): The language to be used for singularization (default is 'en').

**Returns:**
- `str`: The singularized form of the word.

**Example:**
```python
print(singularize("dogs"))  # 'dog'
print(singularize("futboles", lang="es"))  # 'futbol'
```

---

## 🌍 **Supported Languages**
The module supports multiple languages, including English, Spanish, French, German, Italian, Portuguese, Galician, Dutch, Russian, Ukrainian, and Greek. Each language has its own backend, and new languages can be added by following the structure in `pluralsingular/lang/`.

---

## 🤔 **How It Works**
The module dynamically loads the appropriate backend for each language when the `pluralize` or `singularize` function is called. The backends are cached to avoid multiple imports. Each backend implements the same interface with two methods:
- **`pluralize(word: str) -> str`**
- **`singularize(word: str) -> str`**

The backends for each language use a combination of **rule-based transformations** and **exception lists** to handle irregular words.

---

## ✨ **Features**
- **Multi-language support**: Handle multiple languages with ease.
- **Custom backends**: Easily extend the package to support other languages.
- **Dynamic imports**: Load only what is needed for each language.
- **Exception handling**: Custom handling for irregular words.

---

## 📚 **Examples**

### **Spanish Examples**
```python
from pluralsingular import pluralize, singularize

print(pluralize("flor", lang="es"))  # 'flores'
print(pluralize("luz", lang="es"))  # 'luces'
print(pluralize("país", lang="es"))  # 'países'
print(pluralize("rey", lang="es"))  # 'reyes'

print(singularize("flores", lang="es"))  # 'flor'
print(singularize("luces", lang="es"))  # 'luz'
print(singularize("países", lang="es"))  # 'país'
print(singularize("reyes", lang="es"))  # 'rey'
```

---

## 🛠️ **Development**
If you'd like to contribute to this project, you can fork the repository and submit a pull request. 

To set up a development environment, run:
```bash
git clone https://github.com/salva/py-pluralsingular.git
cd py-pluralsingular
python -m venv venv
source venv/bin/activate  # On Windows use `venv\Scripts\activate`
pip install -e .
```

To run tests, you can use **pytest**:
```bash
pytest
```

## 🤝 **Contributing**

Corrections to the rules and exceptions are welcome! Contributions,
support for other language backends, and any feedback or suggestions
are highly appreciated. If you find any incorrect behavior or have
suggestions for improvement, please submit an issue or a pull request.


## 🔗 **Links**
- **GitHub**: [https://github.com/salva/py-pluralsingular](https://github.com/salva/py-pluralsingular)


## 📝 **Copyright and License**


This project is licensed under the **MIT License**.

```
Copyright (c) 2024 - Salvador Fandiño Garía (sfandino@yahoo.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```

This software incorpoates code from Pattern library with has the
following copyright and license:

```
Copyright (c) 2010 University of Antwerp, Belgium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in
  the documentation and/or other materials provided with the
  distribution.

* Neither the name of Pattern nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior written
  permission.
```
