Merge lp:~jtv/launchpad/bug-662552-suggestive-potemplates into lp:launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Jeroen T. Vermeulen
Approved revision: no longer in the source branch.
Merged at revision: 11800
Proposed branch: lp:~jtv/launchpad/bug-662552-suggestive-potemplates
Merge into: lp:launchpad
Diff against target: 335 lines (+91/-20)
11 files modified
lib/lp/translations/doc/potmsgset.txt (+17/-1)
lib/lp/translations/model/potmsgset.py (+4/-17)
lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt (+8/-0)
lib/lp/translations/stories/standalone/xx-pofile-translate-dismiss-suggestions.txt (+10/-0)
lib/lp/translations/stories/standalone/xx-pofile-translate-legal-warning.txt (+8/-0)
lib/lp/translations/stories/standalone/xx-pofile-translate.txt (+8/-2)
lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt (+10/-0)
lib/lp/translations/stories/translationgroups/60-translation-suggestions.txt (+5/-0)
lib/lp/translations/tests/test_potmsgset.py (+7/-0)
lib/lp/translations/tests/test_suggestions.py (+6/-0)
lib/lp/translations/tests/test_translatablemessage.py (+8/-0)
To merge this branch: bzr merge lp:~jtv/launchpad/bug-662552-suggestive-potemplates
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+39354@code.launchpad.net

Commit message

Use suggestive-potemplates cache.

Description of the change

= Bug 662552 =

Translations has been getting a lot of timeouts lately. The page that probably makes users suffer most is POFile:+translate, which is slow mainly because it collects and displays "global suggestions." These are translations that have been entered or used for a given English string elsewhere in Launchpad. They're one of those features that make Launchpad Translations so useful.

Part of the work when gathering global suggestions is to find matching English strings and their translations. Another part is finding out whether their templates belong to projects or distributions that officially use Launchpad for translations, and whether they occur in enabled templates.

This second part is done identically several times for each message on a translation page, and does not change between page requests.

So I did the obvious, some time ago: create a little cache table that lists the templates that qualify as sources for global suggestions. This is the "suggestive templates cache." The cache is present and kept up to date on production, but not used yet. This branch changes that, simplifying the global-suggestions query to a narrower join with less sensitivity to locks. (And an XXX disappears in the process).

Most of the diff deals with tests that are affected by the extra caching. Generally all that's needed is to initialize the cache at the beginning of the test; I didn't want to add more sample data here that needs to be kept consistent and restored after every test.

The best way to test this is to run all Translations tests:
{{{
./bin/test -vvc lp.translations
}}}

To Q/A, check that the translation pages still show global suggestions, i.e. suggestions that are not directly related to the context that you're translating. For instance, until we land the Recife feature branch, suggestions made (but not used) in Ubuntu packages show up in their upstream projects only because of global suggestions.

When doing Q/A, it's important to ensure that the server's configuration has been updated to re-enable global suggestions. Oops levels should end up below what they were on 2010-10-26, and preferably less even than that. The easiest thing to observe is probably the difference in page timings between staging and production.

There's a bit of lint left, though none that I would seem to have caused. I'd be happy to clean it up during or after review. For now I did not want to pollute the diff.

Jeroen

