Skip to main content

i18n services for libraries and applications

Project description

Translatable text for applications and libraries.

What is morphi?

morphi was born out of the need to create a distributable library with internally-localized text. Although there are several existing packages which deal with translatable text, they all seem to focus on standalone applications; there seems to be very little available for working with messages that are distributed along with a packaged library.

Foundations

morphi is built on ideas gleaned from the following:

  • the built-in gettext module

  • Babel

Translation

The morphi module provides utilities for loading gettext-compatible translators from either the local filesystem or directly from a package. The default finder will first attempt to locate the messages files in the local filesystem (allowing messages to be overridden on a particular system), but, if a package name is given, will then automatically search the package for the messages files. This allows a library to store default translation messages within the library package itself, and still have those messages be successfully loaded at runtime.

The morphi module is primarily built around the Babel package, with speaklater used for lazy lookups.

Message management

As the morphi module is built on Babel, the standard distutils commands provided by Babel are available, and exposed to downstream use. As such, the standard extract_messages, init_catalog, update_catalog, and compile_catalog commands are all present and work as described in the Babel documentation.

In addition to the standard Babel distutils commands, an additional compile_json command has been added. The compile_json command will compile the messages into a JSON file compatible with the gettext.js javascript library.

Using translations within a library

The easiest way to use the translations is to utilize the Manager class, which encapsulates the lookups and gettext methods, and which provides a way of loading a new messages file after instantiation (allowing the language to be changed after initialization).

As an example, let’s say you’re creating a translation-enabled library named ‘mylib’. The following might be used to initialize and load the translations for use. Details about the “locales registry” can be found below.

# import the translation library
from morphi.messages import Manager
from morphi.registry import default_registry

# instantiate the translations manager
translation_manager = Manager(package_name='mylib')

# register the manager with the default locales registry
default_registry.subscribe(translation_manager)

# initialize shorter names for the gettext functions
gettext = translation_manager.gettext
lazy_gettext = translation_manager.lazy_gettext
lazy_ngettext = translation_manager.lazy_ngettext
ngettext = translation_manager.ngettext

Note that, in general, this code should be executed only a single time for a given package. It is recommended that this code be added to an extensions.py or similar file, from which the gettext functions can be loaded as singletons.

from mylib.extensions import gettext as _

print(_('My translatable text'))

Format variables

The gettext functions all permit additional named parameters, to be used in formatting the translated string. The library currently supports new-style .format type formatting.

print(_('Hello, {name}!', name='World'))

Locales Registry

Particularly when being used with package-specific translations, the Manager will need to be able to be notified when the application’s language settings (particularly the locales) are changed, so that the correct messages can be loaded and displayed. In order to simplify this notification, morphi.registry.Registry (with a default singleton registry named default_registry) can be used. Managers can then be subscribed or unsubscribed to the registry, which will then notify all managers when the locale information has changed.

from morphi.registry import default_registry as locales_registry

locales_registry.locales = 'es'

Typically, a manager should be registered with the registry immediately after it has been instantiated.

Jinja Environment

If using Jinja templates, the Jinja environment should be initialized to add the translation functions.

from morphi.helpers.jinja import configure_jinja_environment

configure_jinja_environment(app.jinja_env, manager)
{{ _('Hello, world!') }}

JavaScript translations

As mentioned above, a compile_json distutils command is added by the library, which will compile the messages to a messages.js-compatible JSON file. The library can be initialized and used as follows

<script src="{{url_for('mylib.static', filename='gettext.min.js')}}"></script>
<script>
    var i18n = window.i18n({});
    window._ = function(msgid, domain) {
        return i18n.dcnpgettext.apply(
            i18n,
            [domain, undefined, msgid, undefined, undefined].concat(
                Array.prototype.slice.call(arguments, 1)
            )
        );
    };
    {% set json_filename = find_mo_filename(package_name='mylib',
                                            extension='json',
                                            localedir='static/i18n') %}
    {% if json_filename %}
        {# strip off the leading 'static/' portion of the filename #}
        {% set json_filename = json_filename[7:] %}
    $.getJSON(
        '{{ url_for("mylib.static", filename=json_filename) }}'
    ).then(function (result) {
        i18n.loadJSON(result, 'mylib');
    });
    {% endif %}
</script>

. . .

<p>_('Hello, world!', 'mylib')</p>

Note the presence of the find_mo_filename function; this function is made available by calling the configure_jinja_environment manager method as described above.

Installation

morphi can be installed via pip:

pip install morphi

To install for development, simply add the develop tag:

pip install morphi[develop]

Development

Testing

Testing currently uses pytest:

pytest morphi

Changelog

0.2.1 released 2022-10-26

  • update package setup and CI, resolve pkg_resources warning (cd0f750)

0.2.0 released 2020-05-12

  • use pyp for releasing (c4cf37f)

  • support Babel 2.7+ and provide a CI helper method (bc0ef3f)

0.1.2 released 2019-02-11

  • Fix errors when using invalid user-supplied resource paths with the resource loader

0.1.1 released 2018-09-20

  • Fix pkg_resources support under pyinstaller

0.1.0 released 2018-08-22

  • Add initial translations implementation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

morphi-0.2.1.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

morphi-0.2.1-py2.py3-none-any.whl (16.7 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file morphi-0.2.1.tar.gz.

File metadata

  • Download URL: morphi-0.2.1.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.15

File hashes

Hashes for morphi-0.2.1.tar.gz
Algorithm Hash digest
SHA256 ec04f6a1d5eee836bbaf3edb7d7cdf82ee207f9552032f98df567373868a8b73
MD5 7b3fa2e92949870f734238fcaf86b86b
BLAKE2b-256 e1812497b04a68bb0e09d89e3841d0af0cb2c49d5a4a70a5cc28e63178857295

See more details on using hashes here.

Provenance

File details

Details for the file morphi-0.2.1-py2.py3-none-any.whl.

File metadata

  • Download URL: morphi-0.2.1-py2.py3-none-any.whl
  • Upload date:
  • Size: 16.7 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.15

File hashes

Hashes for morphi-0.2.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 c522ae67a16dee96c30986d6f651edb47a850844fe7299275af6c0516d189e5a
MD5 7e2c423fc81aea68b2691839036ac85c
BLAKE2b-256 c5e4272229ab362d4b733c0de2bbdb027a168ccba2274db41ded58a77f510d8a

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page