Merge pull request #2954 from alphagov/support-welsh-characters

Allow Welsh characters in SMS templates
This commit is contained in:
Katie Smith
2019-05-15 16:34:02 +01:00
committed by GitHub
7 changed files with 40 additions and 18 deletions
+2 -2
View File
@@ -40,7 +40,7 @@ from app.main.validators import (
DoesNotStartWithDoubleZero, DoesNotStartWithDoubleZero,
LettersNumbersAndFullStopsOnly, LettersNumbersAndFullStopsOnly,
NoCommasInPlaceHolders, NoCommasInPlaceHolders,
OnlyGSMCharacters, OnlySMSCharacters,
ValidEmail, ValidEmail,
ValidGovEmail, ValidGovEmail,
) )
@@ -639,7 +639,7 @@ class BaseTemplateForm(StripWhitespaceForm):
class SMSTemplateForm(BaseTemplateForm): class SMSTemplateForm(BaseTemplateForm):
def validate_template_content(self, field): def validate_template_content(self, field):
OnlyGSMCharacters()(None, field) OnlySMSCharacters()(None, field)
class EmailTemplateForm(BaseTemplateForm): class EmailTemplateForm(BaseTemplateForm):
+6 -6
View File
@@ -5,7 +5,7 @@ from notifications_utils.recipients import (
InvalidEmailError, InvalidEmailError,
validate_email_address, validate_email_address,
) )
from notifications_utils.sanitise_text import SanitiseGSM from notifications_utils.sanitise_text import SanitiseSMS
from wtforms import ValidationError from wtforms import ValidationError
from wtforms.validators import Email from wtforms.validators import Email
@@ -79,14 +79,14 @@ class NoCommasInPlaceHolders:
raise ValidationError(self.message) raise ValidationError(self.message)
class OnlyGSMCharacters: class OnlySMSCharacters:
def __call__(self, form, field): def __call__(self, form, field):
non_gsm_characters = sorted(list(SanitiseGSM.get_non_compatible_characters(field.data))) non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data)))
if non_gsm_characters: if non_sms_characters:
raise ValidationError( raise ValidationError(
'You cant use {} in text messages. {} wont show up properly on everyones phones.'.format( 'You cant use {} in text messages. {} wont show up properly on everyones phones.'.format(
formatted_list(non_gsm_characters, conjunction='or', before_each='', after_each=''), formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''),
('It' if len(non_gsm_characters) == 1 else 'They') ('It' if len(non_sms_characters) == 1 else 'They')
) )
) )
+1 -1
View File
@@ -127,7 +127,7 @@ def get_sms_thread(service_id, user_number):
) )
}, },
notification.get('personalisation'), notification.get('personalisation'),
downgrade_non_gsm_characters=(not is_inbound), downgrade_non_sms_characters=(not is_inbound),
redact_missing_personalisation=redact_personalisation, redact_missing_personalisation=redact_personalisation,
), ),
'created_at': notification['created_at'], 'created_at': notification['created_at'],
+24 -2
View File
@@ -40,10 +40,10 @@
<p>See <a href="#paying">how to pay</a>. <p>See <a href="#paying">how to pay</a>.
<h3 class="heading-small">Long text messages</h3> <h3 class="heading-small">Long text messages</h3>
<p>If a text message is beyond a certain length, itll be charged as more than one message:</p> <p>If a text message is longer than 160 characters (including spaces), itll be charged as more than one message:</p>
<div class="bottom-gutter-3-2"> <div class="bottom-gutter-3-2">
{% call mapping_table( {% call mapping_table(
caption='Letter pricing', caption='Text message pricing',
field_headings=['Message length', 'Charge'], field_headings=['Message length', 'Charge'],
field_headings_visible=True, field_headings_visible=True,
caption_visible=False caption_visible=False
@@ -61,6 +61,28 @@
{% endfor %} {% endfor %}
{% endcall %} {% endcall %}
</div> </div>
<p>Long text messages containing Welsh characters (Â, â, Ê, ê, Î, î, Ô, ô, Û, û, Ŵ, ŵ, Ŷ, and ŷ) are charged differently:</p>
<div class="bottom-gutter-3-2">
{% call mapping_table(
caption='Text message pricing',
field_headings=['Message length', 'Charge'],
field_headings_visible=True,
caption_visible=False
) %}
{% for message_length, charge in [
('Up to 70 characters', '1 text message'),
('Up to 134 characters', '2 text messages'),
('Up to 201 characters', '3 text messages'),
('Up to 268 characters', '4 text messages'),
('Each additional 67 characters', '1 additional text message'),
] %}
{% call row() %}
{{ text_field(message_length) }}
{{ text_field(charge) }}
{% endcall %}
{% endfor %}
{% endcall %}
</div>
<h3 class="heading-small">Sending text messages to international numbers</h3> <h3 class="heading-small">Sending text messages to international numbers</h3>
<p>It might cost more to send text messages to international numbers than UK ones, depending on the country.</p> <p>It might cost more to send text messages to international numbers than UK ones, depending on the country.</p>
<details> <details>
+1 -1
View File
@@ -23,4 +23,4 @@ awscli-cwlogs>=1.4,<1.5
# Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default # Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default
itsdangerous==0.24 # pyup: <1.0.0 itsdangerous==0.24 # pyup: <1.0.0
git+https://github.com/alphagov/notifications-utils.git@31.2.6#egg=notifications-utils==31.2.6 git+https://github.com/alphagov/notifications-utils.git@32.0.0#egg=notifications-utils==32.0.0
+1 -1
View File
@@ -25,7 +25,7 @@ awscli-cwlogs>=1.4,<1.5
# Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default # Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default
itsdangerous==0.24 # pyup: <1.0.0 itsdangerous==0.24 # pyup: <1.0.0
git+https://github.com/alphagov/notifications-utils.git@31.2.6#egg=notifications-utils==31.2.6 git+https://github.com/alphagov/notifications-utils.git@32.0.0#egg=notifications-utils==32.0.0
## The following requirements were added by pip freeze: ## The following requirements were added by pip freeze:
awscli==1.16.155 awscli==1.16.155
+5 -5
View File
@@ -6,7 +6,7 @@ from wtforms import ValidationError
from app.main.forms import RegisterUserForm, ServiceSmsSenderForm from app.main.forms import RegisterUserForm, ServiceSmsSenderForm
from app.main.validators import ( from app.main.validators import (
NoCommasInPlaceHolders, NoCommasInPlaceHolders,
OnlyGSMCharacters, OnlySMSCharacters,
ValidGovEmail, ValidGovEmail,
) )
@@ -165,8 +165,8 @@ def test_for_commas_in_placeholders(
@pytest.mark.parametrize('msg', ['The quick brown fox', 'Thé “quick” bröwn fox\u200B']) @pytest.mark.parametrize('msg', ['The quick brown fox', 'Thé “quick” bröwn fox\u200B'])
def test_gsm_character_validation(client, msg): def test_sms_character_validation(client, msg):
OnlyGSMCharacters()(None, _gen_mock_field(msg)) OnlySMSCharacters()(None, _gen_mock_field(msg))
@pytest.mark.parametrize('data, err_msg', [ @pytest.mark.parametrize('data, err_msg', [
@@ -185,9 +185,9 @@ def test_gsm_character_validation(client, msg):
) )
), ),
]) ])
def test_non_gsm_character_validation(data, err_msg, client): def test_non_sms_character_validation(data, err_msg, client):
with pytest.raises(ValidationError) as error: with pytest.raises(ValidationError) as error:
OnlyGSMCharacters()(None, _gen_mock_field(data)) OnlySMSCharacters()(None, _gen_mock_field(data))
assert str(error.value) == err_msg assert str(error.value) == err_msg