To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/translations/doc/potmsgset.txt'
--- lib/lp/translations/doc/potmsgset.txt 2010-10-18 22:24:59 +0000
+++ lib/lp/translations/doc/potmsgset.txt 2010-10-26 10:49:44 +0000
@@ -701,10 +701,11 @@
701On the other, we have a translation template for the evolution package in701On the other, we have a translation template for the evolution package in
702Ubuntu Hoary distribution.702Ubuntu Hoary distribution.
703703
704 >>> templateset = getUtility(IPOTemplateSet)
704 >>> ubuntu = getUtility(IDistributionSet)['ubuntu']705 >>> ubuntu = getUtility(IDistributionSet)['ubuntu']
705 >>> ubuntu_hoary = ubuntu.getSeries('hoary')706 >>> ubuntu_hoary = ubuntu.getSeries('hoary')
706 >>> evo_hoary_package = ubuntu_hoary.getSourcePackage('evolution')707 >>> evo_hoary_package = ubuntu_hoary.getSourcePackage('evolution')
707 >>> evo_distro_template = getUtility(IPOTemplateSet).getSubset(708 >>> evo_distro_template = templateset.getSubset(
708 ... sourcepackagename=evo_hoary_package.sourcepackagename,709 ... sourcepackagename=evo_hoary_package.sourcepackagename,
709 ... distroseries=ubuntu_hoary).getPOTemplateByName('evolution-2.2')710 ... distroseries=ubuntu_hoary).getPOTemplateByName('evolution-2.2')
710 >>> print evo_distro_template.title711 >>> print evo_distro_template.title
@@ -724,6 +725,16 @@
724 >>> evo_distro_template.iscurrent725 >>> evo_distro_template.iscurrent
725 True726 True
726727
728The "suggestive templates" cache is up to date.
729
730 >>> def refresh_suggestive_templates_cache():
731 ... """Update the `SuggestivePOTemplate` cache."""
732 ... templateset.wipeSuggestivePOTemplatesCache()
733 ... templateset.populateSuggestivePOTemplatesCache()
734
735 >>> refresh_suggestive_templates_cache()
736 >>> transaction.commit()
737
727We have the same message in both templates but with different738We have the same message in both templates but with different
728translations in Spanish:739translations in Spanish:
729740
@@ -765,6 +776,7 @@
765are not available as suggestions anymore:776are not available as suggestions anymore:
766777
767 >>> evo_distro_template.iscurrent = False778 >>> evo_distro_template.iscurrent = False
779 >>> refresh_suggestive_templates_cache()
768 >>> transaction.commit()780 >>> transaction.commit()
769 >>> suggestions = (781 >>> suggestions = (
770 ... evo_product_message.getExternallyUsedTranslationMessages(spanish))782 ... evo_product_message.getExternallyUsedTranslationMessages(spanish))
@@ -790,6 +802,7 @@
790And products not using translations officially have the same behaviour.802And products not using translations officially have the same behaviour.
791803
792 >>> evolution.translations_usage = ServiceUsage.NOT_APPLICABLE804 >>> evolution.translations_usage = ServiceUsage.NOT_APPLICABLE
805 >>> refresh_suggestive_templates_cache()
793 >>> transaction.commit()806 >>> transaction.commit()
794 >>> suggestions = evo_distro_message.getExternallyUsedTranslationMessages(807 >>> suggestions = evo_distro_message.getExternallyUsedTranslationMessages(
795 ... spanish)808 ... spanish)
@@ -800,6 +813,7 @@
800813
801 >>> ubuntu.translations_usage = ServiceUsage.LAUNCHPAD814 >>> ubuntu.translations_usage = ServiceUsage.LAUNCHPAD
802 >>> evolution.translations_usage = ServiceUsage.LAUNCHPAD815 >>> evolution.translations_usage = ServiceUsage.LAUNCHPAD
816 >>> refresh_suggestive_templates_cache()
803 >>> transaction.commit()817 >>> transaction.commit()
804818
805819
@@ -885,6 +899,7 @@
885we get no suggestions.899we get no suggestions.
886900
887 >>> potmsgset_translated.potemplate.iscurrent = False901 >>> potmsgset_translated.potemplate.iscurrent = False
902 >>> refresh_suggestive_templates_cache()
888 >>> transaction.commit()903 >>> transaction.commit()
889904
890 >>> wiki_submissions = (905 >>> wiki_submissions = (
@@ -900,6 +915,7 @@
900 # suggestions just due to the change to the official_rosetta flag.915 # suggestions just due to the change to the official_rosetta flag.
901 >>> potmsgset_translated.potemplate.iscurrent = True916 >>> potmsgset_translated.potemplate.iscurrent = True
902 >>> ubuntu.translations_usage = ServiceUsage.NOT_APPLICABLE917 >>> ubuntu.translations_usage = ServiceUsage.NOT_APPLICABLE
918 >>> refresh_suggestive_templates_cache()
903 >>> transaction.commit()919 >>> transaction.commit()
904920
905 >>> wiki_submissions = (921 >>> wiki_submissions = (
906922
=== modified file 'lib/lp/translations/model/potmsgset.py'
--- lib/lp/translations/model/potmsgset.py 2010-09-07 15:26:49 +0000
+++ lib/lp/translations/model/potmsgset.py 2010-10-26 10:49:44 +0000
@@ -361,31 +361,18 @@
361 query = ["(NOT %s)" % in_use_clause]361 query = ["(NOT %s)" % in_use_clause]
362 query.append('TranslationMessage.language = %s' % sqlvalues(language))362 query.append('TranslationMessage.language = %s' % sqlvalues(language))
363363
364 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
365 # happened for the usage enums, this sql needs to be updated
366 # to check for the translations_usage, not official_rosetta.
367 query.append('''364 query.append('''
368 potmsgset IN (365 potmsgset IN (
369 SELECT POTMsgSet.id366 SELECT POTMsgSet.id
370 FROM POTMsgSet367 FROM POTMsgSet
371 JOIN TranslationTemplateItem ON368 JOIN TranslationTemplateItem ON
372 TranslationTemplateItem.potmsgset = POTMsgSet.id369 TranslationTemplateItem.potmsgset = POTMsgSet.id
373 JOIN POTemplate ON370 JOIN SuggestivePOTemplate ON
374 TranslationTemplateItem.potemplate = POTemplate.id371 TranslationTemplateItem.potemplate =
375 LEFT JOIN ProductSeries ON372 SuggestivePOTemplate.potemplate
376 POTemplate.productseries = ProductSeries.id
377 LEFT JOIN Product ON
378 ProductSeries.product = Product.id
379 LEFT JOIN DistroSeries ON
380 POTemplate.distroseries = DistroSeries.id
381 LEFT JOIN Distribution ON
382 DistroSeries.distribution = Distribution.id
383 WHERE373 WHERE
384 POTMsgSet.id <> %s AND374 POTMsgSet.id <> %s AND
385 msgid_singular = %s AND375 msgid_singular = %s
386 POTemplate.iscurrent AND
387 (Product.official_rosetta OR
388 Distribution.official_rosetta)
389 )''' % sqlvalues(self, self.msgid_singular))376 )''' % sqlvalues(self, self.msgid_singular))
390377
391 # Subquery to find the ids of TranslationMessages that are378 # Subquery to find the ids of TranslationMessages that are
392379
=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt 2009-09-15 18:53:26 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt 2010-10-26 10:49:44 +0000
@@ -4,7 +4,15 @@
4form will suggest translations from this alternative language as well as those4form will suggest translations from this alternative language as well as those
5in the form's main language.5in the form's main language.
66
7 >>> from zope.component import getUtility
7 >>> from canonical.launchpad.testing.pages import extract_url_parameter8 >>> from canonical.launchpad.testing.pages import extract_url_parameter
9 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
10
11 >>> login(ANONYMOUS)
12 >>> utility = getUtility(IPOTemplateSet)
13 >>> dummy = utility.populateSuggestivePOTemplatesCache()
14 >>> logout()
15
8 >>> def get_alternative_languages_widget(browser):16 >>> def get_alternative_languages_widget(browser):
9 ... """Check and return alternative languages widget offered on page.17 ... """Check and return alternative languages widget offered on page.
10 ...18 ...
1119
=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-dismiss-suggestions.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-translate-dismiss-suggestions.txt 2009-10-29 17:46:00 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-translate-dismiss-suggestions.txt 2010-10-26 10:49:44 +0000
@@ -4,6 +4,16 @@
4translation of a message. If the current translation is good enough, new4translation of a message. If the current translation is good enough, new
5suggestions can be dismissed to keep them off the page.5suggestions can be dismissed to keep them off the page.
66
7 >>> from zope.component import getUtility
8 >>> from canonical.launchpad.testing.pages import extract_url_parameter
9 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
10
11 >>> login(ANONYMOUS)
12 >>> utility = getUtility(IPOTemplateSet)
13 >>> dummy = utility.populateSuggestivePOTemplatesCache()
14 >>> logout()
15
16
7First the admin (or anybody with edit rights) adds a translation.17First the admin (or anybody with edit rights) adds a translation.
818
9 >>> admin_browser.open('http://translations.launchpad.dev/alsa-utils'19 >>> admin_browser.open('http://translations.launchpad.dev/alsa-utils'
1020
=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-legal-warning.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-translate-legal-warning.txt 2010-03-18 18:55:02 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-translate-legal-warning.txt 2010-10-26 10:49:44 +0000
@@ -10,6 +10,14 @@
10On a Hoary Evolution sourcepackage, we can see a suggestion coming10On a Hoary Evolution sourcepackage, we can see a suggestion coming
11from the upstream project.11from the upstream project.
1212
13 >>> from zope.component import getUtility
14 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
15
16 >>> login(ANONYMOUS)
17 >>> utility = getUtility(IPOTemplateSet)
18 >>> dummy = utility.populateSuggestivePOTemplatesCache()
19 >>> logout()
20
13 >>> browser = setupBrowser(auth='Basic carlos@canonical.com:test')21 >>> browser = setupBrowser(auth='Basic carlos@canonical.com:test')
14 >>> browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/es/3/+translate')22 >>> browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/es/3/+translate')
15 >>> print extract_text(find_tag_by_id(23 >>> print extract_text(find_tag_by_id(
1624
=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-translate.txt 2010-10-05 00:08:16 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-translate.txt 2010-10-26 10:49:44 +0000
@@ -1,5 +1,3 @@
1
2
3Translation Submissions1Translation Submissions
4=======================2=======================
53
@@ -17,6 +15,14 @@
17xx-pofile-translate-newlines-check.txt15xx-pofile-translate-newlines-check.txt
18xx-pofile-translate-performance.txt16xx-pofile-translate-performance.txt
1917
18 >>> from zope.component import getUtility
19 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
20
21 >>> login(ANONYMOUS)
22 >>> utility = getUtility(IPOTemplateSet)
23 >>> dummy = utility.populateSuggestivePOTemplatesCache()
24 >>> logout()
25
2026
21Anonymous access27Anonymous access
22----------------28----------------
2329
=== modified file 'lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt'
--- lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt 2010-10-18 22:24:59 +0000
+++ lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt 2010-10-26 10:49:44 +0000
@@ -4,6 +4,16 @@
4Here we are going to check the basic behaviour of the translation form4Here we are going to check the basic behaviour of the translation form
5when we render just one message with all available information for it.5when we render just one message with all available information for it.
66
7The suggestive-templates cache needs to be up to date.
8
9 >>> from zope.component import getUtility
10 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
11
12 >>> login(ANONYMOUS)
13 >>> utility = getUtility(IPOTemplateSet)
14 >>> dummy = utility.populateSuggestivePOTemplatesCache()
15 >>> logout()
16
717
8Getting there18Getting there
9-------------19-------------
1020
=== modified file 'lib/lp/translations/stories/translationgroups/60-translation-suggestions.txt'
--- lib/lp/translations/stories/translationgroups/60-translation-suggestions.txt 2010-10-18 22:24:59 +0000
+++ lib/lp/translations/stories/translationgroups/60-translation-suggestions.txt 2010-10-26 10:49:44 +0000
@@ -16,6 +16,7 @@
16 >>> from lp.registry.interfaces.distribution import IDistributionSet16 >>> from lp.registry.interfaces.distribution import IDistributionSet
17 >>> from lp.registry.interfaces.person import IPersonSet17 >>> from lp.registry.interfaces.person import IPersonSet
18 >>> from lp.services.worlddata.interfaces.language import ILanguageSet18 >>> from lp.services.worlddata.interfaces.language import ILanguageSet
19 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
19 >>> from lp.translations.interfaces.translator import ITranslatorSet20 >>> from lp.translations.interfaces.translator import ITranslatorSet
2021
21 >>> login('foo.bar@canonical.com')22 >>> login('foo.bar@canonical.com')
@@ -25,6 +26,10 @@
25 >>> ubuntu_spanish_reviewer = getUtility(ITranslatorSet).new(26 >>> ubuntu_spanish_reviewer = getUtility(ITranslatorSet).new(
26 ... translationgroup=ubuntu.translationgroup, language=spanish,27 ... translationgroup=ubuntu.translationgroup, language=spanish,
27 ... translator=carlos)28 ... translator=carlos)
29
30 >>> utility = getUtility(IPOTemplateSet)
31 >>> dummy = utility.populateSuggestivePOTemplatesCache()
32
28 >>> logout()33 >>> logout()
2934
30Let's add a new suggestion as a person without privileges.35Let's add a new suggestion as a person without privileges.
3136
=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
--- lib/lp/translations/tests/test_potmsgset.py 2010-10-04 19:50:45 +0000
+++ lib/lp/translations/tests/test_potmsgset.py 2010-10-26 10:49:44 +0000
@@ -25,6 +25,7 @@
25from lp.registry.interfaces.product import IProductSet25from lp.registry.interfaces.product import IProductSet
26from lp.services.worlddata.interfaces.language import ILanguageSet26from lp.services.worlddata.interfaces.language import ILanguageSet
27from lp.testing import TestCaseWithFactory27from lp.testing import TestCaseWithFactory
28from lp.translations.interfaces.potemplate import IPOTemplateSet
28from lp.translations.interfaces.potmsgset import (29from lp.translations.interfaces.potmsgset import (
29 POTMsgSetInIncompatibleTemplatesError,30 POTMsgSetInIncompatibleTemplatesError,
30 TranslationCreditsType,31 TranslationCreditsType,
@@ -64,6 +65,10 @@
64 self.potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate)65 self.potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate)
65 self.potmsgset.setSequence(self.devel_potemplate, 1)66 self.potmsgset.setSequence(self.devel_potemplate, 1)
6667
68 def _refreshSuggestiveTemplatesCache(self):
69 """Refresh the `SuggestivePOTemplate` cache."""
70 getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache()
71
67 def test_TranslationTemplateItem(self):72 def test_TranslationTemplateItem(self):
68 self.potmsgset.setSequence(self.stable_potemplate, 1)73 self.potmsgset.setSequence(self.stable_potemplate, 1)
6974
@@ -333,6 +338,7 @@
333 external_potmsgset.setSequence(external_template, 1)338 external_potmsgset.setSequence(external_template, 1)
334 external_pofile = self.factory.makePOFile('sr', external_template)339 external_pofile = self.factory.makePOFile('sr', external_template)
335 serbian = external_pofile.language340 serbian = external_pofile.language
341 self._refreshSuggestiveTemplatesCache()
336342
337 transaction.commit()343 transaction.commit()
338344
@@ -393,6 +399,7 @@
393 external_potmsgset.setSequence(external_template, 1)399 external_potmsgset.setSequence(external_template, 1)
394 external_pofile = self.factory.makePOFile('sr', external_template)400 external_pofile = self.factory.makePOFile('sr', external_template)
395 serbian = external_pofile.language401 serbian = external_pofile.language
402 self._refreshSuggestiveTemplatesCache()
396403
397 transaction.commit()404 transaction.commit()
398405
399406
=== modified file 'lib/lp/translations/tests/test_suggestions.py'
--- lib/lp/translations/tests/test_suggestions.py 2010-10-04 19:50:45 +0000
+++ lib/lp/translations/tests/test_suggestions.py 2010-10-26 10:49:44 +0000
@@ -20,6 +20,7 @@
20from lp.app.enums import ServiceUsage20from lp.app.enums import ServiceUsage
21from lp.services.worlddata.interfaces.language import ILanguageSet21from lp.services.worlddata.interfaces.language import ILanguageSet
22from lp.testing.factory import LaunchpadObjectFactory22from lp.testing.factory import LaunchpadObjectFactory
23from lp.translations.interfaces.potemplate import IPOTemplateSet
23from lp.translations.interfaces.translationmessage import (24from lp.translations.interfaces.translationmessage import (
24 TranslationValidationStatus,25 TranslationValidationStatus,
25 )26 )
@@ -50,6 +51,11 @@
50 self.nl = getUtility(ILanguageSet).getLanguageByCode('nl')51 self.nl = getUtility(ILanguageSet).getLanguageByCode('nl')
51 self.foo_nl = factory.makePOFile('nl', potemplate=self.foo_template)52 self.foo_nl = factory.makePOFile('nl', potemplate=self.foo_template)
52 self.bar_nl = factory.makePOFile('nl', potemplate=self.bar_template)53 self.bar_nl = factory.makePOFile('nl', potemplate=self.bar_template)
54 self._refreshSuggestiveTemplatesCache()
55
56 def _refreshSuggestiveTemplatesCache(self):
57 """Update the `SuggestivePOTemplate` cache."""
58 getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache()
5359
54 def test_NoSuggestions(self):60 def test_NoSuggestions(self):
55 # When a msgid string is unique and nobody has submitted any61 # When a msgid string is unique and nobody has submitted any
5662
=== modified file 'lib/lp/translations/tests/test_translatablemessage.py'
--- lib/lp/translations/tests/test_translatablemessage.py 2010-10-04 19:50:45 +0000
+++ lib/lp/translations/tests/test_translatablemessage.py 2010-10-26 10:49:44 +0000
@@ -13,10 +13,12 @@
1313
14import pytz14import pytz
15import transaction15import transaction
16from zope.component import getUtility
1617
17from canonical.testing.layers import ZopelessDatabaseLayer18from canonical.testing.layers import ZopelessDatabaseLayer
18from lp.app.enums import ServiceUsage19from lp.app.enums import ServiceUsage
19from lp.testing import TestCaseWithFactory20from lp.testing import TestCaseWithFactory
21from lp.translations.interfaces.potemplate import IPOTemplateSet
20from lp.translations.model.translatablemessage import TranslatableMessage22from lp.translations.model.translatablemessage import TranslatableMessage
2123
2224
@@ -153,6 +155,12 @@
153155
154 self.message = TranslatableMessage(self.potmsgset, self.pofile)156 self.message = TranslatableMessage(self.potmsgset, self.pofile)
155157
158 self._refreshSuggestiveTemplatesCache()
159
160 def _refreshSuggestiveTemplatesCache(self):
161 """Refresh the `SuggestivePOTemplate` cache."""
162 getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache()
163
156 def test_getExternalTranslations(self):164 def test_getExternalTranslations(self):
157 transaction.commit()165 transaction.commit()
158 externals = self.message.getExternalTranslations()166 externals = self.message.getExternalTranslations()