"""
The core application: view model definitions for the root of the webapp.
"""
from django.utils.translation import pgettext, gettext as _
from django.urls import reverse

from benefits.core import models

from . import session


class Button:
    """
    Represents a clickable button as styled <a> element (with optional label, optional transparent fallback text):
    * classes: str, str[]
    * id: str
    * fallback_text: str
    * label: str
    * text: str
    * url: str
    * target: str
    * rel: str
    """

    def __init__(self, **kwargs):
        classes = kwargs.get("classes", [])
        if isinstance(classes, str):
            classes = classes.split()

        self.classes = ["btn", "btn-lg"]
        self.classes.extend(classes)
        self.id = kwargs.get("id")
        self.fallback_text = kwargs.get("fallback_text")
        self.label = kwargs.get("label")
        self.text = kwargs.get("text", "Button")
        self.url = kwargs.get("url")
        self.target = kwargs.get("target")
        self.rel = kwargs.get("rel")

    @staticmethod
    def agency_contact_links(agency):
        """Create link buttons for agency contact information."""
        return [
            Button.link(classes="agency", label=agency.long_name, text=agency.phone, url=f"tel:{agency.phone}"),
            Button.link(
                classes="agency", text=agency.info_url, url=agency.info_url, target="_blank", rel="noopener noreferrer"
            ),
        ]

    @staticmethod
    def home(request, text=None):
        """Create a button back to this session's origin."""
        if text is None:
            text = _("core.buttons.return_home")

        return Button.primary(text=text, url=session.origin(request))

    @staticmethod
    def link(**kwargs):
        classes = kwargs.pop("classes", [])
        if isinstance(classes, str):
            classes = classes.split(" ")
        classes.insert(0, "btn-link")
        return Button(classes=classes, **kwargs)

    @staticmethod
    def primary(**kwargs):
        classes = kwargs.pop("classes", [])
        if isinstance(classes, str):
            classes = classes.split(" ")
        classes.insert(0, "btn-primary")
        return Button(classes=classes, **kwargs)

    @staticmethod
    def outline_primary(**kwargs):
        classes = kwargs.pop("classes", [])
        if isinstance(classes, str):
            classes = classes.split(" ")
        classes.insert(0, "btn-outline-primary")
        return Button(classes=classes, **kwargs)

    @staticmethod
    def login(**kwargs):
        """Create a login.gov button, with a login.gov logo and fallback text"""
        btn = Button.primary(fallback_text="Login.gov", id="login", **kwargs)
        return btn

    @staticmethod
    def logout(**kwargs):
        """Create a button that logs user out, with a login.gov button, with a login.gov logo and fallback text"""
        btn = Button.primary(fallback_text="Login.gov", id="login", url=reverse("oauth:logout"), text="", **kwargs)
        return btn


class Icon:
    """Represents an icon."""

    def __init__(self, icon, alt):
        self.src = f"img/icon/{icon}.svg"
        self.alt = alt


class Page:
    """
    Represents a page of content:
    * title: str
    * noimage: bool
    * icon: core.viewmodels.Icon
    * content_title: str
    * paragraphs: str[]
    * form: django.forms.Form
    * forms: django.forms.Form[]
    * button: core.viewmodels.Button
    * buttons: core.viewmodels.Button[]
    * classes: str[]
    """

    def __init__(self, **kwargs):
        self.title = kwargs.get("title")
        if self.title is None:
            self.title = _("core.pages.index.prefix")
        else:
            self.title = f"{_('core.pages.index.prefix')}: {self.title}"

        self.noimage = kwargs.get("noimage", False)
        self.icon = kwargs.get("icon")
        self.content_title = kwargs.get("content_title")
        self.paragraphs = kwargs.get("paragraphs", [])
        self.steps = kwargs.get("steps")

        self.forms = kwargs.get("forms", [])
        if not isinstance(self.forms, list):
            self.forms = [self.forms]
        if "form" in kwargs:
            self.forms.append(kwargs.get("form"))

        self.buttons = kwargs.get("buttons", [])
        if not isinstance(self.buttons, list):
            self.buttons = [self.buttons]
        if "button" in kwargs:
            self.buttons.append(kwargs.get("button"))

        self.classes = kwargs.get("classes", [])
        if not isinstance(self.classes, list):
            self.classes = self.classes.split(" ")
        if not self.noimage:
            self.classes.append("with-image")

    def context_dict(self):
        """Return a context dict for a Page."""
        return {"page": self}


