From ac1f711fef5f2ec087a356a539c2fd3194a44f3d Mon Sep 17 00:00:00 2001 From: Hemant Umre Date: Wed, 13 Sep 2023 01:28:58 +0530 Subject: [PATCH] registration: Set the organization language at creation time. In this commit, we add a new dropdown 'Organization language' on the `/new` and `/realm/register` pages. This dropdown allows setting the language of the organization during its creation. This allows messages from Welcome Bot and introductory messages in streams to be internationalized. Fixes a part of #25729. --- templates/zerver/accounts_send_confirm.html | 1 + templates/zerver/realm_creation_form.html | 17 ++++ templates/zerver/register.html | 4 + zerver/actions/create_realm.py | 3 + zerver/context_processors.py | 2 + zerver/forms.py | 9 +++ zerver/lib/test_classes.py | 4 + ...4_preregistrationrealm_default_language.py | 20 +++++ zerver/models.py | 4 + zerver/tests/test_management_commands.py | 4 +- zerver/tests/test_signup.py | 79 ++++++++++++++++--- zerver/views/auth.py | 2 + zerver/views/development/registration.py | 12 ++- zerver/views/registration.py | 48 ++++++++++- 14 files changed, 191 insertions(+), 18 deletions(-) create mode 100644 zerver/migrations/0484_preregistrationrealm_default_language.py diff --git a/templates/zerver/accounts_send_confirm.html b/templates/zerver/accounts_send_confirm.html index f5d8ac61c3..c88e38fdc8 100644 --- a/templates/zerver/accounts_send_confirm.html +++ b/templates/zerver/accounts_send_confirm.html @@ -30,6 +30,7 @@ page can be easily identified in it's respective JavaScript file -->       +     {% else %} diff --git a/templates/zerver/realm_creation_form.html b/templates/zerver/realm_creation_form.html index 471d5114b8..1a8bfb4c62 100644 --- a/templates/zerver/realm_creation_form.html +++ b/templates/zerver/realm_creation_form.html @@ -34,6 +34,23 @@ +
+
+ +
+ + +
+
+
+ +
{{ selected_realm_default_language_name }}
+
{% if form.realm_subdomain.value() %}{{ form.realm_subdomain.value() }}.{% endif %}{{external_host}}
diff --git a/zerver/actions/create_realm.py b/zerver/actions/create_realm.py index 9be0bec244..9dfd82cc98 100644 --- a/zerver/actions/create_realm.py +++ b/zerver/actions/create_realm.py @@ -159,6 +159,7 @@ def do_create_realm( invite_required: Optional[bool] = None, plan_type: Optional[int] = None, org_type: Optional[int] = None, + default_language: Optional[str] = None, date_created: Optional[datetime.datetime] = None, is_demo_organization: bool = False, enable_read_receipts: Optional[bool] = None, @@ -184,6 +185,8 @@ def do_create_realm( kwargs["plan_type"] = plan_type if org_type is not None: kwargs["org_type"] = org_type + if default_language is not None: + kwargs["default_language"] = default_language if enable_spectator_access is not None: if enable_spectator_access: # Realms with LIMITED plan cannot have spectators enabled. diff --git a/zerver/context_processors.py b/zerver/context_processors.py index 500229d866..0a4594c93f 100644 --- a/zerver/context_processors.py +++ b/zerver/context_processors.py @@ -14,6 +14,7 @@ from version import ( ZULIP_VERSION, ) from zerver.lib.exceptions import InvalidSubdomainError +from zerver.lib.i18n import get_language_list from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description from zerver.lib.realm_icon import get_realm_icon_url from zerver.lib.request import RequestNotes @@ -259,6 +260,7 @@ def latest_info_context() -> Dict[str, str]: def get_realm_create_form_context() -> Dict[str, Any]: context = { + "language_list": get_language_list(), "MAX_REALM_NAME_LENGTH": str(Realm.MAX_REALM_NAME_LENGTH), "MAX_REALM_SUBDOMAIN_LENGTH": str(Realm.MAX_REALM_SUBDOMAIN_LENGTH), "root_domain_available": is_root_domain_available(), diff --git a/zerver/forms.py b/zerver/forms.py index 41eb032800..467983e29f 100644 --- a/zerver/forms.py +++ b/zerver/forms.py @@ -28,6 +28,7 @@ from zerver.lib.email_validation import ( email_reserved_for_system_bots_error, ) from zerver.lib.exceptions import JsonableError, RateLimitedError +from zerver.lib.i18n import get_language_list from zerver.lib.name_restrictions import is_disposable_domain, is_reserved_subdomain from zerver.lib.rate_limiter import RateLimitedObject, rate_limit_request_by_ip from zerver.lib.send_email import FromAddress, send_email @@ -140,6 +141,7 @@ class RealmDetailsForm(forms.Form): realm_type = forms.TypedChoiceField( coerce=int, choices=[(t["id"], t["name"]) for t in Realm.ORG_TYPES.values()] ) + realm_default_language = forms.ChoiceField(choices=[]) realm_name = forms.CharField(max_length=Realm.MAX_REALM_NAME_LENGTH) def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -147,6 +149,9 @@ class RealmDetailsForm(forms.Form): del kwargs["realm_creation"] super().__init__(*args, **kwargs) + self.fields["realm_default_language"] = forms.ChoiceField( + choices=[(lang["code"], lang["name"]) for lang in get_language_list()], + ) def clean_realm_subdomain(self) -> str: if not self.realm_creation: @@ -192,6 +197,10 @@ class RegistrationForm(RealmDetailsForm): choices=[(t["id"], t["name"]) for t in Realm.ORG_TYPES.values()], required=self.realm_creation, ) + self.fields["realm_default_language"] = forms.ChoiceField( + choices=[(lang["code"], lang["name"]) for lang in get_language_list()], + required=self.realm_creation, + ) def clean_full_name(self) -> str: try: diff --git a/zerver/lib/test_classes.py b/zerver/lib/test_classes.py index 38987211da..c66191c4bf 100644 --- a/zerver/lib/test_classes.py +++ b/zerver/lib/test_classes.py @@ -820,6 +820,7 @@ Output: source_realm_id: str = "", key: Optional[str] = None, realm_type: int = Realm.ORG_TYPES["business"]["id"], + realm_default_language: str = "en", enable_marketing_emails: Optional[bool] = None, email_address_visibility: Optional[int] = None, is_demo_organization: bool = False, @@ -840,6 +841,7 @@ Output: "realm_name": realm_name, "realm_subdomain": realm_subdomain, "realm_type": realm_type, + "realm_default_language": realm_default_language, "key": key if key is not None else find_key_by_email(email), "timezone": timezone, "terms": True, @@ -874,12 +876,14 @@ Output: realm_subdomain: str, realm_name: str, realm_type: int = Realm.ORG_TYPES["business"]["id"], + realm_default_language: str = "en", realm_in_root_domain: Optional[str] = None, ) -> "TestHttpResponse": payload = { "email": email, "realm_name": realm_name, "realm_type": realm_type, + "realm_default_language": realm_default_language, "realm_subdomain": realm_subdomain, } if realm_in_root_domain is not None: diff --git a/zerver/migrations/0484_preregistrationrealm_default_language.py b/zerver/migrations/0484_preregistrationrealm_default_language.py new file mode 100644 index 0000000000..8e4a0d45eb --- /dev/null +++ b/zerver/migrations/0484_preregistrationrealm_default_language.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.5 on 2023-09-12 19:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ( + "zerver", + "0483_rename_escape_navigates_to_default_view_realmuserdefault_web_escape_navigates_to_home_view_and_more", + ), + ] + + operations = [ + migrations.AddField( + model_name="preregistrationrealm", + name="default_language", + field=models.CharField(default="en", max_length=50), + ), + ] diff --git a/zerver/models.py b/zerver/models.py index a80221bf6c..05bb13df90 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -2434,6 +2434,10 @@ class PreregistrationRealm(models.Model): default=Realm.ORG_TYPES["unspecified"]["id"], choices=[(t["id"], t["name"]) for t in Realm.ORG_TYPES.values()], ) + default_language = models.CharField( + default="en", + max_length=MAX_LANGUAGE_ID_LENGTH, + ) string_id = models.CharField(max_length=Realm.MAX_REALM_SUBDOMAIN_LENGTH) email = models.EmailField() diff --git a/zerver/tests/test_management_commands.py b/zerver/tests/test_management_commands.py index e9645d0ab5..8542f92b0a 100644 --- a/zerver/tests/test_management_commands.py +++ b/zerver/tests/test_management_commands.py @@ -310,6 +310,7 @@ class TestGenerateRealmCreationLink(ZulipTestCase): "email": email, "realm_name": "Zulip test", "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_default_language": "en", "realm_subdomain": "custom-test", }, ) @@ -337,12 +338,13 @@ class TestGenerateRealmCreationLink(ZulipTestCase): "email": email, "realm_name": realm_name, "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_default_language": "en", "realm_subdomain": string_id, }, ) self.assertEqual(result.status_code, 302) self.assertEqual( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}", + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}", result["Location"], ) result = self.client_get(result["Location"]) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index f4a64b79ec..5ab534e4f4 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -748,7 +748,7 @@ class PasswordResetTest(ZulipTestCase): self.assert_in_success_response(["/accounts/home/"], result) result = self.client_get( - "/accounts/new/send_confirm/?email=alice@example.com&realm_name=Zulip+test&realm_type=10&realm_subdomain=zuliptest" + "/accounts/new/send_confirm/?email=alice@example.com&realm_name=Zulip+test&realm_type=10&realm_default_language=en&realm_subdomain=zuliptest" ) self.assert_in_success_response(["/new/"], result) @@ -1256,7 +1256,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(org_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(org_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1264,6 +1264,7 @@ class RealmCreationTest(ZulipTestCase): prereg_realm = PreregistrationRealm.objects.get(email=email) self.assertEqual(prereg_realm.name, "Zulip Test") self.assertEqual(prereg_realm.org_type, Realm.ORG_TYPES["business"]["id"]) + self.assertEqual(prereg_realm.default_language, "en") self.assertEqual(prereg_realm.string_id, string_id) # Check confirmation email has the correct subject and body, extract @@ -1295,6 +1296,7 @@ class RealmCreationTest(ZulipTestCase): # Check defaults self.assertEqual(realm.org_type, Realm.ORG_TYPES["business"]["id"]) + self.assertEqual(realm.default_language, "en") self.assertEqual(realm.emails_restricted_to_domains, False) self.assertEqual(realm.invite_required, True) @@ -1397,7 +1399,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1443,7 +1445,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1492,7 +1494,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1552,7 +1554,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1597,7 +1599,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1648,7 +1650,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=35&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=35&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1683,6 +1685,61 @@ class RealmCreationTest(ZulipTestCase): self.assertIn("Using Zulip for a class guide", welcome_msg.content) self.assertIn("demo organization", welcome_msg.content) + @override_settings(OPEN_REALM_CREATION=True) + def test_create_realm_with_custom_language(self) -> None: + email = "user1@test.com" + password = "test" + string_id = "custom-test" + realm_name = "Zulip Test" + realm_language = "it" + + # Make sure the realm does not exist + with self.assertRaises(Realm.DoesNotExist): + get_realm(string_id) + + # Create new realm with the email + result = self.submit_realm_creation_form( + email, + realm_subdomain=string_id, + realm_name=realm_name, + realm_default_language=realm_language, + ) + self.assertEqual(result.status_code, 302) + self.assertTrue( + result["Location"].endswith( + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language={realm_language}&realm_subdomain={string_id}" + ) + ) + result = self.client_get(result["Location"]) + self.assert_in_response("check your email", result) + + prereg_realm = PreregistrationRealm.objects.get(email=email) + # Check default_language field of PreregistrationRealm object + self.assertEqual(prereg_realm.default_language, realm_language) + + # Visit the confirmation link. + confirmation_url = self.get_confirmation_url_from_outbox(email) + result = self.client_get(confirmation_url) + self.assertEqual(result.status_code, 200) + + result = self.submit_reg_form_for_user( + email, + password, + realm_subdomain=string_id, + realm_name=realm_name, + realm_default_language=realm_language, + ) + self.assertEqual(result.status_code, 302) + + result = self.client_get(result["Location"], subdomain=string_id) + self.assertEqual(result.status_code, 302) + self.assertEqual(result["Location"], "http://custom-test.testserver") + + # Make sure the realm is created and check default_language field + realm = get_realm(string_id) + self.assertEqual(realm.string_id, string_id) + self.assertEqual(realm.default_language, realm_language) + @override_settings(OPEN_REALM_CREATION=True, FREE_TRIAL_DAYS=30) def test_create_realm_during_free_trial(self) -> None: password = "test" @@ -1700,7 +1757,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_subdomain={string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={string_id}" ) ) result = self.client_get(result["Location"]) @@ -1756,7 +1813,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(first_realm_name)}&realm_type=10&realm_subdomain={first_string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(first_realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={first_string_id}" ) ) result = self.client_get(result["Location"]) @@ -1770,7 +1827,7 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( - f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(second_realm_name)}&realm_type=10&realm_subdomain={second_string_id}" + f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}&realm_name={urllib.parse.quote_plus(second_realm_name)}&realm_type=10&realm_default_language=en&realm_subdomain={second_string_id}" ) ) result = self.client_get(result["Location"]) diff --git a/zerver/views/auth.py b/zerver/views/auth.py index 6a079aec44..a629a68a70 100644 --- a/zerver/views/auth.py +++ b/zerver/views/auth.py @@ -143,12 +143,14 @@ def create_preregistration_realm( name: str, string_id: str, org_type: int, + default_language: str, ) -> PreregistrationRealm: return PreregistrationRealm.objects.create( email=email, name=name, string_id=string_id, org_type=org_type, + default_language=default_language, ) diff --git a/zerver/views/development/registration.py b/zerver/views/development/registration.py index e68f0583c2..8136e43c8a 100644 --- a/zerver/views/development/registration.py +++ b/zerver/views/development/registration.py @@ -65,8 +65,11 @@ def register_development_realm(request: HttpRequest) -> HttpResponse: email = f"{name}@zulip.com" realm_name = f"realm-{count}" realm_type = Realm.ORG_TYPES["business"]["id"] + realm_default_language = "en" realm_subdomain = realm_name - prereg_realm = create_preregistration_realm(email, realm_name, realm_subdomain, realm_type) + prereg_realm = create_preregistration_realm( + email, realm_name, realm_subdomain, realm_type, realm_default_language + ) activation_url = create_confirmation_link( prereg_realm, Confirmation.REALM_CREATION, realm_creation=True ) @@ -77,6 +80,7 @@ def register_development_realm(request: HttpRequest) -> HttpResponse: key=key, realm_name=realm_name, realm_type=realm_type, + realm_default_language=realm_default_language, full_name=name, password="test", realm_subdomain=realm_subdomain, @@ -91,11 +95,14 @@ def register_demo_development_realm(request: HttpRequest) -> HttpResponse: # Demo organization owners are not required to provide a name or email. name = "Your name" email = "" + realm_default_language = "en" realm_name = generate_demo_realm_name() realm_type = Realm.ORG_TYPES["unspecified"]["id"] realm_subdomain = realm_name email_address_visibility = UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY - prereg_realm = create_preregistration_realm(email, realm_name, realm_subdomain, realm_type) + prereg_realm = create_preregistration_realm( + email, realm_name, realm_subdomain, realm_type, realm_default_language + ) activation_url = create_confirmation_link( prereg_realm, Confirmation.REALM_CREATION, realm_creation=True ) @@ -106,6 +113,7 @@ def register_demo_development_realm(request: HttpRequest) -> HttpResponse: key=key, realm_name=realm_name, realm_type=realm_type, + realm_default_language=realm_default_language, email_address_visibility=email_address_visibility, full_name=name, password="test", diff --git a/zerver/views/registration.py b/zerver/views/registration.py index 0dd566b93b..75a35b7e05 100644 --- a/zerver/views/registration.py +++ b/zerver/views/registration.py @@ -52,7 +52,11 @@ from zerver.forms import ( ) from zerver.lib.email_validation import email_allowed_for_realm, validate_email_not_already_in_realm from zerver.lib.exceptions import RateLimitedError -from zerver.lib.i18n import get_default_language_for_new_user +from zerver.lib.i18n import ( + get_browser_language_code, + get_default_language_for_new_user, + get_language_name, +) from zerver.lib.pysa import mark_sanitized from zerver.lib.rate_limiter import rate_limit_request_by_ip from zerver.lib.request import REQ, has_request_variables @@ -70,6 +74,7 @@ from zerver.lib.validator import ( ) from zerver.lib.zephyr import compute_mit_user_fullname from zerver.models import ( + MAX_LANGUAGE_ID_LENGTH, DisposableEmailError, DomainNotAllowedForRealmError, EmailContainsPlusError, @@ -195,6 +200,16 @@ def get_selected_realm_type_name(prereg_realm: Optional[PreregistrationRealm]) - return get_org_type_display_name(prereg_realm.org_type) +def get_selected_realm_default_language_name( + prereg_realm: Optional[PreregistrationRealm], +) -> Optional[str]: + if prereg_realm is None: + # We show the selected realm language only when creating new realm. + return None + + return get_language_name(prereg_realm.default_language) + + @add_google_analytics @require_post def realm_register(*args: Any, **kwargs: Any) -> HttpResponse: @@ -361,6 +376,7 @@ def registration_helper( initial_data = { "realm_name": prereg_realm.name, "realm_type": prereg_realm.org_type, + "realm_default_language": prereg_realm.default_language, "realm_subdomain": prereg_realm.string_id, } @@ -440,11 +456,13 @@ def registration_helper( string_id = form.cleaned_data["realm_subdomain"] realm_name = form.cleaned_data["realm_name"] realm_type = form.cleaned_data["realm_type"] + realm_default_language = form.cleaned_data["realm_default_language"] is_demo_organization = form.cleaned_data["is_demo_organization"] realm = do_create_realm( string_id, realm_name, org_type=realm_type, + default_language=realm_default_language, is_demo_organization=is_demo_organization, prereg_realm=prereg_realm, ) @@ -654,6 +672,9 @@ def registration_helper( "corporate_enabled": settings.CORPORATE_ENABLED, "default_email_address_visibility": default_email_address_visibility, "selected_realm_type_name": get_selected_realm_type_name(prereg_realm), + "selected_realm_default_language_name": get_selected_realm_default_language_name( + prereg_realm + ), "email_address_visibility_admins_only": RealmUserDefault.EMAIL_ADDRESS_VISIBILITY_ADMINS, "email_address_visibility_moderators": RealmUserDefault.EMAIL_ADDRESS_VISIBILITY_MODERATORS, "email_address_visibility_nobody": RealmUserDefault.EMAIL_ADDRESS_VISIBILITY_NOBODY, @@ -727,8 +748,11 @@ def prepare_realm_activation_url( realm_name: str, string_id: str, org_type: int, + default_language: str, ) -> str: - prereg_realm = create_preregistration_realm(email, realm_name, string_id, org_type) + prereg_realm = create_preregistration_realm( + email, realm_name, string_id, org_type, default_language + ) activation_url = create_confirmation_link( prereg_realm, Confirmation.REALM_CREATION, realm_creation=True ) @@ -802,9 +826,15 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht email = form.cleaned_data["email"] realm_name = form.cleaned_data["realm_name"] realm_type = form.cleaned_data["realm_type"] + realm_default_language = form.cleaned_data["realm_default_language"] realm_subdomain = form.cleaned_data["realm_subdomain"] activation_url = prepare_realm_activation_url( - email, request.session, realm_name, realm_subdomain, realm_type + email, + request.session, + realm_name, + realm_subdomain, + realm_type, + realm_default_language, ) if key_record is not None and key_record.presume_email_valid: # The user has a token created from the server command line; @@ -830,13 +860,21 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht "email": email, "realm_name": realm_name, "realm_type": realm_type, + "realm_default_language": realm_default_language, "realm_subdomain": realm_subdomain, } ) url = append_url_query_string(new_realm_send_confirm_url, query) return HttpResponseRedirect(url) else: - form = RealmCreationForm() + default_language_code = get_browser_language_code(request) + if default_language_code is None: + default_language_code = "en" + + initial_data = { + "realm_default_language": default_language_code, + } + form = RealmCreationForm(initial=initial_data) context = get_realm_create_form_context() context.update( @@ -868,6 +906,7 @@ def new_realm_send_confirm( email: str = REQ("email"), realm_name: str = REQ(str_validator=check_capped_string(Realm.MAX_REALM_NAME_LENGTH)), realm_type: int = REQ(json_validator=check_int_in(Realm.ORG_TYPE_IDS)), + realm_default_language: str = REQ(str_validator=check_capped_string(MAX_LANGUAGE_ID_LENGTH)), realm_subdomain: str = REQ(str_validator=check_capped_string(Realm.MAX_REALM_SUBDOMAIN_LENGTH)), ) -> HttpResponse: return TemplateResponse( @@ -880,6 +919,7 @@ def new_realm_send_confirm( # creation. "new_realm_name": realm_name, "realm_type": realm_type, + "realm_default_language": realm_default_language, "realm_subdomain": realm_subdomain, "realm_creation": True, },