-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
388 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
__pycache__/ | ||
test.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} | ||
), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] |
Oops, something went wrong.