Difference between revisions of "I18NSupport"
(8 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | + | {{ImplementedFeature}} | |
− | * '''Launchpad Entry''': | + | |
+ | * '''Launchpad Entry''': NovaSpec:i18n-support | ||
* '''Created''': 2010-10-22 | * '''Created''': 2010-10-22 | ||
* '''Contributors''': Koji Iida, Hisaharu Ishii | * '''Contributors''': Koji Iida, Hisaharu Ishii | ||
+ | |||
+ | http://etherpad.openstack.org/I18N-Support | ||
== Summary == | == Summary == | ||
− | * Internationalization support | + | * Internationalization support for logging messages |
* Support Japanese messages | * Support Japanese messages | ||
Line 14: | Line 17: | ||
== Rationale == | == Rationale == | ||
− | * Currently, messages are written only in English. | + | * Currently, log messages are written only in English. |
* I18N support is required for world-wide use of [[OpenStack]]. | * I18N support is required for world-wide use of [[OpenStack]]. | ||
Line 23: | Line 26: | ||
== Assumptions == | == Assumptions == | ||
− | * | + | * Server side logging messages only |
+ | * Use launchpad function https://help.launchpad.net/Translations to manage translations. | ||
== Design == | == Design == | ||
− | * Replace existing source code for message output to I18N style by using gettext module. | + | * Replace existing source code for log message output to I18N style by using gettext module. |
* Provide Japanese message catalog (.po) files. | * Provide Japanese message catalog (.po) files. | ||
== Implementation == | == Implementation == | ||
− | + | [[JayPipes]] has already begun the i18n process for the [http://launchpad.net/openstack-ci OpenStack-CI project]. He will provide assistance on automating the upload of the message catalog to Launchpad translations unit. | |
=== UI Changes === | === UI Changes === | ||
− | * | + | * No UI changes. |
=== Code Changes === | === Code Changes === | ||
+ | The followings are sample implementation step. | ||
+ | |||
+ | 1. Install the function '''_()''' in Python’s builtin namespace. | ||
+ | |||
+ | Example: nova/nova-scheduler: | ||
+ | |||
+ | <pre><nowiki> | ||
+ | import os | ||
+ | import sys | ||
+ | + import gettext | ||
+ | |||
+ | # If ../nova/__init__.py exists, add ../ to Python search path, so that | ||
+ | # it will override what happens to be installed in /usr/(local/)lib/python... | ||
+ | possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), | ||
+ | os.pardir, | ||
+ | os.pardir)) | ||
+ | if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): | ||
+ | sys.path.insert(0, possible_topdir) | ||
+ | |||
+ | from nova import service | ||
+ | from nova import twistd | ||
+ | |||
+ | + gettext.install('nova', './locale', unicode=1) | ||
+ | + | ||
+ | if __name__ == '__main__': | ||
+ | twistd.serve(__file__) | ||
+ | |||
+ | if __name__ == '__builtin__': | ||
+ | application = service.Service.create() | ||
+ | </nowiki></pre> | ||
+ | |||
+ | 2. Mark the strings which are used in logging function, by wrapping them in a call to the '''_()''' function. | ||
+ | |||
+ | Example: ./nova/service.py | ||
+ | |||
+ | <pre><nowiki> | ||
+ | if not periodic_interval: | ||
+ | periodic_interval = FLAGS.periodic_interval | ||
+ | - logging.warn("Starting %s node", topic) | ||
+ | + logging.warn(_("Starting %s node"), topic) | ||
+ | service_obj = cls(host, binary, topic, manager, | ||
+ | report_interval, periodic_interval) | ||
+ | </nowiki></pre> | ||
+ | |||
+ | |||
+ | 3. Generate .pot file. | ||
+ | |||
+ | <pre><nowiki> | ||
+ | $ pygettext -p locale -d nova nova/service.py | ||
+ | </nowiki></pre> | ||
+ | |||
+ | File ''locale/nova.pot'' generated. | ||
+ | |||
+ | 4. Copy ''nova.pot'' to ''nova.po''. | ||
+ | |||
+ | <pre><nowiki> | ||
+ | $ cp locale/nova.pot locale/ja/LC_MESSAGES/nova.po | ||
+ | </nowiki></pre> | ||
+ | |||
+ | 5. Translate ''locale/ja/LC_MESSAGES/nova.po'' to your language. | ||
+ | |||
+ | Example translation of ''locale/ja/LC_MESSAGES/nova.po'' to Japanese: | ||
+ | |||
+ | <pre><nowiki> | ||
+ | # SOME DESCRIPTIVE TITLE. | ||
+ | # Copyright (C) YEAR ORGANIZATION | ||
+ | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||
+ | # | ||
+ | msgid "" | ||
+ | msgstr "" | ||
+ | "Project-Id-Version: 0.1\n" | ||
+ | "POT-Creation-Date: 2010-10-27 17:50+JST\n" | ||
+ | "PO-Revision-Date: 2010-10-27 18:13+JST\n" | ||
+ | "Last-Translator: Someone <iida.koji@example.com>\n" | ||
+ | "Language-Team: LANGUAGE <LL@li.org>\n" | ||
+ | "MIME-Version: 1.0\n" | ||
+ | "Content-Type: text/plain; charset=UTF-8\n" | ||
+ | "Content-Transfer-Encoding: 8bit\n" | ||
+ | "Generated-By: pygettext.py 1.5\n" | ||
+ | |||
+ | |||
+ | #: nova/service.py:141 | ||
+ | msgid "Starting %s node" | ||
+ | msgstr "%s ノードを開始します" | ||
+ | |||
+ | </nowiki></pre> | ||
+ | |||
+ | |||
+ | 6. Generate .mo file. | ||
+ | |||
+ | <pre><nowiki> | ||
+ | $ msgfmt -o locale/ja/LC_MESSAGES/nova.mo locale/ja/LC_MESSAGES/nova.po | ||
+ | </nowiki></pre> | ||
+ | |||
+ | File ''./locale/ja/LC_MESSAGES/nova.mo'' is generated. | ||
+ | |||
+ | 7. Test nova-scheduler | ||
+ | |||
+ | <pre><nowiki> | ||
+ | $ LANGUAGE=ja_JP.UTF-8 ./bin/nova-scheduler --flagfile=./nova-manage.conf | ||
+ | </nowiki></pre> | ||
+ | |||
+ | |||
+ | Output messages: | ||
+ | |||
+ | <pre><nowiki> | ||
+ | ... | ||
+ | DEBUG:root:network_topic : network | ||
+ | WARNING:root:scheduler ノードを開始します | ||
+ | 2010-10-27 18:30:41+0900 [-] Log opened. | ||
+ | 2010-10-27 18:30:41+0900 [-] twistd 10.0.0 (/usr/bin/python 2.6.5) starting up. | ||
+ | 2010-10-27 18:30:41+0900 [-] reactor class: twisted.internet.selectreactor.SelectReactor. | ||
+ | INFO:root:backend <module 'nova.db.sqlalchemy.api' from '/home/iida/openstack/nova-2010.1-i18n/nova/db/sqlalchemy/api.pyc'> | ||
+ | 2010-10-27 18:30:41+0900 [-] (root): INFO backend <module 'nova.db.sqlalchemy.api' from '/home/iida/openstack/nova-2010.1-i18n/nova/db/sqlalchemy/api.pyc'> | ||
+ | </nowiki></pre> | ||
− | |||
=== Migration === | === Migration === |
Latest revision as of 04:29, 7 October 2013
- Launchpad Entry: NovaSpec:i18n-support
- Created: 2010-10-22
- Contributors: Koji Iida, Hisaharu Ishii
http://etherpad.openstack.org/I18N-Support
Contents
Summary
- Internationalization support for logging messages
- Support Japanese messages
Release Note
- TBD
Rationale
- Currently, log messages are written only in English.
- I18N support is required for world-wide use of OpenStack.
User stories
- TBD
Assumptions
- Server side logging messages only
- Use launchpad function https://help.launchpad.net/Translations to manage translations.
Design
- Replace existing source code for log message output to I18N style by using gettext module.
- Provide Japanese message catalog (.po) files.
Implementation
JayPipes has already begun the i18n process for the OpenStack-CI project. He will provide assistance on automating the upload of the message catalog to Launchpad translations unit.
UI Changes
- No UI changes.
Code Changes
The followings are sample implementation step.
1. Install the function _() in Python’s builtin namespace.
Example: nova/nova-scheduler:
import os import sys + import gettext # If ../nova/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) from nova import service from nova import twistd + gettext.install('nova', './locale', unicode=1) + if __name__ == '__main__': twistd.serve(__file__) if __name__ == '__builtin__': application = service.Service.create()
2. Mark the strings which are used in logging function, by wrapping them in a call to the _() function.
Example: ./nova/service.py
if not periodic_interval: periodic_interval = FLAGS.periodic_interval - logging.warn("Starting %s node", topic) + logging.warn(_("Starting %s node"), topic) service_obj = cls(host, binary, topic, manager, report_interval, periodic_interval)
3. Generate .pot file.
$ pygettext -p locale -d nova nova/service.py
File locale/nova.pot generated.
4. Copy nova.pot to nova.po.
$ cp locale/nova.pot locale/ja/LC_MESSAGES/nova.po
5. Translate locale/ja/LC_MESSAGES/nova.po to your language.
Example translation of locale/ja/LC_MESSAGES/nova.po to Japanese:
# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: 0.1\n" "POT-Creation-Date: 2010-10-27 17:50+JST\n" "PO-Revision-Date: 2010-10-27 18:13+JST\n" "Last-Translator: Someone <iida.koji@example.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" #: nova/service.py:141 msgid "Starting %s node" msgstr "%s ノードを開始します"
6. Generate .mo file.
$ msgfmt -o locale/ja/LC_MESSAGES/nova.mo locale/ja/LC_MESSAGES/nova.po
File ./locale/ja/LC_MESSAGES/nova.mo is generated.
7. Test nova-scheduler
$ LANGUAGE=ja_JP.UTF-8 ./bin/nova-scheduler --flagfile=./nova-manage.conf
Output messages:
... DEBUG:root:network_topic : network WARNING:root:scheduler ノードを開始します 2010-10-27 18:30:41+0900 [-] Log opened. 2010-10-27 18:30:41+0900 [-] twistd 10.0.0 (/usr/bin/python 2.6.5) starting up. 2010-10-27 18:30:41+0900 [-] reactor class: twisted.internet.selectreactor.SelectReactor. INFO:root:backend <module 'nova.db.sqlalchemy.api' from '/home/iida/openstack/nova-2010.1-i18n/nova/db/sqlalchemy/api.pyc'> 2010-10-27 18:30:41+0900 [-] (root): INFO backend <module 'nova.db.sqlalchemy.api' from '/home/iida/openstack/nova-2010.1-i18n/nova/db/sqlalchemy/api.pyc'>
Migration
- TBD
Test/Demo Plan
- TBD
Unresolved issues
- TBD
BoF agenda and discussion
- TBD