class ErrorPage(Page):
    """
    Represents an error page:
    * title: str
    * icon: core.viewmodels.Icon
    * content_title: str
    * paragraphs: str[]
    * button: core.viewmodels.Button
    """

    def __init__(self, **kwargs):
        super().__init__(
            title=kwargs.get("title", _("core.pages.error.title")),
            icon=kwargs.get("icon", Icon("sadbus", pgettext("image alt text", "core.icons.sadbus"))),
            content_title=kwargs.get("content_title", _("core.pages.error.title")),
            paragraphs=kwargs.get("paragraphs", [_("core.pages.server_error.content_title")]),
            button=kwargs.get("button"),
        )

    @staticmethod
    def error(
        title=_("core.pages.server_error.title"),
        content_title=_("core.pages.server_error.title"),
        paragraphs=[_("core.pages.server_error.p[0]"), _("core.pages.server_error.p[1]")],
        **kwargs,
    ):
        """Create a new core.viewmodels.ErrorPage instance with defaults for a generic error."""
        return ErrorPage(title=title, content_title=content_title, paragraphs=paragraphs, **kwargs)

    @staticmethod
    def not_found(
        title=_("core.pages.not_found.title"),
        content_title=_("core.pages.not_found.content_title"),
        paragraphs=[_("core.pages.not_found.p[0]")],
        **kwargs,
    ):
        """Create a new core.viewmodels.ErrorPage with defaults for a 404."""
        path = kwargs.pop("path", None)
        if path and title:
            title = f"{title}: {path}"
        elif path and not title:
            title = path
        return ErrorPage(title=title, content_title=content_title, paragraphs=paragraphs, **kwargs)


class PaymentProcessor:
    """
    Represents a core.models.PaymentProcessor:
    * model: core.models.PaymentProcessor
    * access_token_url: str
    * element_id: str
    * color: str
    * [name: str]
    * [loading_text: str]
    """

    def __init__(self, model, access_token_url, element_id, color, name=None, loading_text=_("core.buttons.wait")):
        if isinstance(model, models.PaymentProcessor):
            self.access_token_url = access_token_url
            self.element_id = element_id
            self.color = color
            self.name = name or model.name
            self.loading_text = loading_text
            self.card_tokenize_url = model.card_tokenize_url
            self.card_tokenize_func = model.card_tokenize_func
            self.card_tokenize_env = model.card_tokenize_env

    def context_dict(self):
        """Return a context dict for a PaymentProcessor."""
        return {"payment_processor": self}


class TransitAgency:
    """
    Represents a core.models.TransitAgency:
    * model: core.models.TransitAgency
    """

    def __init__(self, model):
        if isinstance(model, models.TransitAgency):
            self.slug = model.slug
            self.short_name = model.short_name
            self.long_name = model.long_name
            self.agency_id = model.agency_id
            self.merchant_id = model.merchant_id
            self.info_url = model.info_url
            self.phone = model.phone

    def context_dict(self):
        """Return a context dict for a TransitAgency."""
        return {"agency": self}

benefits/core/viewmodels.py
"""
The core application: view model definitions for the root of the webapp.
"""
from django.utils.translation import pgettext, gettext_lazy as _
from django.urls import reverse

from benefits.core import models

from . import session


class Button:
    """
    Represents a clickable button as styled <a> element (with optional label, optional transparent fallback text):
    * classes: str, str[]
    * id: str
    * fallback_text: str
    * label: str
    * text: str
    * url: str
    * target: str
    * rel: str
    """

    def __init__(self, **kwargs):
        classes = kwargs.get("classes", [])
        if isinstance(classes, str):
            classes = classes.split()

        self.classes = ["btn", "btn-lg"]
        self.classes.extend(classes)
        self.id = kwargs.get("id")
        self.fallback_text = kwargs.get("fallback_text")
        self.label = kwargs.get("label")
        self.text = kwargs.get("text", "Button")
        self.url = kwargs.get("url")
        self.target = kwargs.get("target")
        self.rel = kwargs.get("rel")

    @staticmethod
    def agency_contact_links(agency):
        """Create link buttons for agency contact information."""
        return [
            Button.link(classes="agency", label=agency.long_name, text=agency.phone, url=f"tel:{agency.phone}"),
            Button.link(
                classes="agency", text=agency.info_url, url=agency.info_url, target="_blank", rel="noopener noreferrer"
            ),
        ]

    @staticmethod
    def home(request, text=None):
        """Create a button back to this session's origin."""
        if text is None:
            text = _("core.buttons.return_home")

        return Button.primary(text=text, url=session.origin(request))

    @staticmethod
    def link(**kwargs):
        classes = kwargs.pop("classes", [])
        if isinstance(classes, str):
            classes = classes.split(" ")
        classes.insert(0, "btn-link")
        return Button(classes=classes, **kwargs)

    @staticmethod
    def primary(**kwargs):
        classes = kwargs.pop("classes", [])
        if isinstance(classes, str):
            classes = classes.split(" ")
        classes.insert(0, "btn-primary")
        return Button(classes=classes, **kwargs)

    @staticmethod
    def outline_primary(**kwargs):
        classes = kwargs.pop("classes", [])
        if isinstance(classes, str):
            classes = classes.split(" ")
        classes.insert(0, "btn-outline-primary")
        return Button(classes=classes, **kwargs)

    @staticmethod
    def login(**kwargs):
        """Create a login.gov button, with a login.gov logo and fallback text"""
        btn = Button.primary(fallback_text="Login.gov", id="login", **kwargs)
        return btn

    @staticmethod
    def logout(**kwargs):
        """Create a button that logs user out, with a login.gov button, with a login.gov logo and fallback text"""
        btn = Button.primary(fallback_text="Login.gov", id="login", url=reverse("oauth:logout"), text="", **kwargs)
        return btn


class Icon:
    """Represents an icon."""

    def __init__(self, icon, alt):
        self.src = f"img/icon/{icon}.svg"
        self.alt = alt


class Page:
    """
    Represents a page of content:
    * title: str
    * noimage: bool
    * icon: core.viewmodels.Icon
    * content_title: str
    * paragraphs: str[]
    * form: django.forms.Form
    * forms: django.forms.Form[]
    * button: core.viewmodels.Button
    * buttons: core.viewmodels.Button[]
    * classes: str[]
    """

    def __init__(self, **kwargs):
        self.title = kwargs.get("title")
        if self.title is None:
            self.title = _("core.pages.index.prefix")
        else:
            self.title = f"{_('core.pages.index.prefix')}: {self.title}"

        self.noimage = kwargs.get("noimage", False)
        self.icon = kwargs.get("icon")
        self.content_title = kwargs.get("content_title")
        self.paragraphs = kwargs.get("paragraphs", [])
        self.steps = kwargs.get("steps")

        self.forms = kwargs.get("forms", [])
        if not isinstance(self.forms, list):
            self.forms = [self.forms]
        if "form" in kwargs:
            self.forms.append(kwargs.get("form"))

        self.buttons = kwargs.get("buttons", [])
        if not isinstance(self.buttons, list):
            self.buttons = [self.buttons]
        if "button" in kwargs:
            self.buttons.append(kwargs.get("button"))

        self.classes = kwargs.get("classes", [])
        if not isinstance(self.classes, list):
            self.classes = self.classes.split(" ")
        if not self.noimage:
            self.classes.append("with-image")

    def context_dict(self):
        """Return a context dict for a Page."""
        return {"page": self}


class ErrorPage(Page):
    """
    Represents an error page:
    * title: str
    * icon: core.viewmodels.Icon
    * content_title: str
    * paragraphs: str[]
    * button: core.viewmodels.Button
    """

    def __init__(self, **kwargs):
        super().__init__(
            title=kwargs.get("title", _("core.pages.error.title")),
            icon=kwargs.get("icon", Icon("sadbus", pgettext("image alt text", "core.icons.sadbus"))),
            content_title=kwargs.get("content_title", _("core.pages.error.title")),
            paragraphs=kwargs.get("paragraphs", [_("core.pages.server_error.content_title")]),
            button=kwargs.get("button"),
        )

    @staticmethod
    def error(
        title=_("core.pages.server_error.title"),
        content_title=_("core.pages.server_error.title"),
        paragraphs=[_("core.pages.server_error.p[0]"), _("core.pages.server_error.p[1]")],
        **kwargs,
    ):
        """Create a new core.viewmodels.ErrorPage instance with defaults for a generic error."""
        return ErrorPage(title=title, content_title=content_title, paragraphs=paragraphs, **kwargs)

    @staticmethod
    def not_found(
        title=_("core.pages.not_found.title"),
        content_title=_("core.pages.not_found.content_title"),
        paragraphs=[_("core.pages.not_found.p[0]")],
        **kwargs,
    ):
        """Create a new core.viewmodels.ErrorPage with defaults for a 404."""
        path = kwargs.pop("path", None)
        if path and title:
            title = f"{title}: {path}"
        elif path and not title:
            title = path
        return ErrorPage(title=title, content_title=content_title, paragraphs=paragraphs, **kwargs)


class PaymentProcessor:
    """
    Represents a core.models.PaymentProcessor:
    * model: core.models.PaymentProcessor
    * access_token_url: str
    * element_id: str
    * color: str
    * [name: str]
    * [loading_text: str]
    """

    def __init__(self, model, access_token_url, element_id, color, name=None, loading_text=_("core.buttons.wait")):
        if isinstance(model, models.PaymentProcessor):
            self.access_token_url = access_token_url
            self.element_id = element_id
            self.color = color
            self.name = name or model.name
            self.loading_text = loading_text
            self.card_tokenize_url = model.card_tokenize_url
            self.card_tokenize_func = model.card_tokenize_func
            self.card_tokenize_env = model.card_tokenize_env

    def context_dict(self):
        """Return a context dict for a PaymentProcessor."""
        return {"payment_processor": self}


class TransitAgency:
    """
    Represents a core.models.TransitAgency:
    * model: core.models.TransitAgency
    """

    def __init__(self, model):
        if isinstance(model, models.TransitAgency):
            self.slug = model.slug
            self.short_name = model.short_name
            self.long_name = model.long_name
            self.agency_id = model.agency_id
            self.merchant_id = model.merchant_id
            self.info_url = model.info_url
            self.phone = model.phone

    def context_dict(self):
        """Return a context dict for a TransitAgency."""
        return {"agency": self}

benefits/core/viewmodels.py
diff --git a/benefits/core/viewmodels.py b/benefits/core/viewmodels.py
index cf9f67ffca..9a6953bee4 100644
--- a/benefits/core/viewmodels.py
+++ b/benefits/core/viewmodels.py
@@ -1,7 +1,7 @@
 """
 The core application: view model definitions for the root of the webapp.
 """
-from django.utils.translation import pgettext, gettext as _
+from django.utils.translation import pgettext, gettext_lazy as _
 from django.urls import reverse
 
 from benefits.core import models
diff --git a/tests/pytest/core/test_viewmodels.py b/tests/pytest/core/test_viewmodels.py
new file mode 100644
index 0000000000..ca0c176aa4
--- /dev/null
+++ b/tests/pytest/core/test_viewmodels.py
@@ -0,0 +1,60 @@
+from django.utils import translation
+from django.utils.translation import gettext as _
+
+from benefits.core.viewmodels import ErrorPage
+
+
+def test_ErrorPage_error_translations():
+    translation.activate("en")
+
+    error_page = ErrorPage.error()
+    english_title = f"{_('core.pages.index.prefix')}: {_('core.pages.server_error.title')}"
+    english_content_title = _("core.pages.server_error.title")
+    english_paragraphs = [_("core.pages.server_error.p[0]"), _("core.pages.server_error.p[1]")]
+
+    assert error_page.title == english_title
+    assert error_page.content_title == english_content_title
+    assert error_page.paragraphs == english_paragraphs
+
+    translation.activate("es")
+
+    error_page = ErrorPage.error()
+    spanish_title = f"{_('core.pages.index.prefix')}: {_('core.pages.server_error.title')}"
+    spanish_content_title = _("core.pages.server_error.title")
+    spanish_paragraphs = [_("core.pages.server_error.p[0]"), _("core.pages.server_error.p[1]")]
+
+    assert error_page.title != english_title
+    assert error_page.content_title != english_content_title
+    assert error_page.paragraphs != english_paragraphs
+
+    assert error_page.title == spanish_title
+    assert error_page.content_title == spanish_content_title
+    assert error_page.paragraphs == spanish_paragraphs
+
+
+def test_ErrorPage_not_found_translations():
+    translation.activate("en")
+
+    error_page = ErrorPage.not_found()
+    english_title = f"{_('core.pages.index.prefix')}: {_('core.pages.not_found.title')}"
+    english_content_title = _("core.pages.not_found.content_title")
+    english_paragraphs = [_("core.pages.not_found.p[0]")]
+
+    assert error_page.title == english_title
+    assert error_page.content_title == english_content_title
+    assert error_page.paragraphs == english_paragraphs
+
+    translation.activate("es")
+
+    error_page = ErrorPage.not_found()
+    spanish_title = f"{_('core.pages.index.prefix')}: {_('core.pages.not_found.title')}"
+    spanish_content_title = _("core.pages.not_found.content_title")
+    spanish_paragraphs = [_("core.pages.not_found.p[0]")]
+
+    assert error_page.title != english_title
+    assert error_page.content_title != english_content_title
+    assert error_page.paragraphs != english_paragraphs
+
+    assert error_page.title == spanish_title
+    assert error_page.content_title == spanish_content_title
+    assert error_page.paragraphs == spanish_paragraphs

Bug: Spanish translations on all error pages are not showing up.
## To Reproduce

Steps to reproduce the behavior:

1. Go to benefits.calitp.org/
2. Click on Spanish
3. Go to benefits.calitp.org/asfakljsfasdf
4. See error

<img width="705" alt="image" src="https://user-images.githubusercontent.com/3673236/190244616-0867bdbe-cd77-477f-9fd0-0cf8f3b8625a.png">

Happening for 404 and 500

## Expected behavior

All the text should be in Spanish, not just the Footer and the Button.

## Screenshots

<img width="705" alt="image" src="https://user-images.githubusercontent.com/3673236/190244616-0867bdbe-cd77-477f-9fd0-0cf8f3b8625a.png">

## Desktop (please complete the following information)

Both 

## Smartphone (please complete the following information)

All

## Additional context

Fix translations on error pages (default arguments set once, need to use None and check for None instead)


