forked from openstack/horizon
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Angular translation via babel (singular only)
An approach to i18n for Angular HTML templates using babel. This patch allows only singular translation. Plurals and context will be addressed in subsequent patches. Based on Thai Tran's work at https://review.openstack.org/#/c/187321 This patch implements a custom extractor in horizon/utils/babel_extract_angular.py. pybabel really wants this to be a package installed into site-packages. I have not done this so as to avoid introducing a dependency on another change to global requirements just yet. I will upload a package to pypi in parallel so that we can start using it in the future. For now, I have had to modify tools/with_venv.sh to add horizon to the PYTHONPATH. This is less than ideal but seemed to be the least worst option. Steps to verify that it works: 1. Create a new html file in horizon/static or openstack_dashboard/static 2. Add something like <div translate>hello world!</div> to the html To test interpolation add something like: <div translate>hello {$name$}!</div> 3. Run ./run_tests.sh --makemessages 4. Inspect your djangojs.po file, it should be there. The following steps are optional: 5. Run ./run_tests.sh --pseudo de 6. Run ./run_tests.sh --compilemessages 7. Go to http://localhost:8000/settings 8. Change Language to Deutsch 9. Go to http://localhost:8000/i18n/js/horizon+openstack_dashboard 10. Your translated text should be there as well. Note: There are now unit tests as well. Partially-Implements: blueprint angular-translate-makemessages Depends on: If4352aba01ce0ca6337f590c0689d8fe9f0867c8 Change-Id: I26d4fef8646d5f038918cd3376dbbdbef37eb603
- Loading branch information
Showing
5 changed files
with
263 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,14 @@ | ||
[extractors] | ||
# We use a custom extractor to find translatable strings in AngularJS | ||
# templates. The extractor is included in horizon.utils for now. | ||
# See http://babel.pocoo.org/docs/messages/#referencing-extraction-methods for | ||
# details on how this works. | ||
angular = horizon.utils.babel_extract_angular:extract_angular | ||
|
||
[javascript: **.js] | ||
|
||
# We need to look into all static folders for HTML files. | ||
# The **/static ensures that we also search within | ||
# /openstack_dashboard/dashboards/XYZ/static which will ensure | ||
# that plugins are also translated. | ||
[angular: **/static/**.html] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Copyright 2015, Rackspace, US, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
try: | ||
from html.parser import HTMLParser | ||
except ImportError: | ||
from HTMLParser import HTMLParser | ||
|
||
import re | ||
|
||
|
||
class AngularGettextHTMLParser(HTMLParser): | ||
"""Parse HTML to find translate directives. | ||
Note: This will not cope with nested tags (which I don't think make any | ||
sense) | ||
""" | ||
|
||
def __init__(self): | ||
try: | ||
super(self.__class__, self).__init__() | ||
except TypeError: | ||
HTMLParser.__init__(self) | ||
|
||
self.in_translate = False | ||
self.data = '' | ||
self.strings = [] | ||
|
||
def handle_starttag(self, tag, attrs): | ||
if tag == 'translate' or \ | ||
(attrs and 'translate' in [attr[0] for attr in attrs]): | ||
self.in_translate = True | ||
self.line = self.getpos()[0] | ||
|
||
def handle_data(self, data): | ||
if self.in_translate: | ||
self.data += data | ||
|
||
def handle_endtag(self, tag): | ||
if self.in_translate: | ||
self.strings.append( | ||
(self.line, u'gettext', self.interpolate(), []) | ||
) | ||
self.in_translate = False | ||
self.data = '' | ||
|
||
def interpolate(self): | ||
interpolation_regex = r"""{\$([\w\."'\]\[\(\)]+)\$}""" | ||
return re.sub(interpolation_regex, r'%(\1)', self.data) | ||
|
||
|
||
def extract_angular(fileobj, keywords, comment_tags, options): | ||
"""Extract messages from angular template (HTML) files that use the | ||
angular-gettext translate directive as per | ||
https://angular-gettext.rocketeer.be/ . | ||
:param fileobj: the file-like object the messages should be extracted | ||
from | ||
:param keywords: This is a standard parameter so it isaccepted but ignored. | ||
:param comment_tags: This is a standard parameter so it is accepted but | ||
ignored. | ||
:param options: Another standard parameter that is accepted but ignored. | ||
:return: an iterator over ``(lineno, funcname, message, comments)`` | ||
tuples | ||
:rtype: ``iterator`` | ||
This particular extractor is quite simple because it is intended to only | ||
deal with angular templates which do not need comments, or the more | ||
complicated forms of translations. | ||
A later version will address pluralization. | ||
""" | ||
|
||
parser = AngularGettextHTMLParser() | ||
|
||
for line in fileobj: | ||
parser.feed(line) | ||
|
||
for string in parser.strings: | ||
yield(string) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters