Skip to content

Commit 0268ae8

Browse files
committedOct 4, 2024
Init commit
1 parent ab91af7 commit 0268ae8

File tree

11 files changed

+388
-10
lines changed

11 files changed

+388
-10
lines changed
 

‎.github/workflows/release.yml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags: ["*"]
6+
7+
permissions:
8+
contents: write
9+
id-token: write
10+
11+
jobs:
12+
publish:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Python 3.10
18+
uses: actions/setup-python@v2
19+
with:
20+
python-version: "3.10"
21+
22+
- run: python -m pip install build
23+
24+
- run: python -m build
25+
26+
- uses: pypa/gh-action-pypi-publish@release/v1
27+
28+
- uses: softprops/action-gh-release@v1
29+
with:
30+
generate_release_notes: true

‎.github/workflows/ruff.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: ruff
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
format:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Set up Python 3.10
14+
uses: actions/setup-python@v2
15+
with:
16+
python-version: "3.10"
17+
- name: Install ruff
18+
run: |
19+
python -m pip install --upgrade pip
20+
pip install ruff
21+
- run: ruff format --check pylangs
22+
23+
lint:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v2
27+
- name: Set up Python 3.10
28+
uses: actions/setup-python@v2
29+
with:
30+
python-version: "3.10"
31+
- name: Install ruff
32+
run: |
33+
python -m pip install --upgrade pip
34+
pip install ruff
35+
- run: ruff check pylangs

‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__pycache__/
2+
test.py

‎LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 ZAID
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.

‎README.md

+87-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,87 @@
1-
## PyLangs
2-
- `PyLangs` is python library to manage languages in multi-languages projects.
1+
# PyLangs
2+
3+
**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.
4+
5+
---
6+
7+
## Features
8+
- **Easy to Use**: Simple API for adding and retrieving language-specific messages.
9+
- **Category Support**: Organize your messages by categories (e.g., general, support, etc.).
10+
- **Flexible**: Add messages for any language, and easily switch between them.
11+
- **Fallback Support**: Default fallback to a specified language if a message is missing in the current language.
12+
- **Customizable**: Supports adding, retrieving, and printing all messages or language-specific ones.
13+
14+
## Installation
15+
- Install ``PyLangs`` via pip:
16+
```bash
17+
pip install pylangs
18+
```
19+
20+
## Usage
21+
**Initialize the language management system.**
22+
```python
23+
from pylangs import Langs
24+
25+
langs = Langs()
26+
```
27+
### Simple Example
28+
You can easily insert and retrieve messages in multiple languages.
29+
```python
30+
# Insert Arabic and English welcome messages
31+
langs.insert("ar", "WELCOME_MESSAGE", "السلام عليكم ورحمة الله, وبركاته")
32+
langs.insert("ar", "SUPPORT_WELCOME_MESSAGE", "اهلًا بك في الدعم الفني!")
33+
langs.insert("en", "WELCOME_MESSAGE", "Hi, How are you?")
34+
langs.insert("en", "SUPPORT_WELCOME_MESSAGE", "Hi, This is Support, How can I help you?")
35+
36+
# Get messages in various scenarios
37+
print(langs.get("ar", "WELCOME_MESSAGE")) # Should print Arabic welcome message
38+
print(langs.get("ar", "SUPPORT_WELCOME_MESSAGE")) # Should print Arabic support welcome message
39+
print(langs.get("en", "WELCOME_MESSAGE")) # Should print English welcome message
40+
print(langs.get("en", "SUPPORT_WELCOME_MESSAGE")) # Should print English support welcome message
41+
```
42+
### Using Categories
43+
To further organize messages, you can assign them to categories, making it easier to handle messages for different contexts (e.g., general, support, etc.).
44+
45+
```python
46+
# Insert messages with categories
47+
langs.insert("ar", "WELCOME_MESSAGE", "السلام عليكم ورحمة الله, وبركاته", category="GENERAL")
48+
langs.insert("ar", "WELCOME_MESSAGE", "اهلًا بك في الدعم الفني!", category="SUPPORT")
49+
langs.insert("en", "WELCOME_MESSAGE", "Hi, How are you?", category="GENERAL")
50+
langs.insert("en", "WELCOME_MESSAGE", "Hi, Welcome to our support team, How can I help you today?", category="SUPPORT")
51+
52+
# Retrieve categorized messages
53+
print(langs.get("ar", "WELCOME_MESSAGE", category="GENERAL")) # Outputs: "السلام عليكم ورحمة الله, وبركاته"
54+
print(langs.get("ar", "WELCOME_MESSAGE", category="SUPPORT")) # Outputs: "اهلًا بك في الدعم الفني!"
55+
print(langs.get("en", "WELCOME_MESSAGE", category="GENERAL")) # Outputs: "Hi, How are you?"
56+
print(langs.get("en", "WELCOME_MESSAGE", category="SUPPORT")) # Outputs: "Hi, Welcome to our support team, How can I help you today?"
57+
```
58+
59+
### Printing All Messages
60+
To print all messages across all languages:
61+
```python
62+
print(langs)
63+
```
64+
To print messages for a specific language:
65+
```python
66+
print(langs.en) # Prints only English messages
67+
print(langs.ar) # Prints only Arabic messages
68+
```
69+
### Example Output
70+
Here’s an example of what the output might look like:
71+
```json
72+
{
73+
"lang_code": "en",
74+
"categories": {
75+
"GENERAL": {
76+
"WELCOME_MESSAGE": "Hi, How are you?"
77+
},
78+
"SUPPORT": {
79+
"WELCOME_MESSAGE": "Hi, Welcome to our support team, How can I help you today?"
80+
}
81+
}
82+
}
83+
```
84+
---
85+
86+
# LICENSE
87+
- This project is licensed under the **MIT** License. See the ``LICENSE`` file for more information.

