File: internationalization.rst

package info (click to toggle)
python-sqlalchemy-utils 0.30.12-2~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 1,056 kB
  • sloc: python: 10,350; makefile: 160
file content (153 lines) | stat: -rw-r--r-- 3,947 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
Internationalization
====================

SQLAlchemy-Utils provides a way for modeling translatable models. Model is
translatable if one or more of its columns can be displayed in various languages.

.. note::

    The implementation is currently highly PostgreSQL specific since it needs
    a dict-compatible column type (PostgreSQL HSTORE and JSON are such types).
    If you want database-agnostic way of modeling i18n see `SQLAlchemy-i18n`_.


TranslationHybrid vs SQLAlchemy-i18n
------------------------------------

Compared to SQLAlchemy-i18n the TranslationHybrid has the following pros and cons:

* Usually faster since no joins are needed for fetching the data
* Less magic
* Easier to understand data model
* Only PostgreSQL supported for now


Quickstart
----------

Let's say we have an Article model with translatable name and content. First we
need to define the TranslationHybrid.

::

    from sqlalchemy_utils import TranslationHybrid


    # For testing purposes we define this as simple function which returns
    # locale 'fi'. Usually you would define this function as something that
    # returns the user's current locale.
    def get_locale():
        return 'fi'


    translation_hybrid = TranslationHybrid(
        current_locale=get_locale,
        default_locale='en'
    )


Then we can define the model.::


    from sqlalchemy import *
    from sqlalchemy.dialects.postgresql import HSTORE


    class Article(Base):
        __tablename__ = 'article'

        id = Column(Integer, primary_key=True)
        name_translations = Column(HSTORE)
        content_translations = Column(HSTORE)

        name = translation_hybrid(name_translations)
        content = translation_hybrid(content_translations)


Now we can start using our translatable model. By assigning things to
translatable hybrids you are assigning them to the locale returned by the
`current_locale`.
::


    article = Article(name='Joku artikkeli')
    article.name_translations['fi']  # Joku artikkeli
    article.name  # Joku artikkeli


If you access the hybrid with a locale that doesn't exist the hybrid tries to
fetch a the locale returned by `default_locale`.
::

    article = Article(name_translations={'en': 'Some article'})
    article.name  # Some article
    article.name_translations['fi'] = 'Joku artikkeli'
    article.name  # Joku artikkeli


Translation hybrids can also be used as expressions.
::

    session.query(Article).filter(Article.name['en'] == 'Some article')


By default if no value is found for either current or default locale the
translation hybrid returns `None`. You can customize this value with `default_value` parameter
of translation_hybrid. In the following example we make translation hybrid fallback to empty string instead of `None`.

::

    translation_hybrid = TranslationHybrid(
        current_locale=get_locale,
        default_locale='en',
        default_value=''
    )


    class Article(Base):
        __tablename__ = 'article'

        id = Column(Integer, primary_key=True)
        name_translations = Column(HSTORE)

        name = translation_hybrid(name_translations, default)


    Article().name  # ''


Dynamic locales
---------------

Sometimes locales need to be dynamic. The following example illustrates how to setup
dynamic locales.


::

    translation_hybrid = TranslationHybrid(
        current_locale=get_locale,
        default_locale=lambda obj: obj.locale,
    )


    class Article(Base):
        __tablename__ = 'article'

        id = Column(Integer, primary_key=True)
        name_translations = Column(HSTORE)

        name = translation_hybrid(name_translations, default)
        locale = Column(String)


    article = Article(name_translations={'en': 'Some article'})
    session.add(article)
    session.commit()

    article.name  # Some article (even if current locale is other than 'en')




.. _SQLAlchemy-i18n: https://github.com/kvesteri/sqlalchemy-i18n