← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:stormify-translationmessage into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:stormify-translationmessage into launchpad:master.

Commit message:
Convert TranslationMessage to Storm

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/446348
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-translationmessage into launchpad:master.
diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
index 57dc83a..4c5900b 100644
--- a/lib/lp/scripts/garbo.py
+++ b/lib/lp/scripts/garbo.py
@@ -1624,7 +1624,7 @@ class UnusedPOTMsgSetPruner(TunableLoop):
         # Remove related TranslationMessages.
         related_translation_messages = store.find(
             TranslationMessage,
-            In(TranslationMessage.potmsgsetID, msgset_ids_to_remove),
+            In(TranslationMessage.potmsgset_id, msgset_ids_to_remove),
         )
         related_translation_messages.remove()
         store.find(POTMsgSet, In(POTMsgSet.id, msgset_ids_to_remove)).remove()
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index ab55f4b..8764715 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -4231,7 +4231,7 @@ class LaunchpadObjectFactory(ObjectFactory):
                 translation_message
             )
             naked_translation_message.date_created = date_created
-            naked_translation_message.sync()
+            IStore(naked_translation_message).flush()
         return ProxyFactory(translation_message)
 
     def makeCurrentTranslationMessage(
diff --git a/lib/lp/translations/browser/tests/translationmessage-views.rst b/lib/lp/translations/browser/tests/translationmessage-views.rst
index 4b6d758..3c4da4a 100644
--- a/lib/lp/translations/browser/tests/translationmessage-views.rst
+++ b/lib/lp/translations/browser/tests/translationmessage-views.rst
@@ -4,6 +4,7 @@ TranslationMessage View
 On this section, we are going to test the view class for an
 ITranslationMessage object.
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.services.database.sqlbase import flush_database_updates
     >>> from lp.translations.model.pofile import POFile
     >>> from lp.translations.model.translationmessage import (
@@ -24,7 +25,9 @@ No plural forms
 We are going to see what happens if we get an entry for a language
 without the plural form information.
 
-    >>> translationmessage = TranslationMessage.get(1)
+    >>> translationmessage = IStore(TranslationMessage).get(
+    ...     TranslationMessage, 1
+    ... )
     >>> pofile = POFile.get(1)
     >>> language_tlh = getUtility(ILanguageSet).getLanguageByCode("tlh")
     >>> pofile_tlh = pofile.potemplate.getPlaceholderPOFile(language_tlh)
diff --git a/lib/lp/translations/doc/potmsgset.rst b/lib/lp/translations/doc/potmsgset.rst
index 8fa016c..400c533 100644
--- a/lib/lp/translations/doc/potmsgset.rst
+++ b/lib/lp/translations/doc/potmsgset.rst
@@ -11,6 +11,7 @@ standby database.
 We need to get a POTMsgSet object to perform this test.
 
     >>> from zope.component import getUtility
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.translations.model.translationmessage import (
     ...     TranslationMessage,
     ... )
@@ -284,7 +285,9 @@ isTranslationNewerThan
 This method tells us whether the active translation was reviewed after
 the given timestamp.
 
-    >>> translationmessage = TranslationMessage.get(2)
+    >>> translationmessage = IStore(TranslationMessage).get(
+    ...     TranslationMessage, 2
+    ... )
     >>> potmsgset = translationmessage.potmsgset
     >>> from lp.translations.model.pofile import POFile
     >>> pofile = POFile.get(1)
diff --git a/lib/lp/translations/doc/translationmessage-destroy.rst b/lib/lp/translations/doc/translationmessage-destroy.rst
index 0841544..6c79ec3 100644
--- a/lib/lp/translations/doc/translationmessage-destroy.rst
+++ b/lib/lp/translations/doc/translationmessage-destroy.rst
@@ -9,6 +9,7 @@ but we test it here to be sure it appears in our public interface.
 
 We will need extra permissions to use this method.
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.translations.model.translationmessage import (
     ...     TranslationMessage,
     ... )
@@ -17,15 +18,16 @@ We will need extra permissions to use this method.
 
 Select an existing ITranslationMessage and try to remove it.
 
-    >>> translationmessage = TranslationMessage.get(1)
+    >>> translationmessage = IStore(TranslationMessage).get(
+    ...     TranslationMessage, 1
+    ... )
     >>> translationmessage.destroySelf()
 
 It should not exist now.
 
-    >>> translationmessage = TranslationMessage.get(1)
-    Traceback (most recent call last):
-    ...
-    storm.sqlobject.SQLObjectNotFound: ...
+    >>> translationmessage = IStore(TranslationMessage).get(
+    ...     TranslationMessage, 1
+    ... )
 
 
 POFileTranslator update on remove
@@ -37,7 +39,6 @@ translation, we get two POFileTranslator records for each of the POFiles.
     # We need to be able to create persons and projects so let's just use
     # a global 'postgres' permission which allows everything.
     >>> switch_dbuser("postgres")
-    >>> from lp.services.database.interfaces import IStore
     >>> from lp.app.enums import ServiceUsage
     >>> from lp.testing.factory import LaunchpadObjectFactory
     >>> from lp.translations.model.pofiletranslator import POFileTranslator
diff --git a/lib/lp/translations/model/currenttranslations.py b/lib/lp/translations/model/currenttranslations.py
index 8bb108b..84688a0 100644
--- a/lib/lp/translations/model/currenttranslations.py
+++ b/lib/lp/translations/model/currenttranslations.py
@@ -59,8 +59,10 @@ class CurrentTranslations:
             raise ValueError("sides must not be empty")
 
         clauses = [
-            TranslationMessage.potmsgsetID.is_in(s.id for s in potmsgsets),
-            TranslationMessage.languageID.is_in(lang.id for lang in languages),
+            TranslationMessage.potmsgset_id.is_in(s.id for s in potmsgsets),
+            TranslationMessage.language_id.is_in(
+                lang.id for lang in languages
+            ),
         ]
 
         side_clauses = []
@@ -78,7 +80,7 @@ class CurrentTranslations:
             clauses.append(
                 Or(
                     TranslationMessage.potemplate == None,
-                    TranslationMessage.potemplateID.is_in(
+                    TranslationMessage.potemplate_id.is_in(
                         t.id for t in potemplates if t is not None
                     ),
                 )
@@ -92,9 +94,9 @@ class CurrentTranslations:
                 if not trait.getFlag(message):
                     continue
                 key = CurrentTranslationKey(
-                    message.potmsgsetID,
-                    message.potemplateID,
-                    message.languageID,
+                    message.potmsgset_id,
+                    message.potemplate_id,
+                    message.language_id,
                     side,
                 )
                 messages_by_key[key] = message
diff --git a/lib/lp/translations/model/pofile.py b/lib/lp/translations/model/pofile.py
index 6539f65..232927a 100644
--- a/lib/lp/translations/model/pofile.py
+++ b/lib/lp/translations/model/pofile.py
@@ -154,7 +154,7 @@ class POFileMixIn(RosettaStats):
                         tm_ids,
                         Join(
                             TranslationTemplateItem,
-                            tm_ids.potmsgsetID
+                            tm_ids.potmsgset_id
                             == TranslationTemplateItem.potmsgset_id,
                         ),
                     ),
@@ -162,7 +162,7 @@ class POFileMixIn(RosettaStats):
                         TranslationTemplateItem.potemplate
                         == pofile.potemplate,
                         TranslationTemplateItem.sequence > 0,
-                        tm_ids.languageID == pofile.languageID,
+                        tm_ids.language_id == pofile.languageID,
                     ),
                     distinct=True,
                 )
@@ -175,7 +175,7 @@ class POFileMixIn(RosettaStats):
             ),
         ]
         return Select(
-            TranslationMessage.potmsgsetID,
+            TranslationMessage.potmsgset_id,
             tables=(
                 TranslationMessage,
                 Join(
@@ -386,11 +386,11 @@ class POFile(SQLBase, POFileMixIn):
     def getTranslationMessages(self, condition=None):
         """See `IPOFile`."""
         applicable_template = Coalesce(
-            TranslationMessage.potemplateID, self.potemplate.id
+            TranslationMessage.potemplate_id, self.potemplate.id
         )
         clauses = [
             TranslationTemplateItem.potmsgset_id
-            == TranslationMessage.potmsgsetID,
+            == TranslationMessage.potmsgset_id,
             TranslationTemplateItem.potemplate == self.potemplate,
             TranslationMessage.language == self.language,
             applicable_template == self.potemplate.id,
@@ -536,7 +536,7 @@ class POFile(SQLBase, POFileMixIn):
             TranslationTemplateItem.potemplate == self.potemplate,
             (
                 TranslationTemplateItem.potmsgset_id
-                == TranslationMessage.potmsgsetID
+                == TranslationMessage.potmsgset_id
             ),
             TranslationMessage.language == self.language,
         ]
@@ -580,23 +580,23 @@ class POFile(SQLBase, POFileMixIn):
         #  * (it's diverged AND non-empty)
         #     OR (it's shared AND non-empty AND no diverged one exists)
         diverged_translation_clause = (
-            TranslationMessage.potemplateID == self.potemplate.id,
+            TranslationMessage.potemplate_id == self.potemplate.id,
         )
 
         Diverged = ClassAlias(TranslationMessage, "Diverged")
         shared_translation_clause = And(
-            TranslationMessage.potemplateID == None,
+            TranslationMessage.potemplate_id == None,
             Not(
                 Exists(
                     Select(
                         1,
                         tables=[Diverged],
                         where=And(
-                            Diverged.potmsgsetID
-                            == TranslationMessage.potmsgsetID,
-                            Diverged.languageID == self.language.id,
+                            Diverged.potmsgset_id
+                            == TranslationMessage.potmsgset_id,
+                            Diverged.language_id == self.language.id,
                             getattr(Diverged, flag_name),
-                            Diverged.potemplateID == self.potemplate.id,
+                            Diverged.potemplate_id == self.potemplate.id,
                         ),
                     )
                 )
@@ -674,10 +674,10 @@ class POFile(SQLBase, POFileMixIn):
             Coalesce(Diverged.date_reviewed, Diverged.date_created),
             tables=[Diverged],
             where=And(
-                Diverged.potmsgsetID == POTMsgSet.id,
-                Diverged.languageID == self.language.id,
+                Diverged.potmsgset_id == POTMsgSet.id,
+                Diverged.language_id == self.language.id,
                 getattr(Diverged, flag_name),
-                Diverged.potemplateID == self.potemplate.id,
+                Diverged.potemplate_id == self.potemplate.id,
             ),
         )
 
@@ -686,10 +686,10 @@ class POFile(SQLBase, POFileMixIn):
             Coalesce(Shared.date_reviewed, Shared.date_created),
             tables=[Shared],
             where=And(
-                Shared.potmsgsetID == POTMsgSet.id,
-                Shared.languageID == self.language.id,
+                Shared.potmsgset_id == POTMsgSet.id,
+                Shared.language_id == self.language.id,
                 getattr(Shared, flag_name),
-                Shared.potemplateID == None,
+                Shared.potemplate_id == None,
             ),
         )
 
@@ -708,7 +708,7 @@ class POFile(SQLBase, POFileMixIn):
         query = And(
             POTMsgSet.id.is_in(
                 Select(
-                    TranslationMessage.potmsgsetID,
+                    TranslationMessage.potmsgset_id,
                     tables=[
                         TranslationMessage,
                         TranslationTemplateItem,
@@ -753,22 +753,23 @@ class POFile(SQLBase, POFileMixIn):
                     tables=[Diverged],
                     where=And(
                         Diverged.id != Imported.id,
-                        Diverged.potmsgsetID == TranslationMessage.potmsgsetID,
-                        Diverged.languageID == self.language.id,
+                        Diverged.potmsgset_id
+                        == TranslationMessage.potmsgset_id,
+                        Diverged.language_id == self.language.id,
                         getattr(Diverged, other_side_flag_name),
-                        Diverged.potemplateID == self.potemplate.id,
+                        Diverged.potemplate_id == self.potemplate.id,
                     ),
                 )
             )
         )
         imported_clauses = [
             Imported.id != TranslationMessage.id,
-            Imported.potmsgsetID == POTMsgSet.id,
-            Imported.languageID == self.language.id,
+            Imported.potmsgset_id == POTMsgSet.id,
+            Imported.language_id == self.language.id,
             getattr(Imported, other_side_flag_name),
             Or(
-                Imported.potemplateID == self.potemplate.id,
-                And(Imported.potemplateID == None, imported_no_diverged),
+                Imported.potemplate_id == self.potemplate.id,
+                And(Imported.potemplate_id == None, imported_no_diverged),
             ),
         ]
         imported_clauses.extend(
@@ -1635,9 +1636,9 @@ class POFileSet:
             message_select = Select(
                 True,
                 And(
-                    TranslationMessage.potmsgsetID == POTMsgSet.id,
+                    TranslationMessage.potmsgset_id == POTMsgSet.id,
                     TranslationMessage.potemplate == None,
-                    POFile.languageID == TranslationMessage.languageID,
+                    POFile.languageID == TranslationMessage.language_id,
                     Or(
                         And(
                             POTemplate.productseries == None,
diff --git a/lib/lp/translations/model/potmsgset.py b/lib/lp/translations/model/potmsgset.py
index 4635d5c..9cdefa0 100644
--- a/lib/lp/translations/model/potmsgset.py
+++ b/lib/lp/translations/model/potmsgset.py
@@ -398,19 +398,19 @@ class POTMsgSet(SQLBase):
         lang_used = []
         if both_languages:
             lang_used.append(
-                TranslationMessage.languageID.is_in(both_languages)
+                TranslationMessage.language_id.is_in(both_languages)
             )
         if used_languages:
             lang_used.append(
                 And(
-                    TranslationMessage.languageID.is_in(used_languages),
+                    TranslationMessage.language_id.is_in(used_languages),
                     in_use_clause,
                 )
             )
         if suggested_languages:
             lang_used.append(
                 And(
-                    TranslationMessage.languageID.is_in(suggested_languages),
+                    TranslationMessage.language_id.is_in(suggested_languages),
                     Not(in_use_clause),
                 )
             )
@@ -626,9 +626,9 @@ class POTMsgSet(SQLBase):
         # Prefer either shared or diverged messages, depending on
         # arguments.
         if prefer_shared:
-            order = [NullsFirst(TranslationMessage.potemplateID)]
+            order = [NullsFirst(TranslationMessage.potemplate_id)]
         else:
-            order = [NullsLast(TranslationMessage.potemplateID)]
+            order = [NullsLast(TranslationMessage.potemplate_id)]
 
         # Normally at most one message should match.  But if there is
         # more than one, prefer the one that adds the fewest extraneous
@@ -829,7 +829,6 @@ class POTMsgSet(SQLBase):
         return TranslationMessage(
             potmsgset=self,
             potemplate=potemplate,
-            pofile=pofile,
             language=pofile.language,
             origin=origin,
             submitter=submitter,
diff --git a/lib/lp/translations/model/translationmessage.py b/lib/lp/translations/model/translationmessage.py
index 25403fb..0265f4d 100644
--- a/lib/lp/translations/model/translationmessage.py
+++ b/lib/lp/translations/model/translationmessage.py
@@ -12,25 +12,20 @@ __all__ = [
 from datetime import datetime, timezone
 
 from storm.expr import And
-from storm.locals import SQL, Int, Reference
+from storm.locals import SQL, Bool, DateTime, Int, Reference, Unicode
 from storm.store import Store
 from zope.component import getUtility
 from zope.interface import implementer
 from zope.security.proxy import removeSecurityProxy
 
+from lp.app.errors import NotFoundError
 from lp.registry.interfaces.person import IPersonSet, validate_public_person
 from lp.services.database.bulk import load, load_related
 from lp.services.database.constants import DEFAULT, UTC_NOW
-from lp.services.database.datetimecol import UtcDateTimeCol
 from lp.services.database.enumcol import DBEnum
 from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import SQLBase, quote, sqlvalues
-from lp.services.database.sqlobject import (
-    BoolCol,
-    ForeignKey,
-    SQLObjectNotFound,
-    StringCol,
-)
+from lp.services.database.sqlbase import sqlvalues
+from lp.services.database.stormbase import StormBase
 from lp.services.propertycache import cachedproperty, get_property_cache
 from lp.translations.interfaces.currenttranslations import ICurrentTranslations
 from lp.translations.interfaces.potemplate import IPOTemplateSet
@@ -222,41 +217,40 @@ class PlaceholderTranslationMessage(TranslationMessageMixIn):
 
 
 @implementer(ITranslationMessage)
-class TranslationMessage(SQLBase, TranslationMessageMixIn):
-    _table = "TranslationMessage"
+class TranslationMessage(StormBase, TranslationMessageMixIn):
+    __storm_table__ = "TranslationMessage"
 
+    id = Int(primary=True)
     browser_pofile = None
-    potemplate = ForeignKey(
-        foreignKey="POTemplate",
-        dbName="potemplate",
-        notNull=False,
-        default=None,
-    )
-    language = ForeignKey(
-        foreignKey="Language", dbName="language", notNull=False, default=None
-    )
-    potmsgset = ForeignKey(
-        foreignKey="POTMsgSet", dbName="potmsgset", notNull=True
-    )
-    date_created = UtcDateTimeCol(
-        dbName="date_created", notNull=True, default=UTC_NOW
+    potemplate_id = Int(name="potemplate", allow_none=True, default=None)
+    potemplate = Reference(potemplate_id, "POTemplate.id")
+    language_id = Int(name="language", allow_none=True, default=None)
+    language = Reference(language_id, "Language.id")
+    potmsgset_id = Int(name="potmsgset", allow_none=False)
+    potmsgset = Reference(potmsgset_id, "POTMsgSet.id")
+    date_created = DateTime(
+        name="date_created",
+        allow_none=False,
+        default=UTC_NOW,
+        tzinfo=timezone.utc,
     )
-    submitter = ForeignKey(
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        dbName="submitter",
-        notNull=True,
+    submitter_id = Int(
+        name="submitter", validator=validate_public_person, allow_none=False
     )
-    date_reviewed = UtcDateTimeCol(
-        dbName="date_reviewed", notNull=False, default=None
+    submitter = Reference(submitter_id, "Person.id")
+    date_reviewed = DateTime(
+        name="date_reviewed",
+        allow_none=True,
+        default=None,
+        tzinfo=timezone.utc,
     )
-    reviewer = ForeignKey(
-        dbName="reviewer",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=False,
+    reviewer_id = Int(
+        name="reviewer",
+        validator=validate_public_person,
+        allow_none=True,
         default=None,
     )
+    reviewer = Reference(reviewer_id, "Person.id")
 
     assert TranslationConstants.MAX_PLURAL_FORMS == 6, (
         "Change this code to support %d plural forms."
@@ -276,7 +270,7 @@ class TranslationMessage(SQLBase, TranslationMessageMixIn):
     msgstr5_id = Int(name="msgstr5", allow_none=True, default=DEFAULT)
     msgstr5 = Reference(msgstr5_id, "POTranslation.id")
 
-    comment = StringCol(dbName="comment", notNull=False, default=None)
+    comment = Unicode(name="comment", allow_none=True, default=None)
     origin = DBEnum(
         name="origin", allow_none=False, enum=RosettaTranslationOrigin
     )
@@ -285,16 +279,59 @@ class TranslationMessage(SQLBase, TranslationMessageMixIn):
         allow_none=False,
         enum=TranslationValidationStatus,
     )
-    is_current_ubuntu = BoolCol(
-        dbName="is_current_ubuntu", notNull=True, default=False
+    is_current_ubuntu = Bool(
+        name="is_current_ubuntu", allow_none=False, default=False
     )
-    is_current_upstream = BoolCol(
-        dbName="is_current_upstream", notNull=True, default=False
+    is_current_upstream = Bool(
+        name="is_current_upstream", allow_none=False, default=False
     )
-    was_obsolete_in_last_import = BoolCol(
-        dbName="was_obsolete_in_last_import", notNull=True, default=False
+    was_obsolete_in_last_import = Bool(
+        name="was_obsolete_in_last_import", allow_none=False, default=False
     )
 
+    def __init__(
+        self,
+        potmsgset,
+        submitter,
+        potemplate=None,
+        language=None,
+        date_created=DEFAULT,
+        date_reviewed=None,
+        reviewer=None,
+        msgstr0=None,
+        msgstr1=None,
+        msgstr2=None,
+        msgstr3=None,
+        msgstr4=None,
+        msgstr5=None,
+        comment=None,
+        origin=None,
+        validation_status=DEFAULT,
+        is_current_ubuntu=DEFAULT,
+        is_current_upstream=DEFAULT,
+        was_obsolete_in_last_import=DEFAULT,
+    ):
+        super().__init__()
+        self.potmsgset = potmsgset
+        self.submitter = submitter
+        self.potemplate = potemplate
+        self.language = language
+        self.date_created = date_created
+        self.date_reviewed = date_reviewed
+        self.reviewer = reviewer
+        self.msgstr0 = msgstr0
+        self.msgstr1 = msgstr1
+        self.msgstr2 = msgstr2
+        self.msgstr3 = msgstr3
+        self.msgstr4 = msgstr4
+        self.msgstr5 = msgstr5
+        self.comment = comment
+        self.origin = origin
+        self.validation_status = validation_status
+        self.is_current_ubuntu = is_current_ubuntu
+        self.is_current_upstream = is_current_upstream
+        self.was_obsolete_in_last_import = was_obsolete_in_last_import
+
     # XXX jamesh 2008-05-02:
     # This method is not being called anymore.  The Storm
     # validator code doesn't handle getters.
@@ -436,7 +473,7 @@ class TranslationMessage(SQLBase, TranslationMessageMixIn):
                     FROM TranslationTemplateItem
                     WHERE potmsgset = %s AND sequence > 0
                     LIMIT 1)"""
-                    % sqlvalues(self.potmsgsetID)
+                    % sqlvalues(self.potmsgset_id)
                 ),
                 POFile.language == self.language,
             )
@@ -453,22 +490,22 @@ class TranslationMessage(SQLBase, TranslationMessageMixIn):
     def getSharedEquivalent(self):
         """See `ITranslationMessage`."""
         clauses = [
-            "potemplate IS NULL",
-            "potmsgset = %s" % sqlvalues(self.potmsgset),
-            "language = %s" % sqlvalues(self.language),
+            TranslationMessage.potemplate == None,
+            TranslationMessage.potmsgset == self.potmsgset,
+            TranslationMessage.language == self.language,
         ]
 
         for form in range(TranslationConstants.MAX_PLURAL_FORMS):
-            msgstr_name = "msgstr%d" % form
-            msgstr = getattr(self, "msgstr%d_id" % form)
+            msgstr_name = "msgstr%d_id" % form
+            msgstr_property = getattr(TranslationMessage, msgstr_name)
+            msgstr = getattr(self, msgstr_name)
             if msgstr is None:
-                form_clause = "%s IS NULL" % msgstr_name
+                form_clause = msgstr_property == None
             else:
-                form_clause = "%s = %s" % (msgstr_name, quote(msgstr))
+                form_clause = msgstr_property == msgstr
             clauses.append(form_clause)
 
-        where_clause = SQL(" AND ".join(clauses))
-        return Store.of(self).find(TranslationMessage, where_clause).one()
+        return Store.of(self).find(TranslationMessage, *clauses).one()
 
     def shareIfPossible(self):
         """See `ITranslationMessage`."""
@@ -537,8 +574,8 @@ class TranslationMessage(SQLBase, TranslationMessageMixIn):
 
         forms_match = TranslationMessage.msgstr0_id == self.msgstr0_id
         for form in range(1, TranslationConstants.MAX_PLURAL_FORMS):
-            form_name = "msgstr%d" % form
-            form_value = getattr(self, "msgstr%d_id" % form)
+            form_name = "msgstr%d_id" % form
+            form_value = getattr(self, form_name)
             forms_match = And(
                 forms_match,
                 getattr(TranslationMessage, form_name) == form_value,
@@ -580,6 +617,9 @@ class TranslationMessage(SQLBase, TranslationMessageMixIn):
         )
         return clone
 
+    def destroySelf(self):
+        Store.of(self).remove(self)
+
 
 @implementer(ITranslationMessageSet)
 class TranslationMessageSet:
@@ -587,10 +627,10 @@ class TranslationMessageSet:
 
     def getByID(self, ID):
         """See `ITranslationMessageSet`."""
-        try:
-            return TranslationMessage.get(ID)
-        except SQLObjectNotFound:
-            return None
+        tm = IStore(TranslationMessage).get(TranslationMessage, ID)
+        if tm is None:
+            raise NotFoundError(ID)
+        return tm
 
     def preloadDetails(
         self,
@@ -636,12 +676,12 @@ class TranslationMessageSet:
                 ],
             )
         if need_potmsgset:
-            load_related(POTMsgSet, tms, ["potmsgsetID"])
+            load_related(POTMsgSet, tms, ["potmsgset_id"])
         if need_people:
             list(
                 getUtility(IPersonSet).getPrecachedPersonsFromIDs(
-                    [tm.submitterID for tm in tms]
-                    + [tm.reviewerID for tm in tms]
+                    [tm.submitter_id for tm in tms]
+                    + [tm.reviewer_id for tm in tms]
                 )
             )
         if need_potmsgset_current_message:
@@ -685,7 +725,7 @@ class TranslationMessageSet:
                     TranslationTemplateItem.sequence,
                 ),
                 TranslationTemplateItem.potmsgset_id.is_in(
-                    message.potmsgsetID for message in messages
+                    message.potmsgset_id for message in messages
                 ),
                 POFile.potemplateID == TranslationTemplateItem.potemplate_id,
                 *pofile_constraints,
@@ -700,6 +740,6 @@ class TranslationMessageSet:
         for message in messages:
             assert message.language == language
             pofile_id, sequence = potmsgset_map.get(
-                message.potmsgsetID, (None, None)
+                message.potmsgset_id, (None, None)
             )
             message.setPOFile(IStore(POFile).get(POFile, pofile_id), sequence)
diff --git a/lib/lp/translations/scripts/migrate_current_flag.py b/lib/lp/translations/scripts/migrate_current_flag.py
index 0b09102..26046bf 100644
--- a/lib/lp/translations/scripts/migrate_current_flag.py
+++ b/lib/lp/translations/scripts/migrate_current_flag.py
@@ -64,20 +64,20 @@ class TranslationMessageImportedFlagUpdater:
             where=And(
                 PreviousImported.is_current_upstream == True,
                 (
-                    PreviousImported.potmsgsetID
-                    == CurrentTranslation.potmsgsetID
+                    PreviousImported.potmsgset_id
+                    == CurrentTranslation.potmsgset_id
                 ),
                 Or(
                     And(
-                        PreviousImported.potemplateID == None,
-                        CurrentTranslation.potemplateID == None,
+                        PreviousImported.potemplate_id == None,
+                        CurrentTranslation.potemplate_id == None,
                     ),
                     (
-                        PreviousImported.potemplateID
-                        == CurrentTranslation.potemplateID
+                        PreviousImported.potemplate_id
+                        == CurrentTranslation.potemplate_id
                     ),
                 ),
-                PreviousImported.languageID == CurrentTranslation.languageID,
+                PreviousImported.language_id == CurrentTranslation.language_id,
                 CurrentTranslation.id.is_in(tm_ids),
             ),
         )
@@ -147,7 +147,7 @@ class MigrateCurrentFlagProcess:
             TranslationMessage.is_current_ubuntu == True,
             TranslationMessage.is_current_upstream == False,
             (
-                TranslationMessage.potmsgsetID
+                TranslationMessage.potmsgset_id
                 == TranslationTemplateItem.potmsgset_id
             ),
             TranslationTemplateItem.potemplate_id == POTemplate.id,
diff --git a/lib/lp/translations/scripts/scrub_pofiletranslator.py b/lib/lp/translations/scripts/scrub_pofiletranslator.py
index 7aa0cb1..dccade1 100644
--- a/lib/lp/translations/scripts/scrub_pofiletranslator.py
+++ b/lib/lp/translations/scripts/scrub_pofiletranslator.py
@@ -84,11 +84,11 @@ def summarize_contributors(potemplate_id, language_ids, potmsgset_ids):
     store = IStore(POFile)
     contribs = {language_id: set() for language_id in language_ids}
     for language_id, submitter_id in store.find(
-        (TranslationMessage.languageID, TranslationMessage.submitterID),
-        TranslationMessage.potmsgsetID.is_in(potmsgset_ids),
-        TranslationMessage.languageID.is_in(language_ids),
+        (TranslationMessage.language_id, TranslationMessage.submitter_id),
+        TranslationMessage.potmsgset_id.is_in(potmsgset_ids),
+        TranslationMessage.language_id.is_in(language_ids),
         TranslationMessage.msgstr0 != None,
-        Coalesce(TranslationMessage.potemplateID, potemplate_id)
+        Coalesce(TranslationMessage.potemplate_id, potemplate_id)
         == potemplate_id,
     ).config(distinct=True):
         contribs[language_id].add(submitter_id)
@@ -114,15 +114,15 @@ def get_contributions(pofile, potmsgset_ids):
     language_id = pofile.language.id
     template_id = pofile.potemplate.id
     contribs = store.find(
-        (TranslationMessage.submitterID, TranslationMessage.date_created),
-        TranslationMessage.potmsgsetID.is_in(potmsgset_ids),
-        TranslationMessage.languageID == language_id,
+        (TranslationMessage.submitter_id, TranslationMessage.date_created),
+        TranslationMessage.potmsgset_id.is_in(potmsgset_ids),
+        TranslationMessage.language_id == language_id,
         TranslationMessage.msgstr0 != None,
-        Coalesce(TranslationMessage.potemplateID, template_id) == template_id,
+        Coalesce(TranslationMessage.potemplate_id, template_id) == template_id,
     )
-    contribs = contribs.config(distinct=(TranslationMessage.submitterID,))
+    contribs = contribs.config(distinct=(TranslationMessage.submitter_id,))
     contribs = contribs.order_by(
-        TranslationMessage.submitterID, Desc(TranslationMessage.date_created)
+        TranslationMessage.submitter_id, Desc(TranslationMessage.date_created)
     )
     return dict(contribs)
 
diff --git a/lib/lp/translations/tests/helpers.py b/lib/lp/translations/tests/helpers.py
index ffd1ec9..ed55ceb 100644
--- a/lib/lp/translations/tests/helpers.py
+++ b/lib/lp/translations/tests/helpers.py
@@ -7,7 +7,7 @@ __all__ = [
     "make_translationmessage_for_context",
 ]
 
-from storm.expr import Or
+from storm.expr import Desc, Or
 from storm.store import Store
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
@@ -82,7 +82,6 @@ def make_translationmessage(
     new_message = TranslationMessage(
         potmsgset=potmsgset,
         potemplate=potemplate,
-        pofile=None,
         language=pofile.language,
         origin=origin,
         submitter=submitter,
@@ -115,7 +114,7 @@ def get_all_translations_diverged_anywhere(pofile, potmsgset):
         TranslationMessage.potemplate != pofile.potemplate,
         TranslationMessage.language == pofile.language,
     )
-    return result.order_by(-TranslationMessage.potemplateID)
+    return result.order_by(Desc(TranslationMessage.potemplate_id))
 
 
 def summarize_current_translations(pofile, potmsgset):
diff --git a/lib/lp/translations/utilities/translationmerger.py b/lib/lp/translations/utilities/translationmerger.py
index 7992a65..3963227 100644
--- a/lib/lp/translations/utilities/translationmerger.py
+++ b/lib/lp/translations/utilities/translationmerger.py
@@ -642,7 +642,9 @@ class TranslationMerger:
 
                 for ids in tm_ids:
                     for id in ids:
-                        message = TranslationMessage.get(id)
+                        message = IStore(TranslationMessage).get(
+                            TranslationMessage, id
+                        )
                         removeSecurityProxy(message).shareIfPossible()
 
                 self.tm.endTransaction(intermediate=True)
@@ -671,7 +673,7 @@ class TranslationMerger:
             for form in range(TranslationConstants.MAX_PLURAL_FORMS)
         )
 
-        return (tm.potemplateID, tm.languageID) + msgstr_ids
+        return (tm.potemplate_id, tm.language_id) + msgstr_ids
 
     @staticmethod
     def _partitionTranslationMessageIds(potmsgset):
@@ -687,10 +689,10 @@ class TranslationMerger:
         """
         ids_per_language = {}
         tms = potmsgset.getAllTranslationMessages().order_by(
-            TranslationMessage.languageID
+            TranslationMessage.language_id
         )
         for tm in tms:
-            language = removeSecurityProxy(tm).languageID
+            language = removeSecurityProxy(tm).language_id
             if language not in ids_per_language:
                 ids_per_language[language] = []
             ids_per_language[language].append(tm.id)
@@ -719,7 +721,7 @@ class TranslationMerger:
             translations = {}
 
             for tm_id in ids:
-                tm = TranslationMessage.get(tm_id)
+                tm = IStore(TranslationMessage).get(TranslationMessage, tm_id)
                 key = self._getPOTMsgSetTranslationMessageKey(tm)
 
                 if key in translations:
diff --git a/lib/lp/translations/vocabularies.py b/lib/lp/translations/vocabularies.py
index 680db35..b856f80 100644
--- a/lib/lp/translations/vocabularies.py
+++ b/lib/lp/translations/vocabularies.py
@@ -80,9 +80,9 @@ class TranslationGroupVocabulary(NamedStormVocabulary):
     _table = TranslationGroup
 
 
-class TranslationMessageVocabulary(SQLObjectVocabularyBase):
+class TranslationMessageVocabulary(StormVocabularyBase):
     _table = TranslationMessage
-    _orderBy = "date_created"
+    _order_by = "date_created"
 
     def toTerm(self, obj):
         translation = ""