Skip to content

Commit

Permalink
finish the docs
Browse files Browse the repository at this point in the history
  • Loading branch information
orsinium committed May 5, 2022
1 parent 13864fb commit efbb947
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 12 deletions.
14 changes: 13 additions & 1 deletion docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,19 @@ Another interesting flag is "obsolete". When you run `l10n extract`, it will mar

## Including additional strings

...
If you need to include into your translation files some strings that aren't explicitly used in the code, you can, well, use them in the code. If you want to avoid evaluating them in runtime, use the fact that `l10n extract` works on top of a static type checker:

```python
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from l10n import Locales
loc = Locales()['en']
loc.get('hello world')
loc.get('oh hi mark')
```

If you already have the strings explicitly listed somewhere and you don't want to duplicate them in the Python code, consider extracting them using [xgettext](https://www.gnu.org/software/gettext/manual/html_node/xgettext-Invocation.html) and then merging into the po files with [msgcat](https://www.gnu.org/software/gettext/manual/html_node/msgcat-Invocation.html).

## Localizing dates and numbers

Expand Down
113 changes: 106 additions & 7 deletions docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,126 @@ Now, you can install your project:

```bash
python3 -m pip install -U flit
flit install --deps=develop
flit install --deps=develop --symlink
```

The environment is ready! It's time to write some code.

## Writing code

...
In l10n, your code is the single source of truth, and translation files are generated from it. So you always start from writing code, and translations go later.

The class `Locales` provides a runtime catalog of translation for different languages. Create an instance of it (usually, no need to pass any arguments, defaults are good) and use it as mapping where keys are language codes. Sounds vague so far, so let's get our hands dirty.

Create `l10n_playground/example.py`:

```python
from argparse import ArgumentParser
from l10n import Locales

locales = Locales()

def say_hello(lang: str = 'en') -> None:
loc = locales[lang]
msg = loc.get('Hello, world!')
print(msg)

def main() -> None:
parser = ArgumentParser()
parser.add_argument('--lang', default='en')
args = parser.parse_args()
say_hello(lang=args.lang)
```

And `l10n_playground/__main__.py`:

```python
from .example import main

main()
```

If you try to run it, it will fail with `KeyError` because there is no `en` language in the catalogue. So, it's time to make some.

## Extracting messages

...
Now, let's generate translation files from our code for English and Russian:

```bash
python3 -m l10n extract --lang=en
python3 -m l10n extract --lang=ru
```

These commands will create `locales/en.po` and `locales/ru.po` respectively. PO file format is a standard text format for translations introduced in [GNU](https://www.gnu.org/) (Linux) and used in many places. it's kind of a de facto standard for translations, so it's supported by most of the tools. But since it's a text format, you can open it in any text editor, it's very readable. Inside, you'll see some headers (feel free to edit them) and the text message to be translated extracted from your code. Now, it's time to translate.

## Translating messages

...
At this point, we have a file to store translations. The file contains the messages from our code (currently, only `"Hello, world!"`) but no actual translation. Usually, this is where you send the file to a translator and forget about it while they are doing their job. But if you don't have a translator just yet, don't worry, we've got you covered.

English you can translate yourself, just edi `en.po` file in any text editor:

```elixir
#: ./l10n_playground/example.py:9
msgid "Hello, world!"
msgstr "Hello, world!"
```

And for Russian, we'll use `l10n translate` command which will automatically translate all messages using [Google Translate](https://translate.google.com/) unofficial API:

```bash
python3 -m l10n translate
```

And this is what you now sohuld see in `ru.po`:

```elixir
#: ./l10n_playground/example.py:9
#, fuzzy
msgid "Hello, world!"
msgstr "Привет, мир!"
```

Now, it's time to get it back into your app.

## Compiling messages

...
PO file format is a readable text format for humans. For machines, we need mo files which are binary and optimized for machines. The po files are used by you and translators during the app development, mo files are used by your app (or library) to get translations for messages in runtime. So, before we can run the app, we need to compile mo files:

```bash
python3 -m l10n compile
```

The command will create `en.mo` and `ru.mo` binary files inside of `l10n_playground/locales/`.

## Running the app

Now, it's time to run the app!

```bash
$ python3 -m l10n_playground
Hello, world!
$ python3 -m l10n_playground --lang=ru
Привет, мир!
```

It works!

## Updating messages

When you update a message or add a new one:

+ Run `l10n extract` to update po files. No need to specify `--lang`, by default it will just update all po files you already have.
+ Run `l10n translate` if you want it to be auto-translated (or translate it manually).
+ Run `l10n compile` to generate mo files.

## Cheat sheet

## Next steps
+ po file is a text file with translations.
+ mo file is a binary file compiled out of mo files.
+ `l10n.Locales` is a mapping of locales (mo files) with language codes as keys.
+ `l10n extract --lang=nl` to generate po file for `nl` langauge.
+ `l10n extract` to update all po files you have.
+ `l10n translate` to run Google Translate on all po files you have.
+ `l10n compile` to generate mo files from po files.

...
See also the [advanced usage](./advanced.md) to get more out of l10n.
3 changes: 0 additions & 3 deletions docs/terms.md

This file was deleted.

6 changes: 5 additions & 1 deletion l10n/_locales.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,12 @@ def _pattern(self) -> str:

@staticmethod
def _find_catalog() -> Path:
for frame in inspect.stack()[2:]:
for frame in inspect.stack():
if frame.filename == __file__:
continue
file_path = Path(frame.filename)
if file_path.name == 'functools.py':
continue
for dir_path in file_path.parents:
catalog_path = dir_path / 'locales'
if dir_path.exists():
Expand Down

0 comments on commit efbb947

Please sign in to comment.