‎langs/__init__.py

-3
This file was deleted.

‎pylangs/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from ._lang import Lang
2+
from ._langs import Langs
3+
4+
__all__ = ["Lang", "Langs"]

‎pylangs/_json.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import json
2+
3+
4+
class JsonViewer:
5+
def __str__(self) -> str:
6+
return json.dumps(
7+
self,
8+
ensure_ascii=False,
9+
indent=2,
10+
default=lambda x: (
11+
{k: v for k, v in x.__dict__.items() if (not k.startswith("_")) and v}
12+
),
13+
)

‎pylangs/_lang.py

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
from collections import OrderedDict
2+
from typing import Dict, Optional
3+
4+
from ._json import JsonViewer
5+
6+
7+
class Lang(JsonViewer):
8+
"""
9+
The Lang class is responsible for managing messages for a specific language.
10+
It supports organizing messages by categories and provides methods to insert,
11+
delete, and retrieve messages both within and outside of categories.
12+
"""
13+
14+
def __init__(self, lang_code: str) -> None:
15+
"""
16+
Initializes the Lang class with a language code and empty structures for storing messages.
17+
18+
Attributes:
19+
lang_code (str): The language code representing this Lang object.
20+
categories (Dict[str, Dict[str, str]]): A nested dictionary to store messages organized by category.
21+
messages (OrderedDict): A dictionary to store uncategorized messages.
22+
"""
23+
self.lang_code = lang_code
24+
self.categories: Dict[str, Dict[str, str]] = OrderedDict()
25+
self.messages = OrderedDict()
26+
27+
def insert(self, k: str, v: str, category: Optional[str] = None) -> None:
28+
"""
29+
Inserts a message into the language, either into a specified category or into the general message store.
30+
31+
Args:
32+
k (str): The key or identifier for the message.
33+
v (str): The actual message text.
34+
category (Optional[str]): The category under which the message will be stored.
35+
If None, the message is stored without a category.
36+
"""
37+
if category is not None:
38+
return self.insert_to_category(category=category, k=k, v=v)
39+
40+
return self.messages.update({k: v})
41+
42+
def delete(self, k: str, category: Optional[str] = None) -> None:
43+
"""
44+
Deletes a message from the language, either from a specified category or from the general message store.
45+
46+
Args:
47+
k (str): The key or identifier for the message to delete.
48+
category (Optional[str]): The category from which the message will be deleted.
49+
If None, the message is deleted from the general store.
50+
"""
51+
if category is not None:
52+
return self.delete_from_category(category=category, k=k)
53+
54+
del self.messages[k]
55+
56+
def get(self, k: str, category: Optional[str] = None) -> Optional[str]:
57+
"""
58+
Retrieves a message from the language, either from a specified category or from the general message store.
59+
60+
Args:
61+
k (str): The key or identifier for the message.
62+
category (Optional[str]): The category from which to retrieve the message.
63+
If None, the message is retrieved from the general store.
64+
65+
Returns:
66+
Optional[str]: The message text if found, otherwise None.
67+
"""
68+
if category is not None:
69+
return self.get_from_category(category=category, k=k)
70+
71+
return self.messages.get(k, None)
72+
73+
def get_from_category(self, category: str, k: str) -> Optional[str]:
74+
"""
75+
Retrieves a message from a specified category.
76+
77+
Args:
78+
category (str): The category from which to retrieve the message.
79+
k (str): The key or identifier for the message.
80+
81+
Returns:
82+
Optional[str]: The message text if found, otherwise None.
83+
"""
84+
return self.categories.get(category).get(k)
85+
86+
def insert_to_category(self, category: str, k: str, v: str) -> None:
87+
"""
88+
Inserts a message into a specific category.
89+
90+
Args:
91+
category (str): The category under which to store the message.
92+
k (str): The key or identifier for the message.
93+
v (str): The actual message text.
94+
"""
95+
if category not in self.categories:
96+
self.categories.update({category: {}})
97+
98+
return self.categories[category].update({k: v})
99+
100+
def delete_from_category(self, category: str, k: str) -> None:
101+
"""
102+
Deletes a message from a specific category.
103+
104+
Args:
105+
category (str): The category from which to delete the message.
106+
k (str): The key or identifier for the message.
107+
"""
108+
del self.categories[category][k]

0 commit comments

Comments
 (0)
Failed to load comments.