Skip to content

Commit

Permalink
Init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
z44d committed Oct 4, 2024
1 parent ab91af7 commit 0268ae8
Show file tree
Hide file tree
Showing 11 changed files with 388 additions and 10 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Release

on:
push:
tags: ["*"]

permissions:
contents: write
id-token: write

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v2
with:
python-version: "3.10"

- run: python -m pip install build

- run: python -m build

- uses: pypa/gh-action-pypi-publish@release/v1

- uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
35 changes: 35 additions & 0 deletions .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: ruff

on:
push:
branches: [main]
pull_request:

jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.10
uses: actions/setup-python@v2
with:
python-version: "3.10"
- name: Install ruff
run: |
python -m pip install --upgrade pip
pip install ruff
- run: ruff format --check pylangs

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.10
uses: actions/setup-python@v2
with:
python-version: "3.10"
- name: Install ruff
run: |
python -m pip install --upgrade pip
pip install ruff
- run: ruff check pylangs
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
test.py
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 ZAID

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.
89 changes: 87 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,87 @@
## PyLangs
- `PyLangs` is python library to manage languages in multi-languages projects.
# PyLangs

**PyLangs** is a Python library designed to simplify the management of multiple languages in projects that need to support internationalization. Whether you're building a website, app, or any multilingual system, ``PyLangs`` makes it easy to store and retrieve messages in various languages with organized categories.

---

## Features
- **Easy to Use**: Simple API for adding and retrieving language-specific messages.
- **Category Support**: Organize your messages by categories (e.g., general, support, etc.).
- **Flexible**: Add messages for any language, and easily switch between them.
- **Fallback Support**: Default fallback to a specified language if a message is missing in the current language.
- **Customizable**: Supports adding, retrieving, and printing all messages or language-specific ones.

## Installation
- Install ``PyLangs`` via pip:
```bash
pip install pylangs
```

## Usage
**Initialize the language management system.**
```python
from pylangs import Langs

langs = Langs()
```
### Simple Example
You can easily insert and retrieve messages in multiple languages.
```python
# Insert Arabic and English welcome messages
langs.insert("ar", "WELCOME_MESSAGE", "السلام عليكم ورحمة الله, وبركاته")
langs.insert("ar", "SUPPORT_WELCOME_MESSAGE", "اهلًا بك في الدعم الفني!")
langs.insert("en", "WELCOME_MESSAGE", "Hi, How are you?")
langs.insert("en", "SUPPORT_WELCOME_MESSAGE", "Hi, This is Support, How can I help you?")

# Get messages in various scenarios
print(langs.get("ar", "WELCOME_MESSAGE")) # Should print Arabic welcome message
print(langs.get("ar", "SUPPORT_WELCOME_MESSAGE")) # Should print Arabic support welcome message
print(langs.get("en", "WELCOME_MESSAGE")) # Should print English welcome message
print(langs.get("en", "SUPPORT_WELCOME_MESSAGE")) # Should print English support welcome message
```
### Using Categories
To further organize messages, you can assign them to categories, making it easier to handle messages for different contexts (e.g., general, support, etc.).

```python
# Insert messages with categories
langs.insert("ar", "WELCOME_MESSAGE", "السلام عليكم ورحمة الله, وبركاته", category="GENERAL")
langs.insert("ar", "WELCOME_MESSAGE", "اهلًا بك في الدعم الفني!", category="SUPPORT")
langs.insert("en", "WELCOME_MESSAGE", "Hi, How are you?", category="GENERAL")
langs.insert("en", "WELCOME_MESSAGE", "Hi, Welcome to our support team, How can I help you today?", category="SUPPORT")

# Retrieve categorized messages
print(langs.get("ar", "WELCOME_MESSAGE", category="GENERAL")) # Outputs: "السلام عليكم ورحمة الله, وبركاته"
print(langs.get("ar", "WELCOME_MESSAGE", category="SUPPORT")) # Outputs: "اهلًا بك في الدعم الفني!"
print(langs.get("en", "WELCOME_MESSAGE", category="GENERAL")) # Outputs: "Hi, How are you?"
print(langs.get("en", "WELCOME_MESSAGE", category="SUPPORT")) # Outputs: "Hi, Welcome to our support team, How can I help you today?"
```

### Printing All Messages
To print all messages across all languages:
```python
print(langs)
```
To print messages for a specific language:
```python
print(langs.en) # Prints only English messages
print(langs.ar) # Prints only Arabic messages
```
### Example Output
Here’s an example of what the output might look like:
```json
{
"lang_code": "en",
"categories": {
"GENERAL": {
"WELCOME_MESSAGE": "Hi, How are you?"
},
"SUPPORT": {
"WELCOME_MESSAGE": "Hi, Welcome to our support team, How can I help you today?"
}
}
}
```
---

# LICENSE
- This project is licensed under the **MIT** License. See the ``LICENSE`` file for more information.
3 changes: 0 additions & 3 deletions langs/__init__.py

This file was deleted.

4 changes: 4 additions & 0 deletions pylangs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from ._lang import Lang
from ._langs import Langs

__all__ = ["Lang", "Langs"]
13 changes: 13 additions & 0 deletions pylangs/_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import json


class JsonViewer:
def __str__(self) -> str:
return json.dumps(
self,
ensure_ascii=False,
indent=2,
default=lambda x: (
{k: v for k, v in x.__dict__.items() if (not k.startswith("_")) and v}
),
)
108 changes: 108 additions & 0 deletions pylangs/_lang.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from collections import OrderedDict
from typing import Dict, Optional

from ._json import JsonViewer


class Lang(JsonViewer):
"""
The Lang class is responsible for managing messages for a specific language.
It supports organizing messages by categories and provides methods to insert,
delete, and retrieve messages both within and outside of categories.
"""

def __init__(self, lang_code: str) -> None:
"""
Initializes the Lang class with a language code and empty structures for storing messages.
Attributes:
lang_code (str): The language code representing this Lang object.
categories (Dict[str, Dict[str, str]]): A nested dictionary to store messages organized by category.
messages (OrderedDict): A dictionary to store uncategorized messages.
"""
self.lang_code = lang_code
self.categories: Dict[str, Dict[str, str]] = OrderedDict()
self.messages = OrderedDict()

def insert(self, k: str, v: str, category: Optional[str] = None) -> None:
"""
Inserts a message into the language, either into a specified category or into the general message store.
Args:
k (str): The key or identifier for the message.
v (str): The actual message text.
category (Optional[str]): The category under which the message will be stored.
If None, the message is stored without a category.
"""
if category is not None:
return self.insert_to_category(category=category, k=k, v=v)

return self.messages.update({k: v})

def delete(self, k: str, category: Optional[str] = None) -> None:
"""
Deletes a message from the language, either from a specified category or from the general message store.
Args:
k (str): The key or identifier for the message to delete.
category (Optional[str]): The category from which the message will be deleted.
If None, the message is deleted from the general store.
"""
if category is not None:
return self.delete_from_category(category=category, k=k)

del self.messages[k]

def get(self, k: str, category: Optional[str] = None) -> Optional[str]:
"""
Retrieves a message from the language, either from a specified category or from the general message store.
Args:
k (str): The key or identifier for the message.
category (Optional[str]): The category from which to retrieve the message.
If None, the message is retrieved from the general store.
Returns:
Optional[str]: The message text if found, otherwise None.
"""
if category is not None:
return self.get_from_category(category=category, k=k)

return self.messages.get(k, None)

def get_from_category(self, category: str, k: str) -> Optional[str]:
"""
Retrieves a message from a specified category.
Args:
category (str): The category from which to retrieve the message.
k (str): The key or identifier for the message.
Returns:
Optional[str]: The message text if found, otherwise None.
"""
return self.categories.get(category).get(k)

def insert_to_category(self, category: str, k: str, v: str) -> None:
"""
Inserts a message into a specific category.
Args:
category (str): The category under which to store the message.
k (str): The key or identifier for the message.
v (str): The actual message text.
"""
if category not in self.categories:
self.categories.update({category: {}})

return self.categories[category].update({k: v})

def delete_from_category(self, category: str, k: str) -> None:
"""
Deletes a message from a specific category.
Args:
category (str): The category from which to delete the message.
k (str): The key or identifier for the message.
"""
del self.categories[category][k]
Loading

0 comments on commit 0268ae8

Please sign in to comment.