Skip to content

Commit a709254

Browse files
committed
feat/fix: create l10n, fix i18n
1 parent f6f5d9d commit a709254

File tree

16 files changed

+458
-214
lines changed

16 files changed

+458
-214
lines changed

Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = "pyEchoNext"
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = "0.5.4"
51+
PROJECT_NUMBER = "0.5.5"
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewer a

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Welcome to **EchoNext**, where innovation meets simplicity! Are you tired of the
4141

4242
**Imagine** a lightweight framework that empowers you to create modern web applications with lightning speed and flexibility. With EchoNext, you're not just coding; you're building a masterpiece!
4343

44-
> Last stable version: 0.5.4 alpha
44+
> Last stable version: 0.5.5 alpha
4545
4646
## 🤔 Why Choose SqlSymphony?
4747

@@ -498,7 +498,7 @@ Extended documentation and framework specifications are available at the followi
498498
3. [Creating a web application](./docs/en/webapp_creation.md)
499499
4. [Creating routes (routes&views)](./docs/en/routes_and_views.md)
500500
5. [Request/Response](./docs/en/requests_responses.md)
501-
6. [Localization i18n](./docs/en/i18n_locales.md)
501+
6. [Localization i18n/l10n](./docs/en/i18n_locales.md)
502502

503503
### Russian / Русский
504504

@@ -507,7 +507,7 @@ Extended documentation and framework specifications are available at the followi
507507
3. [Создание веб-приложения](./docs/ru/webapp_creation.md)
508508
4. [Создание маршрутов (routes&views)](./docs/ru/routes_and_views.md)
509509
5. [Request/Response](./docs/ru/requests_responses.md)
510-
6. [Локализация i18n](./docs/ru/i18n_locales.md)
510+
6. [Локализация i18n/l10n](./docs/ru/i18n_locales.md)
511511

