Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Redirection for Updated Locale Codes #3023

Merged
merged 13 commits into from
Nov 28, 2023

Conversation

ayanaar
Copy link
Contributor

@ayanaar ayanaar commented Nov 17, 2023

Fixes #2302

This pull request introduces a solution for handling changes to locale codes within our Pontoon application. Updating a locale code (e.g., changing sat-Olck to sat) previously could lead to broken links and inaccessible pages for users who had settings or preferences tied to the old locale code. To address this, I've implemented a redirection mechanism that ensures continuity even when locale codes are changed.

Changes Made:

  1. LocaleCodeHistory Model: Introduced a new model to track the history of changes to locale codes. This model records the old and new codes whenever a locale is updated.
  2. Signals for Locale Updates: Implemented Django signals to capture changes in locale codes and record them in the LocaleCodeHistory model.
  3. Redirection Utility Function (get_locale_or_redirect): Developed a utility function that checks if a requested locale exists. If an entry is found, it either redirects to the view specified by redirect_view_name using the new locale code or returns the Locale object if no redirect_view_name is provided. This function is now used across various views where locales are handled.
  4. Updates to Views: Modified several views, including the settings, translate, team, and localization views, to incorporate the get_locale_or_redirect function. This ensures that any references to outdated locale codes are correctly redirected to the new codes.
  5. Test Cases: Comprehensive test cases have been added to validate the functionality of the get_locale_or_redirect utility function in various views. These tests cover scenarios like code changes, missing codes, and non-existent codes to ensure proper redirection and error handling.

@ayanaar ayanaar requested a review from mathjazz November 17, 2023 02:51
@@ -1563,6 +1563,12 @@ class ProjectSlugHistory(models.Model):
created_at = models.DateTimeField(auto_now_add=True)


class LocaleCodeHistory(models.Model):
locale = models.ForeignKey("Locale", on_delete=models.CASCADE)
old_code = models.CharField(max_length=10)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locale.code has max_length set to 20, let's use that number here as well.

https://pontoon.mozilla.org/rm-vallader/

- get_locale_or_redirect function now returns a Locale object directly when no redirection is needed, facilitating use of locale names instead of codes.
- Adjusted settings view to set the default and custom homepage based on locale names. This change accommodates scenarios where locale codes are altered in the admin panel, ensuring the settings page remains functional.
- This approach leverages the stability of locale names, providing resilience against changes in locale codes.”
Copy link
Collaborator

@mathjazz mathjazz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update!

Left a few notes. It's mostly nits, but we should fix the logic in the settings view.

redirect_url = reverse(redirect_view_name, kwargs=redirect_kwargs)
return redirect(redirect_url)
else:
return code_history.locale # Return the locale instead of redirecting
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: You can dedent the main block like this:

if not redirect_view_name or not url_arg_name:
    return code_history.locale

redirect_kwargs = {url_arg_name: code_history.locale.code}
redirect_kwargs.update(kwargs)
redirect_url = reverse(redirect_view_name, kwargs=redirect_kwargs)
return redirect(redirect_url)
...

Also, no need for the comment, it's already well clarified in the docstring above.

custom_homepage_locale = profile.custom_homepage
if custom_homepage_locale:
# Set default for custom homepage locale based on name
custom_homepage_locale_object = get_locale_or_redirect(profile.custom_homepage)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just leave the name custom_homepage_locale.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you should first check if we have profile.custom_homepage.

If we don't, use default_homepage_locale.
Only if we do, call get_locale_or_redirect(), otherwise it will fail (redirect).

if custom_homepage_locale:
# Set default for custom homepage locale based on name
custom_homepage_locale_object = get_locale_or_redirect(profile.custom_homepage)
custom_homepage_locale_name = custom_homepage_locale_object.name
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why name (not unique), not code (unique)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I understood from our conversation yesterday, the name of the local rarely would ever be edited (in comparison to the locale code) so I thought that setting the custom and default homepage using the locale name would be more resilient to changes in the locale code. However, if it is not unique then that will cause issues so I will change the logic to use the locale code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, sounds like a misunderstanding. Locale names are probably edited more often than locale codes.

When you address the comment above, you might even be good without either.

preferred_source_locale = profile.preferred_source_locale
if preferred_source_locale:
# Set preferred source locale based on name
preferred_source_locale_object = get_locale_or_redirect(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as above.

@mathjazz mathjazz marked this pull request as ready for review November 22, 2023 19:43
Copy link
Collaborator

@mathjazz mathjazz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Please also add the missing tests as we discussed.

custom_homepage_locale = default_homepage_locale
messages.info(
request,
"Your previously selected custom homepage locale is no longer available. Reverted to default.",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't really revert the locale, we just show the default homepage when that happens. The user still needs to press Save. So I'd replace "Reverted to default." with something along the lines of "Please pick a different one.".

if profile.custom_homepage:
custom_homepage_locale = get_locale_or_redirect(profile.custom_homepage)
else:
custom_homepage_locale = default_homepage_locale
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move this line in front of the try - except block and then you can remove it from line 321.

At that point you no longer need the else block and you can move the try - except block within the if block.

profile.preferred_source_locale
)
else:
preferred_source_locale = default_preferred_source_locale
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

preferred_source_locale = default_preferred_source_locale
messages.info(
request,
"Your previously selected preferred source locale is no longer available. Reverted to default.",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Collaborator

@mathjazz mathjazz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great!

I'd just add one thing - if the locale that is set as the custom homepage gets deleted, the homepage 404s.

We can mitigate that by adding a call to get_locale_or_redirect() in front of https://github.com/mozilla/pontoon/blob/main/pontoon/homepage/views.py#L22 and wrap it in a try - except Http404 block (and just pass on exception).

Copy link
Collaborator

@mathjazz mathjazz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! This is much more than just a bugfix.

I'll file an issue to consider storing custom_homepage as models.ForeignKey(Locale).

@mathjazz mathjazz merged commit c41639d into mozilla:main Nov 28, 2023
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pontoon settings not accessible if profile has non existing locale as custom home page
2 participants