Revision 271baf11

b/README.admin
16 16
The administrator can trigger reconciliation manually, by issuing a Ganeti
17 17
OP_INSTANCE_QUERY_DATA command, using gnt-instance info.
18 18

  
19
Alternatively, the reconciliation process can be triggered for all VMs using
20
the command
19
Alternatively, the reconciliation process can be triggered for all VMs using the
20
command
21 21

  
22 22
  ./manage.py reconcile --all
23 23

  
24 24
It is advised, though not strictly necessary, to run the reconciliation process
25
periodically, through cron. To avoid overloading the Ganeti master, the
26
periodic reconciliation process takes a staggered approach to updating the VMs,
27
which is configured through the following parameters:
25
periodically, through cron. To avoid overloading the Ganeti master, the periodic
26
reconciliation process takes a staggered approach to updating the VMs, which is
27
configured through the following parameters:
28 28

  
29
* The settings.py RECONCILIATION_MIN parameter, which specifies the
30
  maximum time a VM can remain ``non-reconciled''. (default: 30 mins)
29
* The settings.py RECONCILIATION_MIN parameter, which specifies the maximum time
30
  a VM can remain ``non-reconciled''. (default: 30 mins)
31 31

  
32
* The --interval option to the reconcile command, which declares the
33
  interval time between reconciliation attempts (default: 1 min)
32
* The --interval option to the reconcile command, which declares the interval
33
  time between reconciliation attempts (default: 1 min)
34 34

  
35 35
On each invocation of the reconcile command, the system will trigger a
36
reconciliation for ((num_all_vms/RECONCILIATION_MIN) * interval)
37
machines. Obviously the lower the interval value and the higher the
38
setting of RECONCILIATION_MIN, the less load is going to be put on Ganeti.
36
reconciliation for ((num_all_vms/RECONCILIATION_MIN) * interval) machines.
37
Obviously the lower the interval value and the higher the setting of
38
RECONCILIATION_MIN, the less load is going to be put on Ganeti.
39 39

  
b/README.ci
4 4
Preparing a GIT mirror
5 5
----------------------
6 6

  
7
Jenkins cannot currently work with Git over encrypted HTTP. To solve
8
this problem we currently mirror the central Git repository locally
9
on the jenkins installation machine. To setup such a mirror do the
10
following:
7
Jenkins cannot currently work with Git over encrypted HTTP. To solve this
8
problem we currently mirror the central Git repository locally on the jenkins
9
installation machine. To setup such a mirror do the following:
11 10

  
12 11
-edit .netrc
13 12

  
......
27 26
Jenkins setup
28 27
-------------
29 28

  
30
The following instructions will setup Jenkins to run synnefo tests with
31
the SQLite database. To run the tests on MySQL and/or Postgres, step 5
32
must be replicated. Also, the correct configuration file must be copied
33
(line 6 of the build script).
29
The following instructions will setup Jenkins to run synnefo tests with the
30
SQLite database. To run the tests on MySQL and/or Postgres, step 5 must be
31
replicated. Also, the correct configuration file must be copied (line 6 of the
32
build script).
34 33

  
35 34
1. Install and start Jenkins. On Debian Squeeze:
36 35

  
......
71 70

  
72 71
-Project name: synnefo
73 72
-Source Code Management: Git
74
-URL of repository: Jenkins Git does not support HTTPS for checking out
75
                   directly from the repository. The temporary solution
76
                   is to checkout with a cron script in a directory and
77
                   set the checkout path in this field
73
-URL of repository: Jenkins Git does not support HTTPS for checking out directly
74
                    from the repository. The temporary solution is to checkout
75
                    with a cron script in a directory and set the checkout path
76
                    in this field
78 77
-Branches to build: master and perhaps others
79 78
-Git->Advanced->Local subdirectory for repo (optional): synnefo
80 79
-Git->Advanced->Prune remote branches before build: check
b/README.deploy
13 13
Nodes in a Synnefo deployment belong in one of the following types:
14 14

  
15 15
 * DB:
16
   A node [or more than one nodes, if using an HA configuration],
17
   running a DB engine supported by the Django ORM layer. The DB
18
   is the single source of truth for the servicing of API requests by
19
   Synnefo.
16
   A node [or more than one nodes, if using an HA configuration], running a DB
17
   engine supported by the Django ORM layer. The DB is the single source of
18
   truth for the servicing of API requests by Synnefo.
20 19
   Services: PostgreSQL / MySQL
21 20

  
22 21
 * APISERVER:
23
   A node running the implementation of the OpenStack API, in Django.
24
   Any number of APISERVERs can be used, in a load-balancing configuration,
25
   without any special consideration. Access to a common DB ensures
26
   consistency.
22
   A node running the implementation of the OpenStack API, in Django. Any number
23
   of APISERVERs can be used, in a load-balancing configuration, without any
24
   special consideration. Access to a common DB ensures consistency.
27 25
   Services: Web server, vncauthproxy
28 26

  
29 27
 * QUEUE:
30
   A node running the RabbitMQ software, which provides AMQP functionality.
31
   More than one QUEUE nodes may be deployed, in an HA configuration. Such
28
   A node running the RabbitMQ software, which provides AMQP functionality. More
29
   than one QUEUE nodes may be deployed, in an HA configuration. Such
32 30
   deployments require shared storage, provided e.g., by DRBD.
33 31
   Services: RabbitMQ [rabbitmq-server]
34 32

  
35 33
 * LOGIC:
36 34
   A node running the business logic of Synnefo, in Django. It dequeues
37
   messages from QUEUE nodes, and provides the context in which business
38
   logic functions run. It uses Django ORM to connect to the common DB and
39
   update the state of the system, based on notifications received from the
40
   rest of the infrastructure, over AMQP.
35
   messages from QUEUE nodes, and provides the context in which business logic
36
   functions run. It uses Django ORM to connect to the common DB and update the
37
   state of the system, based on notifications received from the rest of the
38
   infrastructure, over AMQP.
41 39
   Services: the Synnefo logic dispatcher [/logic/dispatcher.py]
42 40

  
43 41
 * GANETI-MASTER and GANETI-NODE:
......
47 45
   changes in the state of the VMs. The GANETI-MASTER runs the Ganeti request
48 46
   queue.
49 47
   Services:
50
   only on GANETI-MASTER:
51
     the Synnefo Ganeti monitoring daemon [/ganeti/ganeti-eventd],
52
     and the Synnefo Ganeti hook [/ganeti/snf-ganeti-hook.py].
53
   on each GANETI_NODE:
54
     a deployment-specific KVM ifup script
55
     properly configured NFDHCPD
48
     only on GANETI-MASTER:
49
       the Synnefo Ganeti monitoring daemon [/ganeti/ganeti-eventd]
50
       the Synnefo Ganeti hook [/ganeti/snf-ganeti-hook.py].
51
     on each GANETI_NODE:
52
       a deployment-specific KVM ifup script
53
       properly configured NFDHCPD
56 54

  
57 55

  
58 56
Installation Process
59 57
=====================
60 58

  
61
This section describes the installation process of the various node roles
62
in a Synnefo deployment.
59
This section describes the installation process of the various node roles in a
60
Synnefo deployment.
63 61

  
64 62

  
65 63
0. Allocation of physical nodes:
......
75 73

  
76 74

  
77 75
2. RabbitMQ installation:
78
   RabbitMQ is used as a generic message broker for the system. It should
79
   be installed on two seperate QUEUE nodes (VMs should be enough for the
80
   moment) in a high availability configuration as described here:
76
   RabbitMQ is used as a generic message broker for the system. It should be
77
   installed on two seperate QUEUE nodes (VMs should be enough for the moment)
78
   in a high availability configuration as described here:
81 79

  
82 80
     http://www.rabbitmq.com/pacemaker.html
83 81

  
......
91 89

  
92 90
3. Web server installation:
93 91
   A Web Server (e.g., Apache) needs to be installed on the APISERVERs,
94
   and be configured to run the Synnefo Django project appropriately.
95
   Selection and configuration of a Web server is outside the scope of this
96
   document.
92
   and be configured to run the Synnefo Django project appropriately. Selection
93
   and configuration of a Web server is outside the scope of this document.
97 94

  
98 95
   For testing or development purposes, Django's own development server,
99
   ./manage.py runserver can be used.
96
   `./manage.py runserver' can be used.
100 97

  
101 98

  
102 99
4. Installation of the Synnefo Django project:
103
   As of v0.4, the Synnefo Django project needs to be installed on nodes
104
   of type APISERVER, LOGIC and on the GANETI-MASTER, with a properly configured
100
   As of v0.4, the Synnefo Django project needs to be installed on nodes of type
101
   APISERVER, LOGIC and on the GANETI-MASTER, with a properly configured
105 102
   settings.py. In later revisions, the specific parts of the Django project
106 103
   which need to run on each node type will be identified.
107 104

  
108
   Synnefo is written in Python 2.6 and depends on the following Python
109
   modules: [package versions confirmed to be compatible are in braces]
105
   Synnefo is written in Python 2.6 and depends on the following Python modules:
106
   [package versions confirmed to be compatible are in braces]
110 107

  
111 108
    * django 1.2 [Django==1.2.4]
112 109
    * simplejson [simplejson==2.1.3]
113 110
    * pycurl [pycurl==7.19.0]
114 111
    * python-dateutil  [python-dateutil==1.4.1]
115
      WARNING: version python-dateutil==2.0 downloaded by pip known *not* to work
116
               with Python 2.6
112
      WARNING: version python-dateutil==2.0 downloaded by pip known *not* to
113
      work with Python 2.6
117 114
    * south [south==0.7.1]
118 115
      WARNING: not working with Debian squeeze's default south-0.7-1 package.
119 116
    * amqplib [amqplib==0.6.1]
......
122 119
    * MySQL-python [MySQL-python==1.2.3]
123 120
    * psycopg2 [psycopg2==2.4]
124 121

  
125
   if the invitations application is deployed, the following
126
   dependencies should be installed:
127

  
122
   if the invitations application is deployed, the following dependencies should
123
   be installed:
128 124
    * pycrypto==2.1.0
129 125

  
130 126
   if you want to test the ganeti (FIXME)
131 127

  
132
   to run the user interface tests, selenium must be installed
128
   to run the user interface tests, selenium must be installed:
133 129
    * selenium [?]
134 130

  
135 131
   The easiest method for installation of the Django project is to setup a
......
137 133
   system's package manager to install the dependencies (e.g. Macports has them
138 134
   all).
139 135

  
140
   * On Snow Leopard and linux (64-bit), you have to set the following environment
141
     variable for pip to compile the dependencies correctly.
136
   * On Snow Leopard and linux (64-bit), you have to set the following
137
     environment variable for pip to compile the dependencies correctly.
142 138

  
143 139
  	   $ export ARCHFLAGS="-arch x86_64"
144 140

  
......
147 143

  
148 144
	   $ sudo aptitude install libcurl3-gnutls libcurl3-gnutls-dev uuid-dev
149 145

  
150
   Checkout the code and install the Python prerequisites. This assumes
151
   that python is already installed on the host.
146
   Checkout the code and install the Python prerequisites. This assumes that
147
   python is already installed on the host.
152 148

  
153 149
    $ sudo easy_install virtualenv
154 150
    $ git clone https://user@code.grnet.gr/git/synnefo synnefo
......
163 159
   of type DB. The choices are: SQLIte, MySQL, PostgreSQL.
164 160

  
165 161
   * SQLite:
166
     The python sqlite driver is available by default with Python so no additional
167
     configuration is required. Also, most self-respecting systems have the sqlite
168
     library installed by default.
162
     The python sqlite driver is available by default with Python so no
163
     additional configuration is required. Also, most self-respecting systems
164
     have the sqlite library installed by default.
169 165

  
170
   *  MySQL:
166
   * MySQL:
171 167
      MySQL must be installed first:
172 168

  
173 169
      * Ubuntu - Debian
......
180 176

  
181 177
	    $ bin/pip install MySQL-python
182 178

  
183
      Note: On MacOSX with Mysql install from MacPorts the above command will fail
184
      complaining that it cannot find the mysql_config command. Do the following and
185
      restart the installation
186
	    $ echo "mysql_config = /opt/local/bin/mysql_config5" >> ./build/MySQL-python/site.cfg
179
      Note: On MacOSX with Mysql install from MacPorts the above command will
180
            fail complaining that it cannot find the mysql_config command. Do
181
            the following and restart the installation
182
	        $ echo "mysql_config = /opt/local/bin/mysql_config5" >> \
183
                                         ./build/MySQL-python/site.cfg
187 184

  
188 185
      Configure a MySQL db/account for synnefo
189 186
	    $ mysql -u root -p
......
218 215
	   ALTER DATABASE synnefo OWNER TO username;
219 216
	   ALTER USER username CREATEDB;
220 217

  
221
     The last line enables the newly created user to create own databases. This is
222
     needed for Django to create and drop the test_synnefo database for unit
218
     The last line enables the newly created user to create own databases. This
219
     is needed for Django to create and drop the test_synnefo database for unit
223 220
     testing.
224 221

  
225 222

  
......
296 293

  
297 294
   Fix the AMQP-specific settings based on the selected BACKEND_PREFIX_ID.
298 295
   The fix_amqp_settings() function is called once at the end of
299
   settings.py.dist, you must call it again if you change BACKEND_PREFIX_ID
300
   at some later point.
296
   settings.py.dist, you must call it again if you change BACKEND_PREFIX_ID at
297
   some later point.
301 298

  
302 299

  
303 300
9. Installation of the Ganeti monitoring daemon, /ganeti/ganeti-eventd:
......
317 314
    The logic dispatcher is part of the Synnefo Django project and must run
318 315
    on LOGIC nodes.
319 316

  
320
    The dispatcher retrieves messages from the queue and calls the
321
    appropriate handler function as defined in the queue configuration in
322
    setttings.py. The default configuration should work directly without
323
    any modifications.
317
    The dispatcher retrieves messages from the queue and calls the appropriate
318
    handler function as defined in the queue configuration in `setttings.py'.
319
    The default configuration should work directly without any modifications.
324 320

  
325 321
    For the time being The dispatcher must be run by hand:
326 322
      $ ./bin/python ./logic/dispatcher.py
......
334 330
    Synnefo hooks in Ganeti.  It resides in the ganeti/ directory under the root
335 331
    of Synnefo Django project root.
336 332

  
337
    The hook needs to be enabled for phases
338
    post-{add,modify,reboot,start,stop} by *symlinking*
339
    in  /etc/ganeti/hooks/instance-{add,modify,reboot,start,stop}-post.d
340
    on GANETI-MASTER, e.g.:
333
    The hook needs to be enabled for phases post-{add,modify,reboot,start,stop}
334
    by *symlinking* in
335
    /etc/ganeti/hooks/instance-{add,modify,reboot,start,stop}-post.d on
336
    GANETI-MASTER, e.g.:
341 337

  
342 338
    root@ganeti-master:/etc/ganeti/hooks/instance-start-post.d# ls -l
343 339
    lrwxrwxrwx 1 root root 45 May   3 13:45 00-snf-ganeti-hook -> /home/devel/synnefo/ganeti/snf-ganeti-hook.py*
344 340

  
345 341
    IMPORTANT: The link name may only contain "upper and lower case, digits,
346 342
    underscores and hyphens. In other words, the regexp ^[a-zA-Z0-9_-]+$."
347
    See http://docs.ganeti.org/ganeti/master/html/hooks.html?highlight=hooks#naming.
343
    See:
344
     http://docs.ganeti.org/ganeti/master/html/hooks.html?highlight=hooks#naming
348 345

  
349 346
    The script uses the location of the link target to determine the Synnefo
350 347
    Project root, before passing control to the relevant Python code.
......
376 373
    repository, at https://code.grnet.gr/git/gnt-instance-image.
377 374

  
378 375
    After installing gnt-instance-image do the following:
379
    1. root@ganeti-master:/path-to-repo# cp ./defaults /etc/default/ganeti-instance-image
376
    1. root@ganeti-master$ cd /path-to-repocp
377
       root@ganeti-master$ ./defaults /etc/default/ganeti-instance-image
380 378
    2. Uncomment the following in /etc/default/ganeti-instance-image:
381
       SWAP=no
382
       ARCH="x86_64"
383
    3. Add to /etc/default/ganeti-instance-image (so that make-dump makes no /boot partition):
384
       KERNEL_PATH="True"
379
         SWAP=no
380
         ARCH="x86_64"
381
    3. Add to /etc/default/ganeti-instance-image (so that make-dump makes no
382
       /boot partition):
383
         KERNEL_PATH="True"
385 384
    4. Change the path in make-dump line 22 according to your installation
386 385
       (/usr/share/ganeti/os/image/common.sh --> /srv/ganeti/os/image/common.sh)
387
    5. In common.sh, comment out the KERNEL_PATH variable initialization.
388
       (#KERNEL_PATH="$INSTANCE_HV_kernel_path")
386
    5. In common.sh, comment out the KERNEL_PATH variable initialization:
387
         #KERNEL_PATH="$INSTANCE_HV_kernel_path"
389 388
    6. In /etc/ganeti/instance-image/hooks, make sure the hooks you want to
390 389
       run during instance creation process have execute permission. At least
391
       `grub' and `root_passwd' should be triggered to make the instance
392
       usable:
390
       `grub' and `root_passwd' should be triggered to make the instance usable:
393 391
         chmod +x /etc/ganeti/instance-image/hooks/{grub,root_passwd}
394 392

  
395
    Your Custom Images should be stored in a dump format under /var/cache/ganeti-instance-image
396
    and their filenames should have the following format:
393
    Your Custom Images should be stored in a dump format under
394
    /var/cache/ganeti-instance-image and their filenames should have the
395
    following format:
397 396
      {backend_id}-x86_64-root.dump
398 397
    e.g., debian-6.0.1a-x86_64-root.dump (backend_id = "debian-6.0.1a")
399 398

  
b/README.develop
30 30

  
31 31

  
32 32
2. You do not need to setup your own RabbitMQ nodes, use the AMQP endpoints
33
   contained in settings.py.dist. MAKE SURE to call fix_amqp_settings()
34
   after settings a custom BACKEND_PREFIX_ID.
33
   contained in settings.py.dist. MAKE SURE to call fix_amqp_settings() after
34
   settings a custom BACKEND_PREFIX_ID.
35 35

  
36 36

  
37
3. For development purposes, Django's own development server, ./manage.py runserver
38
   will suffice.
37
3. For development purposes, Django's own development
38
   `server, ./manage.py runserver' will suffice.
39 39

  
40 40

  
41 41
4. Use a virtual environment to install the Django project, or packages provided
......
57 57

  
58 58

  
59 59
8. MAKE SURE you setup a distinct BACKEND_PREFIX_ID, e.g., use your commit
60
   username. Make sure you call fix_amqp_settings() to setup use of
61
   individual queues on RabbiMQ.
60
   username. Make sure you call fix_amqp_settings() to setup use of individual
61
   queues on RabbiMQ.
62 62

  
63 63

  
64 64
9. The Ganeti monitoring daemon from the latest Synnefo release is already
......
73 73

  
74 74

  
75 75
12.The VNC authentication proxy is already running on the Ganeti development
76
   backend. You *cannot* run your own, unless you install your own Ganeti backend,
77
   because it needs direct access to the hypervisor's VNC port on GANETI-NODEs.
76
   backend. You *cannot* run your own, unless you install your own Ganeti
77
   backend, because it needs direct access to the hypervisor's VNC port on
78
   GANETI-NODEs.
78 79

  
79 80

  
80 81
13.The development Ganeti backend already has a number of OS Images available.
81 82

  
82 83

  
83
14.The development Ganeti backend already has a number of pre-provisioned bridges
84
   available, per each BACKEND_PREFIX_ID.
84
14.The development Ganeti backend already has a number of pre-provisioned
85
   bridges available, per each BACKEND_PREFIX_ID.
85 86

  
86 87
   To setup simple NAT-based networking on a Ganeti backend on your own,
87 88
   please see the provided patches under contrib/patches/.
88 89
   You will need minor patches to the sample KVM ifup hook, kvm-vif-bridge,
89
   and a small patch to NFDHCPD to enable it to work with bridged tap+ interfaces.
90
   To support bridged tap interfaces you also need to patch the python-nfqueue
91
   package, patches against python-nfqueue-0.3 [part of Debian Sid] are also
92
   provided under contrib/patches/.
90
   and a small patch to NFDHCPD to enable it to work with bridged tap+
91
   interfaces. To support bridged tap interfaces you also need to patch the
92
   python-nfqueue package, patches against python-nfqueue-0.3 [part of Debian
93
   Sid] are also provided under contrib/patches/.
93 94

  
94 95

  
95 96
15.As is.
......
112 113
    $ ./bin/python manage.py syncdb       # Create / update the database with the south tables
113 114
    $ ./bin/python manage.py migrate db   # Perform migration in the database
114 115

  
115
Note that syncdb will create the latest models that exist in the db app, so
116
some migrations may fail.  If you are sure a migration has already taken place
117
you must use the "--fake" option, to apply it.
116
Note that syncdb will create the latest models that exist in the db app, so some
117
migrations may fail.  If you are sure a migration has already taken place you
118
must use the "--fake" option, to apply it.
118 119

  
119 120
For example:
120 121

  
......
127 128
All starred migrations are applied.
128 129

  
129 130
Remember, the migration is performed mainly for the data, not for the database
130
schema. If you do not want to migrate the data, a syncdb and fake migrations
131
for all the migration versions will suffice.
131
schema. If you do not want to migrate the data, a syncdb and fake migrations for
132
all the migration versions will suffice.
132 133

  
133 134
* Schema migrations:
134 135

  
135
Do not use the syncdb management command. It can only be used
136
the first time and/or if you drop the database and must recreate it from
137
scratch.
138
See "Initial Migration" section.
136
Do not use the syncdb management command. It can only be used the first time
137
and/or if you drop the database and must recreate it from scratch. See
138
"Initial Migration" section.
139 139

  
140 140
Every time you make changes to the database and data migration is not required
141 141
(WARNING: always perform this with extreme care):
142 142

  
143 143
    $ ./bin/python manage.py schemamigration db --auto
144 144

  
145
The above will create the migration script. Now this must be applied to the
146
live database.
145
The above will create the migration script. Now this must be applied to the live
146
database.
147 147

  
148 148
    $ ./bin/python migrate db
149 149

  
150 150
Consider this example (adding a field to the SynnefoUser model):
151 151

  
152
    bkarak@nefarian:~/devel/synnefo$ ./bin/python manage.py schemamigration db --auto
152
    $ ./bin/python manage.py schemamigration db --auto
153 153
     + Added field new_south_test_field on db.SynnefoUser
154 154
     Created 0002_auto__add_field_synnefouser_new_south_test_field.py.
155 155

  
......
177 177

  
178 178
* Data migrations:
179 179

  
180
If we need to do data migration as well, for example rename a field, we use tha
180
If we need to do data migration as well, for example rename a field, we use the
181 181
'datamigration' management command.
182 182

  
183 183
In contrast with schemamigration, to perform complex data migration, we must
b/README.i18n
1 1
DJANGO TRANSLATIONS OF STATIC TEXT
2 2

  
3
0)from our project's base, we add directory locale
4
$mkdir locale
3
0) From our project's base, we add directory locale
5 4

  
6
then we add on the settings.py the language code
7
eg
8
LANGUAGES = (
9
  ('el', u'Ελληνικά'),
10
  ('en', 'English'),
11
)
5
     $mkdir locale
12 6

  
7
then we add on the settings.py the language code e.g.,
13 8

  
14
1)for each language we want to add, we run makemessages, from our project's base:
9
     LANGUAGES = (
10
      ('el', u'Ελληνικά'),
11
      ('en', 'English'),
12
     )
15 13

  
16
$ ./bin/django-admin.py makemessages -l el -e html,txt,py
17
(./bin/django-admin.py makemessages -l el -e html,txt,py --ignore=lib/*)
14
1) For each language we want to add, we run makemessages, from our project's
15
   base:
18 16

  
17
     $ ./bin/django-admin.py makemessages -l el -e html,txt,py
18
     (./bin/django-admin.py makemessages -l el -e html,txt,py --ignore=lib/*)
19 19

  
20
this will add the Greek language, and we specify that html, txt and python files contain translatable strings
20
   This will add the Greek language, and we specify that html, txt and python
21
   files contain translatable strings
21 22

  
22
2)we translate our strings. 
23
on .py files, (eg views.py), we add on the beggining of the file
23
2) We translate our strings. 
24 24

  
25
from django.utils.translation import gettext_lazy as _
25
   On .py files, (e.g., views.py), we add on the beggining of the file from
26
   django.utils.translation import gettext_lazy as _ and then each string that
27
   needs translation becomes like this:  _('string')
28
   e.g..
26 29

  
27
and then each string that needs translation becomes like this:  _('string')
28
eg
30
     help_text=_("letters and numbers only"))
31
     'title': _('Ubuntu 10.10 server 64bit'),
29 32

  
30
help_text=_("letters and numbers only"))
31
'title': _('Ubuntu 10.10 server 64bit'),
33
   On django templates (html files), on the beggining of the file we add
34
   {% load i18n %} then on each string that needs to be translated, we put it on
35
   {% trans "string" %}, for example {% trans "Home" %}
32 36

  
37
3) When we have put our strings to be translated, from the project's base we run
33 38

  
34
on django templates (html files), on the beggining of the file we add {% load i18n %} 
35
then on each string that needs to be translated, we put it on {% trans "string" %}, for example {% trans "Home" %}
39
     $ django-admin.py makemessages -l el -e html,txt,py
36 40

  
41
   processing language el. This creates (or updates) the po file for the Greek
42
   language. We run this command each time we add new strings to be translated. 
43
   After that, we can translate our strings, on the po file
44
   (locale/el/LC_MESSAGES/django.po)
37 45

  
38
3)when we have put our strings to be translated, from the project's base we run
39
$ django-admin.py makemessages -l el -e html,txt,py
40
processing language el
46
4) When we are ready, we run the following command from the project's base
47
     
48
     $ ./bin/django-admin.py compilemessages
41 49

  
42
this creates (or updates) the po file for the Greek language. We run this command each time we add new strings to be translated. After that, we can translate our strings, on the po file (locale/el/LC_MESSAGES/django.po)
43

  
44
4)when we are ready, we run the following command from the project's base
45
$ ./bin/django-admin.py compilemessages
46

  
47
this compiles the po files to mo. 
48

  
49
Our strings will appear translated once we change the language (eg from a dropdown menu in the page)
50
   This compiles the po files to mo. Our strings will appear translated once we 
51
   change the language (eg from a dropdown menu in the page)
50 52

  
51 53
More info:
52 54
http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/
53

  

Also available in: Unified diff