512512
## License
513513
Distributed under the GNU LGPL 2.1 License. See [LICENSE](https://github.com/alexeev-prog/pyEchoNext/blob/main/LICENSE) for more information.

SECURITY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ currently being supported with security updates.
77

88
| Version | Supported |
99
| ------- | ------------------ |
10+
| 0.5.5 | :white_check_mark: |
1011
| 0.5.4 | :white_check_mark: |
1112
| 0.5.3 | :white_check_mark: |
1213
| 0.4.3 | :white_check_mark: |

docs/en/i18n_locales.md

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +0,0 @@
1-
# pyEchoNext / i18n - localization
2-
3-
---
4-
5-
pyEchoNext since version 0.5.3 supports i18n (so far in its basic form).
6-
7-
i18n is an abbreviation for internationalization process.
8-
9-
Internationalization is the process of developing an application in which its code is independent of any linguistic and cultural characteristics of the region or country. As a result, the application becomes flexible and can easily adapt to different language and cultural settings.
10-
11-
Internationalization implementation usually begins in the early stages of a project to prepare the product for future localization. During this process, they determine what will change for future locales (for example, text, images) and export this data to external files.
12-
13-
The 18 in i18n stands for the number of letters between the first letter i and the last letter n in the word "internationalization".
14-
15-
In pyEchoNext this is implemented like this: a Response is created, if you need to use i18n for localization, use the use_i18n flag:
16-
17-
```python
18-
from pyechonext.response import Request, Response
19-
20-
# create a request...
21-
# request = ...
22-
23-
response = Response(request, body='title', use_i18n=True)
24-
```
25-
26-
This will signal to the application that i18n should be used in this Response. And the application will translate your phrase.
27-
28-
## Creating localizations
29-
You pass the required Settings parameter to the application. It has two fields related to localization:
30-
31-
+ `LOCALE: str = "DEFAULT"`
32-
+ `LOCALE_DIR: str = None`
33-
34-
By default they create the default locale. It looks like this:
35-
36-
```python
37-
DEFAULT_LOCALE = {
38-
"title": "pyEchoNext Example Website",
39-
"description": "This web application is an example of the pyEchonext web framework.",
40-
}
41-
```
42-
43-
That is, if we enter only title or only description in response.body, we will end up with the phrase “pyEchoNext Example Website” or “This web application is an example of the pyEchoNext web framework.”.
44-
45-
But how to create your own locales? It's simple. Create a directory with locale files, we recommend locales, and localization json files in it. Let's say RU_RU.json:
46-
47-
```json
48-
{
49-
"title": "pyEchoNext Web application with locale",
50-
"example one": "example one"
51-
}
52-
```
53-
54-
And already in Settings we specify the following settings:
55-
56-
+ `LOCAL = "RU_RU"`
57-
+ `LOCALE_DIR = "locales"`
58-
59-
Or through the settings loader (in this example, through the python module, you can see [how to use the settings loader](./webapp_creation.md)):
60-
61-
```python
62-
from pyechonext.config import SettingsLoader, SettingsConfigType
63-
64-
config_loader = SettingsLoader(SettingsConfigType.PYMODULE, 'el_config.py')
65-
settings = config_loader.get_settings()
66-
echonext = EchoNext(
67-
__name__,
68-
settings,
69-
middlewares,
70-
urls=url_patterns,
71-
application_type=ApplicationType.HTML,
72-
)
73-
```
74-
75-
el_config.py:
76-
77-
```python
78-
import os
79-
80-
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
81-
TEMPLATES_DIR = 'templates'
82-
SECRET_KEY = 'secret-key'
83-
LOCAL = 'RU_RU'
84-
LOCALE_DIR = 'locales'
85-
```
86-
87-
The LOCALE value must be the same as the file name. If RU_RU, then the file should be RU_RU.json.
88-
89-
And now you can introduce internationalization to your application!
90-
91-
> At the time of version 0.5.3 i18n is under development, many features will be added later. The plans include: dividing the site localization into several files, more convenient handling of i18n and the ability to change localization on the fly. We plan to be inspired by [this documentation](https://developer.mozilla.org/ru/docs/Mozilla/Add-ons/WebExtensions/Internationalization), reworking it for our web framework.
92-
93-
---
94-
95-
[Contents](./index.md)

docs/en/routes_and_views.md

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -162,79 +162,4 @@ url_patterns = [URL(url="/", view=<ВАШ View>)]
162162
Example:
163163

164164
```python
165-
class IndexView(View):
166-
def get(
167-
self, request: Request, response: Response, **kwargs
168-
) -> Union[Response, Any]:
169-
"""
170-
Get
171-
172-
:param request: The request
173-
:type request: Request
174-
:param response: The response
175-
:type response: Response
176-
:param args: The arguments
177-
:type args: list
178-
:param kwargs: The keywords arguments
179-
:type kwargs: dictionary
180-
"""
181-
return "Hello World!"
182-
183-
def post(
184-
self, request: Request, response: Response, **kwargs
185-
) -> Union[Response, Any]:
186-
"""
187-
Post
188-
189-
:param request: The request
190-
:type request: Request
191-
:param response: The response
192-
:type response: Response
193-
:param args: The arguments
194-
:type args: list
195-
:param kwargs: The keywords arguments
196-
:type kwargs: dictionary
197-
"""
198-
return "Message has accepted!"
199-
200-
201-
url_patterns = [URL(url="/", view=IndexView)]
202-
```
203-
204-
## Routes
205-
Routes inspired by flask/fastapi path:
206-
207-
```python
208-
import os
209-
from pyechonext.app import ApplicationType, EchoNext
210-
from pyechonext.config import Settings
211-
from pyechonext.middleware import middlewares
212-
213-
214-
settings = Settings(
215-
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
216-
)
217-
echonext = EchoNext(
218-
__name__, settings, middlewares, application_type=ApplicationType.HTML
219-
)
220-
221-
222-
@echonext.route_page("/")
223-
def home(request, response):
224-
return "Hello from the HOME page"
225-
226-
227-
@echonext.route_page("/book")
228-
class BooksResource(View):
229-
def get(self, request, response, **kwargs):
230-
return f"GET Params: {request.GET}"
231-
232-
def post(self, request, response, **kwargs):
233-
return f"POST Params: {request.POST}"
234-
```
235-
236-
You can also route Views without passing them to parameters, but by creating a class with a page routing decorator.
237-
238-
---
239-
240-
[Contents](./index.md)
165+
class IndexV

docs/en/webframework_design.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# pyEchoNext / web frameworks device
2+
3+
---
4+
5+
The most important parts of web frameworks are:
6+
7+
+ Routing handlers:
8+
- Simple: `/index`
9+
- Parameterized: `/article/{article_id}`
10+
+ Request handlers (views, handlers).
11+
12+
Basic requirement: the web framework must be supported by a fast, lightweight and efficient server (eg gunicorn). Python has a WSGI guide for this.
13+
14+
## Web server design in Python
15+
16+
```
17+
REQUEST
18+
CLIENT <--------------> [HTTP (80) or HTTPS (443)] Server
19+
ANSWER
20+
21+
> Application with logic
22+
> Data conversion for a python application <-- Area of interest for the web framework (ensuring gunicorn works with it)
23+
> Gunicorn
24+
> Converted data
25+
SERVER -> NGINX
26+
> Data routing
27+
```
28+
29+
When developing a web application in python, we encounter the following problems:
30+
31+
+ Many frameworks (ex. django) do not know how to route response requests.
32+
+ Applications are insecure and may be susceptible to DDoS (Distributed Denial of Service) attacks.
33+
+ No load balancing between multiple servers.
34+
+ NGINX solves the problem of load balancing, but it cannot run and communicate with Python applications.
35+
36+
Therefore, there is a need to use a WSGI server (Web Server Gateway Interface) and a proxy server (such as NGINX).
37+
38+
## WSGI
39+
Python currently boasts a wide range of web application frameworks such as Zope, Quixote, Webware, SkunkWeb, PSO and Twisted Web, just to name a few. This wide variety of options can be a challenge for new Python users, as typically their choice of web framework will limit their choice of web servers to use, and vice versa.
40+
41+
In contrast, although Java has as many web application frameworks available, Java's "servlet" API allows applications written with any Java web application framework to run on any web server that supports the servlet API.
42+
43+
The availability and widespread use of such APIs in web servers for Python—whether those servers are written in Python (e.g., Medusa), built-in Python (e.g., mod_python), or call Python through a gateway protocol (e.g., CGI, FastCGI, and etc.) - will separate framework selection from web server selection, allowing users to choose the pair that suits them, while freeing up framework and server developers to focus on their preferred area specializations.
44+
45+
Thus, this PEP offers a simple and universal interface between web servers and web applications or frameworks: the Python Web Server Gateway Interface (WSGI).
46+
47+
But the mere existence of the WSGI specification does nothing to address the current state of Python web application servers and frameworks. Authors and maintainers of servers and frameworks must actually implement WSGI for it to have any effect.
48+
49+
However, since no existing server or framework supports WSGI, an author who implements WSGI support will not receive immediate rewards. Thus, WSGI must be easy to implement so that the author's initial investment in the interface can be fairly low.
50+
51+
Thus, ease of implementation on both the server side and the interface framework side is absolutely critical to the usefulness of a WSGI interface and is therefore a primary criterion for any design decisions.
52+
53+
However, it should be noted that ease of implementation for a framework author is not the same as ease of use for a web application author. WSGI provides a completely "no frills" interface for the framework author, because bells and whistles like response objects and cookie handling would simply prevent existing frameworks from solving these problems. Again, the goal of WSGI is to facilitate simple interoperability between existing servers and applications or frameworks, not to create a new web framework.
54+
55+
It should also be noted that this target does not allow WSGI to require anything that is not already available in deployed versions of Python. Therefore, new standard library modules are not proposed or required by this specification, and nothing in WSGI requires a Python version greater than 2.2.2. (It would be nice, however, for future versions of Python to include support for this interface in the web servers provided by the standard library.)
56+
57+
In addition to being easy to implement for existing and future frameworks and servers, it should also be easy to create request preprocessors, response postprocessors, and other WSGI-based "middleware" components that look like an application to its containing server, while also acting as a server to its contained applications. If middleware can be both simple and reliable, and WSGI is widely available in servers and frameworks, this allows for the possibility of an entirely new type of Python web application framework: one consisting of loosely coupled WSGI middleware components. Indeed, existing framework authors may even choose to refactor their frameworks' existing services so that they are exposed in a way that becomes more like the libraries used with WSGI and less like monolithic frameworks. This would then allow application developers to select "best-of-breed" components for a specific functionality, rather than committing to all the pros and cons of a single framework.
58+
59+
Of course, as of this writing, that day is undoubtedly quite far away. At the same time, this is a sufficient short-term goal for WSGI to enable the use of any framework with any server.
60+
61+
Finally, it should be mentioned that the current version of WSGI does not prescribe any specific mechanism for "deploying" an application for use with a web server or server gateway. Currently, this is necessarily determined by the server or gateway implementation. Once enough servers and frameworks have implemented WSGI to provide hands-on experience with various deployment requirements, it may make sense to create another PEP describing
62+
63+
## Integer pyEchoNext
64+
pyEchoNext is a universal tool with the ability to make a monolithic web application, or vice versa, a modular web application. Django was too big and clumsy for us, flask or fastapi was too small. Therefore, we decided to take some features from django and flask/fastapi, combine them and make it all symbiotic. So that you can make a large monolithic project or a small service. And to turn a small service into a large application or vice versa, a minimum of effort was required.
65+
66+
Our goals were also to make all this as clear as possible, developer-friendly, and add the ability to integrate third-party libraries.
67+
68+
As a result, the main characteristics of the project are as follows:
69+
70+
1. Goal: Create a universal multifaceted web framework in python
71+
2. Tasks:
72+
+ Find the good and bad sides of Flask, FastAPI
73+
+ Find the good and bad sides of Django
74+
+ Compare the capabilities of existing frameworks
75+
+ Selection of the best features
76+
+ Symbiosis of features into one whole
77+
+ Build project code according to SOLID and OOP principles, easily extensible, scalable and complementary.
78+
+ Make the code fast and productive, give freedom to the user and developer
79+
3. Problem: at the moment there are very few universal frameworks that allow you to create both a large monolithic application and a fast small service.
80+
4. Relevance: the web sphere is very popular at the moment, the ability to work with web frameworks, abstractions, and know the structure of sites will help everyone.
81+
82+
---
83+
84+
[Contents](./index.md)

docs/ru/i18n_locales.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# pyEchoNext / i18n - локализация
1+
# pyEchoNext / i18n, l10n - локализация и интернационализация
22

33
---
44

55
pyEchoNext с версии 0.5.3 поддерживает i18n (пока в базовом виде).
66

77
i18n — это сокращённое обозначение процесса интернационализации.
8+
l10n - локализация, то есть процесс учитывания культуры и правила написания дат, денежных сумм, чисел.
89

910
Интернационализация — это процесс разработки приложения, при котором его код независим от любых языковых и культурных особенностей региона или страны. В результате приложение становится гибким и может легко адаптироваться под разные языковые и культурные настройки.
1011

@@ -29,10 +30,16 @@ from pyechonext.response import Request, Response
2930
Также вы можете и не возвращать response:
3031

3132
```python
32-
return echonext.locale_loader.get_string('title')
33+
return echonext.i18n_loader.get_string('title')
3334
```
3435

35-
В echonext есть публичный объект locale_loader, он и является загрузчиком локализации. Метод get_string получает строку из словаря локализации. Как их создавать и читать вы можете увидеть в секции "Создание локализаций" под этой.
36+
И для l10n вы можете возвращать только контент (не Response):
37+
38+
```python
39+
return echonext.l10n_loader.format_currency(1305.50)
40+
```
41+
42+
В echonext есть публичный объект i18n_loader, он и является загрузчиком локализации. Метод get_string получает строку из словаря локализации. Как их создавать и читать вы можете увидеть в секции "Создание локализаций" под этой.
3643

3744
Также вы можете использовать форматирование через Response:
3845

@@ -47,7 +54,7 @@ return Response(request, body="title %{name}", use_i18n=True, name='Localization
4754
И вы можете как раз использовать форматирование напрямую:
4855

4956
```python
50-
return echonext.locale_loader.get_string('title %{name}', name='Localization Site')
57+
return echonext.i18n_loader.get_string('title %{name}', name='Localization Site')
5158
```
5259

5360
## Создание локализаций
@@ -56,7 +63,7 @@ return echonext.locale_loader.get_string('title %{name}', name='Localization Sit
5663
+ `LOCALE: str = "DEFAULT"`
5764
+ `LOCALE_DIR: str = None`
5865

59-
По умолчанию они создают дефолтную локаль. Она выглядит так:
66+
По умолчанию они создают дефолтную локаль. Она выглядит так для i18n:
6067

6168
```python
6269
DEFAULT_LOCALE = {
@@ -65,14 +72,27 @@ DEFAULT_LOCALE = {
6572
}
6673
```
6774

75+
А так для l10n:
76+
6877
То есть, если мы в response.body введем только title или только description, мы получим в итоге фразу "pyEchoNext Example Website" или "This web application is an example of the pyEchonext web framework.".
6978

7079
Но как создать свои локали? Все просто. Создайте директорию с файлами локалей, мы рекомендуем locales, и в ней json-файлы локализации. Допустим RU_RU.json:
7180

7281
```json
7382
{
74-
"title": "pyEchoNext Веб-приложение с локалью",
75-
"example one": "пример один"
83+
"i18n": {
84+
"title": "pyEchoNext Веб-приложение с локалью",
85+
"example one": "пример один"
86+
},
87+
"l10n": {
88+
"date_format": "%Y-%m-%d",
89+
"time_format": "%H:%M",
90+
"date_time_fromat": "%Y-%m-%d %H:%M",
91+
"thousands_separator": ",",
92+
"decimal_separator": ".",
93+
"currency_symbol": "$",
94+
"currency_format": "{symbol}{amount}"
95+
}
7696
}
7797
```
7898

0 commit comments

Comments
 (0)