adliance / Storyblok

A intuitive and easy-to-use .NET wrapper around the Storyblok API
MIT License
3 stars 8 forks source link

Integration with existing localised application #17

Open myquay opened 9 months ago

myquay commented 9 months ago

I ran into an issue with how this package interacts with a solution that's already localised.

During registration of the Storyblok middleware this section was interfering with our localisation configuration causing existing sections of the application to not behave as intended.

I've made a few changes to the library so that it is able to integrate with a solution that's already been localised - here's the commit: https://github.com/myquay/Storyblok/commit/2ab0f6417c1727b826569eabcd833e3b406ff5c6

Let me know if this is something you think could help other users of your library and I'm happy to submit a PR otherwise feel free to close the issue.

The changes I made where around the three touch points below:

  1. In ApplicationBuilderExtensions.cs remove the code that alters the localisation configuration. Add a custom RequestCultureProvider to support the Storyblok style of localization by prefixing the slug so it works nicely with the editor. Placed it at high priority so it overrides other settings but does not modify existing settings so outside of Storyblok the application behaves as before.
 requestLocalizationOptions.Value.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
 {
     // special handling of Storyblok preview URLs that contain the language, like ~/de/home vs. ~/home
     // if we have such a URL, we also change the current culture accordingly
     var slug = context.Request.Path.ToString().Trim('/');
     var supportedCultures = requestLocalizationOptions?.Value?.SupportedCultures?.Select(s => s.Name).ToArray() ?? Array.Empty<string>();

     foreach (var supportedCulture in supportedCultures)
     {
         if (slug.StartsWith($"{supportedCulture}/", StringComparison.OrdinalIgnoreCase) || slug.Equals(supportedCulture, StringComparison.OrdinalIgnoreCase))
             return await Task.FromResult(new ProviderCultureResult(supportedCulture));
     }

     return await Task.FromResult<ProviderCultureResult?>(null);
 }));
  1. Updated the settings validation so that Storybloks configured supported cultures must be a subset of the cultures configured in the application so that we are not adding cultures unsupported in the wider application to the Storyblok integration.
var configuredCultures = requestLocalizationOptions?.SupportedCultures?.Select(s => s.Name) ?? new string[] { };
if(Settings.SupportedCultures.Any(x => !configuredCultures.Any(y => y.Equals(x, StringComparison.OrdinalIgnoreCase))))
{
    throw new Exception("All supported cultures in Storyblok must be configured in ASP.NET.");
}
  1. Update the Storyblok middleware to not interfere with the Culture Cookie, or the CurrentUI Culture
saxx commented 9 months ago

@myquay Thanks for your issue and excellent suggestions. I'd very much like a PR, thanks for the offer :)

The entire culture handling in the middleware is unfortunately quite hacky (and only really useful in our own use cases), so I'd be happy to update this to a better and more generalised version that is useful to others.