Metadata-Version: 2.1
Name: sl10n
Version: 0.3.0.0
Summary: Static localization system that reduces the headache of working with localization
Author: SyberiaK
License: MIT License
        
        Copyright (c) 2023 SyberiaK
        
        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.
Project-URL: Homepage, https://github.com/SyberiaK/sl10n
Project-URL: Documentation, https://syberiak.github.io/sl10n
Project-URL: Issues, https://github.com/SyberiaK/sl10n/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Internationalization
Classifier: Topic :: Software Development :: Localization
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: docs
Requires-Dist: mkdocs>=1.5.3; extra == "docs"
Requires-Dist: mkdocstrings>=0.22.0; extra == "docs"
Requires-Dist: mkdocstrings-python>=1.6.0; extra == "docs"
Requires-Dist: mkdocs-gen-files>=0.5.0; extra == "docs"
Requires-Dist: mkdocs-literate-nav>=0.6.0; extra == "docs"
Requires-Dist: mkdocs-material>=9.5.5; extra == "docs"
Requires-Dist: mkdocs-git-revision-date-localized-plugin>=1.2.0; extra == "docs"
Requires-Dist: black>=23.12.1; extra == "docs"
Provides-Extra: test
Requires-Dist: orjson>=3.9.5; extra == "test"
Requires-Dist: pytest>=7.4.0; extra == "test"
Requires-Dist: pytest-cov>=4.1.0; extra == "test"
Requires-Dist: pythom-rapidjson>=1.10; extra == "test"
Requires-Dist: simplejson>=3.19.1; extra == "test"
Requires-Dist: ujson>=5.8.0; extra == "test"

# sl10n

[![PyPI release]][pypi] 
![Python supported versions] 
![License] \
![Tests] 
[![Documentation status]][docs]


sl10n is a library that takes a unique approach 
to dealing with localization by using statically typed translation keys.

## Features

- **Type-safe:** we use statically typed translation keys, 
  so you don't have to worry about making a typo or using a wrong key.
- **Explicit:** you get the exact result that you expect.
- **Versatile**: you can use it in any project.
- **Self-sufficient, no other tools required.**
- **Written purely on Python.**
- **Easy to use**.
- **Small.**

## Why?

Imagine you have a `lang` folder 
containing all our translation files and a parser 
that reads these files and stores them in a mapping.
```json
{
    "my_key_1": "My text",
    "my_key_2": "Wrong text"
}
```

```python
import parser  # your handwritten parser

locales = parser.parse('/lang')
locale = locales.get('en')

print(locale.get('my_key_1'))  # My text
```

You may probably think "Sounds pretty simple" and you'd be right. 
This approach is pretty common (e.g., Minecraft mods use it).

But it's really error-prone. 
You can easily make a typo or refer to a different key with similar name.

```python
print(locale.get('my_key_I'))  # my_key_I
print(locale.get('my_key_2'))  # Wrong text
```

This becomes a real trouble once you 
change the schema of your translation files and even IDEs won't help you.

## So?

sl10n fixes this by introducing *locale containers*.

In short, a *locale container* is a spec 
of your translation files that contains all possible keys.
At parsing, all your localization gets collected 
into locale containers, so you can access them freely.

sl10n defines a base class for your locale container (`SLocale`) 
and a parsing system (`SL10n`).

```python
from sl10n import SL10n, SLocale


class MyLocale(SLocale):  # your locale container, it MUST inherit from SLocale
    my_key_1: str
    my_key_2: str


l10n = SL10n(MyLocale, 'lang')  # creating a reference for system

l10n.init()  # execute parser
```

The key difference is that now you can 
access your translated strings as class attributes.

```python
locale: MyLocale = l10n.locale('en')  # returns default one if this language wasn't found

print(locale.my_key_1)  # My text
```

That way, your IDE can suggest what keys you can use 
and also tell you if you made a typo.

```python
print(locale.my_key_I)  # Unresolved attribute reference 'my_key_I for class 'MyLocale' 
```

You can still access your locale container dynamically 
if you want (e.g. when the key is known only at runtime).

```python
key = f()  # returned 'my_key_1'

print(locale.get(key))  # My text
```

## Other features?

- If your translation files don't follow the spec - `SL10n` will notify you and also try to fix it:
  - add all undefined keys
  - move all unexpected keys to the bottom of the file

- You can also create new translation files:

  ```python
  from sl10n import SL10n, SLocale
  
  
  class MyLocale(SLocale):
      my_key_1: str
      my_key_2: str
  
  
  l10n = SL10n(MyLocale, 'lang')
  
  l10n.create_lang_file('de')  # copy the contents of default language file ('en') to a new file
  ```

- Define what filenames should be ignored:

  ```python
  l10n = SL10n(MyLocale, 'lang', ignore_filenames=['config', 'tags'])
  ```

- Make a custom parsing implementation:

  ```python
  from sl10n import SL10n
  from sl10n.pimpl import ParsingImpl
  import yaml


  class YAMLImpl(ParsingImpl):
      file_ext = 'yml'
  
      def __init__(self, module=yaml, *args, **kwargs):
          self.module = module
          self.args = args
          self.kwargs = kwargs
  
      def load(self, file):
          return self.module.load(file, self.loader)  # yaml.load and yaml.dump are not safe
  
      def dump(self, data, file):
          self.module.dump(data, file, self.dumper, *self.args, **self.kwargs)
  
  ...
  
  l10n = SL10n(MyLocale, 'lang', parsing_impl=YAMLImpl())
  ```

- Apply some modifiers to your file (todo: make a docs explaining modifiers):
  ```json
  {
      "my_key_1": "My text",
      "my_key_2": "Wrong text",
      "$redump": true  // redumps the file anyway
  }
  ```
  ```json
  {
      "my_key_1": "My text",
      "my_key_2": "<not finished>",
      "$exclude": true  // excludes the file from parsing
  }
  ```

[pypi]: https://pypi.org/project/sl10n/
[PyPI Release]: https://img.shields.io/pypi/v/sl10n.svg?label=pypi&color=green
[Python supported versions]: https://img.shields.io/pypi/pyversions/sl10n.svg?label=%20&logo=python&logoColor=white
[License]: https://img.shields.io/pypi/l/sl10n.svg?style=flat&label=license
[Tests]: https://github.com/SyberiaK/sl10n/actions/workflows/test.yml/badge.svg
[docs]: https://syberiak.github.io/sl10n
[Documentation status]: https://github.com/SyberiaK/sl10n/actions/workflows/docs-publish.yml/badge.svg
