The Wayback Machine - https://web.archive.org/web/20211130035645/https://github.com/dotnet/aspnetcore/issues/38675
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

Improve Blazor localization handling #38675

Open
PieterjanDeClippel opened this issue Nov 28, 2021 · 2 comments
Open

Improve Blazor localization handling #38675

PieterjanDeClippel opened this issue Nov 28, 2021 · 2 comments

Comments

@PieterjanDeClippel
Copy link

@PieterjanDeClippel PieterjanDeClippel commented Nov 28, 2021

Summary

Building a localized website with Blazor Server is really inconvenient at the moment. I've consulted the documentation, tried multiple approaches but Blazor just doesn't seem to make it convenient.

Motivation and goals

For SEO purposes it is recommended to have the language either as an URL segment or query parameter. I prefer using a lang query parameter which needs to be monitored, and the culture updated accordingly.

Here is an example angular app with the approach I'm currently using in other angular apps.

Breakdown

In the AppComponent the query parameter is monitored and changes the language of the entire application:

constructor(private route: ActivatedRoute, private translateService: TranslateService) {
  const defaultLang = 'en';
  this.route.queryParams.subscribe((params) => {
    const lang = params['lang'];
    if (!!lang) {
      this.translateService.use(lang);
    } else {
      this.translateService.use(defaultLang);
    }
  });
}

At the client-side the TranslateModule services are provided through the following module import:

TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: (http: HttpClient) => new TranslateHttpLoader(http),
    deps: [ HttpClient ]
  }
}),

During SSR the TranslateModule services are provided through the following module import in the app.browser.module.ts:

TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: () => new TranslateJsonLoader()
  }
})

With the TranslateJsonLoader like this:

import { TranslateLoader } from '@ngx-translate/core';
import { of } from 'rxjs';
import * as translationEn from '../../assets/i18n/en.json';
import * as translationNl from '../../assets/i18n/nl.json';

export class TranslateJsonLoader implements TranslateLoader {
  constructor() {
  }

  public getTranslation(lang: string) {
    switch (lang) {
      case 'nl':
        return of(translationNl);
      default:
        return of(translationEn);
    }
  }
}

Now you can simply use the TranslatePipe on any component like a charm:

{{ 'message' | translate }}

I'd expect something similarily simple to be possible in Blazor Server.

  • Define your resx files with your translations
  • Use @translateService.Translate("message") in your razor views
  • Change the language using @onclick="@translateService.SetLocale("en-EN")"
  • No dependency on a cookie to select the language, but have the language passed through the url

In scope

  1. How to specify your translations => most likely through resx files
  2. Exposure of the language to the application
    a) Due to SEO considerations, the language should be present in the URL by preference
    b) Most likely some other developers would rather like to have the language in a cookie
  3. How to change the language
    a) Could be through a TranslateService
    b) I myself just use router.navigate([], { queryParams: { lang: 'en-EN' } });
@pranavkm
Copy link
Contributor

@pranavkm pranavkm commented Nov 28, 2021

Blazor Server uses the request localization middleware for it's localization which supports query string among other ways to specify the current request culture. See https://docs.microsoft.com/aspnet/core/fundamentals/localization?view=aspnetcore-6.0#localization-middleware. I think the docs recommend cookies because it takes away the overhead of figuring out how to persist a user's preference it across multiple browser sessions.

Use @translateService.Translate("message") in your razor views

Have you had a look at IStringLocalizer? It looks suspiciously similar to your translator APIs.

I myself just use router.navigate([], { queryParams: { lang: 'en-EN' } });

The equivalent is fairly similar in a Blazor Server once you've configured the query string provider: NavigationManager.NavigateTo(NavigationManager.GetUriWithQueryParameter("culture", userSelectedCulture), forceReload: true);

Loading

@PieterjanDeClippel
Copy link
Author

@PieterjanDeClippel PieterjanDeClippel commented Nov 29, 2021

Thanks for the response. I did look into this yesterday too, and didn't know how to get started with it rightaway. However I've created a boilerplate with the code you provided. Somehow I'm getting the same results as I'm experiencing with one of my previous approaches:

Previous approach

<NavLink class="nav-link" href="@navigationManager.GetUriWithQueryParameter("culture", "en-EN")">
    English
</NavLink>

This does not refresh the page (preferred behaviour)

The prerendered result is localized according to the query parameter provided, but after websassembly takes over, the views return to the default language. Now on top of this, since your suggestion uses forceReload: true, the page is refreshed. This is something I'd rather avoid.

(Do we continue this discussion on StackOverflow?)

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants