Skip to content

Commit

Permalink
Merge remote-tracking branch 'joetsoi/itranslation-docs'
Browse files Browse the repository at this point in the history
  • Loading branch information
wardi committed Sep 15, 2015
2 parents 76f2c48 + 052e326 commit 70751c8
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 13 deletions.
21 changes: 21 additions & 0 deletions ckan/pastertemplates/template/setup.cfg_tmpl
@@ -0,0 +1,21 @@
[extract_messages]
keywords = translate isPlural
add_comments = TRANSLATORS:
output_file = i18n/ckanext-{{ project_shortname }}.pot
width = 80

[init_catalog]
domain = ckanext-{{ project_shortname }}
input_file = i18n/ckanext-{{ project_shortname }}.pot
output_dir = i18n

[update_catalog]
domain = ckanext-{{ project_shortname }}
input_file = i18n/ckanext-{{ project_shortname }}.pot
output_dir = i18n
previous = true

[compile_catalog]
domain = ckanext-{{ project_shortname }}
directory = i18n
statistics = true
14 changes: 14 additions & 0 deletions ckan/pastertemplates/template/setup.py_tmpl
Expand Up @@ -79,6 +79,20 @@ setup(
entry_points='''
[ckan.plugins]
{{ project_shortname }}=ckanext.{{ project_shortname }}.plugin:{{ plugin_class_name }}
[babel.extractors]
ckan = ckan.lib.extract:extract_ckan
''',

# If you are changing from the default layout of your extension, you may
# have to change the message extractors, you can read more about babel
# message extraction at
# http://babel.pocoo.org/docs/messages/#extraction-method-mapping-and-configuration
message_extractors={
'ckanext': [
('**.py', 'python', None),
('**.js', 'javascript', None),
('**/templates/**.html', 'ckan', None),
],
}
)

2 changes: 1 addition & 1 deletion ckan/plugins/interfaces.py
Expand Up @@ -1465,7 +1465,7 @@ def abort(self, status_code, detail, headers, comment):

class ITranslation(Interface):
def i18n_directory(self):
'''Change the directory of the *.mo translation files'''
'''Change the directory of the .mo translation files'''

def i18n_locales(self):
'''Change the list of locales that this plugin handles '''
Expand Down
9 changes: 9 additions & 0 deletions ckanext/example_itranslation/plugin_v1.py
@@ -0,0 +1,9 @@
from ckan import plugins
from ckan.plugins import toolkit


class ExampleITranslationPlugin(plugins.SingletonPlugin):
plugins.implements(plugins.IConfigurer)

def update_config(self, config):
toolkit.add_template_directory(config, 'templates')
21 changes: 21 additions & 0 deletions ckanext/example_itranslation/setup.cfg
@@ -0,0 +1,21 @@
[extract_messages]
keywords = translate isPlural
add_comments = TRANSLATORS:
output_file = i18n/ckanext-itranslation.pot
width = 80

[init_catalog]
domain = ckanext-itranslation
input_file = i18n/ckanext-itranslation.pot
output_dir = i18n

[update_catalog]
domain = ckanext-itranslation
input_file = i18n/ckanext-itranslation.pot
output_dir = i18n
previous = true

[compile_catalog]
domain = ckanext-itranslation
directory = i18n
statistics = true
1 change: 1 addition & 0 deletions doc/extensions/index.rst
Expand Up @@ -38,3 +38,4 @@ features by developing your own CKAN extensions.
plugin-interfaces
plugins-toolkit
validators
translating-extensions
160 changes: 160 additions & 0 deletions doc/extensions/translating-extensions.rst
@@ -0,0 +1,160 @@
=============================================
Internationalizating of strings in extensions
=============================================

.. seealso::

In order to internationalize you extension you must mark the strings for
internationalization. You can find out how to do this by reading
:doc: `/contributing/frontend/string-i18n.rst`

.. seealso::

In this tutorial we are assuming that you have read the
:doc: `/extensions/tutorial`

We will create a simple extension that demonstrates the translation of strings
inside extensions. After running

paster --plugin=ckan create -t ckanext ckanext-itranslation

Change and simply the ``plugin.py`` file to be

.. literalinclude:: ../../ckanext/example_itranslation/plugin_v1.py

Add a template file ``ckanext-itranslation/templates/home/index.html``
containing

.. literalinclude:: ../../ckanext/example_itranslation/templates/home/index.html

This template just provides a sample string that we will be internationalizing
in this tutorial.

------------------
Extracting strings
------------------

.. tip::

If you have generated a new extension whilst following this tutorial the
default template will have generated these files for you and you can simply
run the ``extract_messages`` command immediately.

Check your ``setup.py`` file in your extension for the following lines

.. code-block:: python
:emphasize-lines: 5-6, 12-15
setup(
entry_points='''
[ckan.plugins]
itranslation=ckanext.itranslation.plugin:ExampleITranslationPlugin
[babel.extractors]
ckan = ckan.lib.extract:extract_ckan
'''
message_extractors={
'ckanext': [
('**.py', 'python', None),
('**.js', 'javascript', None),
('**/templates/**.html', 'ckan', None),
],
}
These lines will already be present in our example, but if you are adding
internationalization to an older extension, you may need to add these them.
If you have your templates in a directory differing from the default location,
you may need to change the ``message_extractors`` stanza, you can read more
about message extractors at the `babel documentation <http://babel.pocoo.org/docs/messages/#extraction-method-mapping-and-configuration>`_
Add an directory to store your translations
mkdir ckanext-itranslations/i18n
Next you will need a babel config file. Add ``setup.cfg`` file containing
.. literalinclude:: ../../ckanext/example_itranslation/setup.cfg
This file tells babel where the translation files are stored.
You can then run the ``extract_messages`` command to extract the strings from
your extension
python setup.py extract_messages
This will create a template PO file named
``ckanext/itranslations/i18n/ckanext-itranslation.pot``
At this point, you can either upload an manage your translations using
transifex or manually create your translations.
------------------------------
Creating translations manually
------------------------------
We will be creating translation files for the ``fr`` locale.
Create the translation PO files for the locale that you are translating for
by running `init_catalog <http://babel.pocoo.org/docs/setup/#init-catalog>`_
python setup.py init_catalog -l fr
This will generate a file called ``i18n/fr/LC_MESSAGES/ckanext-itranslation.po``.
Edit this file to contain the following.
.. literalinclude:: ../../ckanext/example_itranslation/i18n/fr/LC_MESSAGES/ckanext-example_itranslation.po
:lines: 17-19
---------------------------
Translations with Transifex
---------------------------
Once you have created your translations, you can manage them using Transifex,
this is out side of the scope of this tutorial, but the Transifex documentation
provides tutorials on how to
`upload translations <http://docs.transifex.com/tutorials/content/#upload-files-and-download-the-translations>`_
and how to manage them using them
`command line client <http://docs.transifex.com/tutorials/client/>`_
---------------------
Compiling the catalog
---------------------
Now compile the PO files by running
python setup.py compile_catalog -l fr
This will generate an mo file containing your translations.
--------------------------
The ITranslation interface
--------------------------
Once you have created the translated strings, you will need to inform CKAN that
your extension is translated by implementing the ``ITranslation`` interface in
your extension. Edit your ``plugin.py`` to contain the following.
.. literalinclude:: ../../ckanext/example_itranslation/plugin.py
:emphasize-lines: 3, 6-7
Your done! To test your translated extension, make sure you add the extension to
your |development.ini| and run a ``paster serve`` and browse to
http://localhost:5000. You should find that switching to the ``fr`` locale in
the web interface should change the home page string to ``this is an itranslated
string``
Advanced ITranslation usage
^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are translating a CKAN extension that already exists, or you have
structured your extension differently from the default layout. You may
have to tell CKAN where to locate your translated files, you can do this by
having your plugin not inherit from the ``DefaultTranslation`` class and
implement the ``ITranslation`` interface yourself.
.. autosummary::
~ckan.plugins.interfaces.ITranslation.i18n_directory
~ckan.plugins.interfaces.ITranslation.i18n_locales
~ckan.plugins.interfaces.ITranslation.i18n_domain
13 changes: 1 addition & 12 deletions setup.py
Expand Up @@ -184,24 +184,13 @@
('templates/importer/**', 'ignore', None),
('templates/**.html', 'ckan', None),
('templates_legacy/**.html', 'ckan', None),
('ckan/templates/home/language.js', 'genshi', {
'template_class': 'genshi.template:TextTemplate'
}),
('templates/**.txt', 'genshi', {
'template_class': 'genshi.template:TextTemplate'
}),
('templates_legacy/**.txt', 'genshi', {
'template_class': 'genshi.template:TextTemplate'
}),
('public/**', 'ignore', None),
],
'ckanext': [
('**.py', 'python', None),
('**.js', 'javascript', None),
('**.html', 'ckan', None),
('multilingual/solr/*.txt', 'ignore', None),
('**.txt', 'genshi', {
'template_class': 'genshi.template:TextTemplate'
}),
]
},
entry_points=entry_points,
Expand Down

0 comments on commit 70751c8

Please sign in to comment.