Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions 10/umbraco-cms/tutorials/multilanguage-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,105 @@
**German Version:**

<figure><img src="images/final-result-da.png" alt=""><figcaption></figcaption></figure>

## Using Multiple languages across APIs

When requesting content over an API, the culture will fall back to the default, unless explicitly set.

To do this, you can use the IVariationContextAccessor.

```csharp
public class ExampleController : SurfaceController
{
private readonly ILocalizationService _localizationService;
private readonly IVariationContextAccessor _variationContextAccessor;

public ExampleController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider, ILocalizationService localizationService, IVariationContextAccessor variationContextAccessor) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
{
_localizationService = localizationService;
_variationContextAccessor = variationContextAccessor;
}

public IActionResult Index(string culture = null)
{
IEnumerable<ILanguage> UmbracoLanguages = _localizationService.GetAllLanguages(); //a helpful method to get all configured languages
var requestedCulture = UmbracoLanguages.FirstOrDefault(l => l.IsoCode == culture);

if (requestedCulture != null)
{
_variationContextAccessor.VariationContext = new VariationContext(requestedCulture.IsoCode);
}

//this will now be in the requested culture
var content = UmbracoContext.Content.GetAtRoot();

//Content requested in this View Component will now be in the requested culture
return ViewComponent();
}
}
```

### Creating a Language Switching Navigation

To navigate between languages, we need to do two key things:

1. Get all the languages that the site can provide
2. Identify the language used on the current page

Once you have these, you need to loop through the languages and provide links to each home node.

### Getting all the languages for a site

There are two ways to achieve this. One is to use `localizationService.GetAllLanguages();` to call the database, which is expensive and ideally includes caching.

The alternative is to get the Home node and find all cultures associated with it. This has a few benefits including speed and providing us with a link to show the user. It is the process you will use when following this guide.

### Identify the language for the current page

This is achieved in `cs.html` files using `umbracoHelper.AssignedContentItem.GetCultureFromDomains();`.

#### Steps

Now that you have what you need, create a view called `Navigation.cshtml`, and paste in the following:

```cshtml
@using Umbraco.Cms.Web.Common
@inject IUmbracoHelperAccessor _umbracoHelperAccessor;

@{
_umbracoHelperAccessor.TryGetUmbracoHelper(out var umbracoHelper);

var homePage = umbracoHelper.ContentAtRoot().FirstOrDefault(c => c.ContentType.Alias == "{{homeNodeContentAlias}}");
var cultures = homePage?.Cultures;
}

@if (cultures.Count > 1)
{
<ul aria-label="Language switcher">
@foreach (var cult in cultures)
{
//get the settings for this culture
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo(cult.Key);
//if the current page has a language variant, otherwise link to the homepage language variant
string langUrl = umbracoHelper.AssignedContentItem.Url(cult.Key, UrlMode.Relative) ?? homePage.Url(cult.Key, UrlMode.Relative);

<li>
@if (cult.Key.ToLower() == umbracoHelper.AssignedContentItem.GetCultureFromDomains().ToLower())
{
<span aria-current="true" >@culture.NativeName</span>
}
else
{
<a href="@langUrl" hreflang="@cult.Key" lang="@cult.Key" >@culture.NativeName</a>
}
</li>
}
</ul>
}
```

You need to replace `{{homeNodeContentAlias}}` with the Document Type alias of your Home node.

This will look at all the cultures available on the home node, and render links to either the language variant of the current page, or the home node for the language variant. If the home node for a language variant is removed, it will not appear in the list.

Check warning on line 328 in 10/umbraco-cms/tutorials/multilanguage-setup.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [UmbracoDocs.SentenceLength] Write shorter sentences (less than 25 words). Raw Output: {"message": "[UmbracoDocs.SentenceLength] Write shorter sentences (less than 25 words).", "location": {"path": "10/umbraco-cms/tutorials/multilanguage-setup.md", "range": {"start": {"line": 328, "column": 1}}}, "severity": "WARNING"}

Additionally, `System.Globalization.CultureInfo` is used to obtain the native name of the language being rendered. This is useful if a user does not speak the default language.
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ To view the language variant on the browser, follow these steps:
![Viewing the Language Variant Link](images/viewing-langvariant-browser-v14.png)
5. Click on the link to view the new language node in the browser.
6. Alternatively, you can add the domain name to your localhost in the browser. For example: [http://localhost:xxxx/da/](http:/localhost:xxxx/da/)

## More Information

Further information on multi-language setups can be found in the [Multilanguage Setup tutorial](../multilanguage-setup.md).
104 changes: 104 additions & 0 deletions 14/umbraco-cms/tutorials/multilanguage-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,107 @@
German Version:

<figure><img src="../../../10/umbraco-cms/tutorials/images/final-result-da.png" alt=""><figcaption></figcaption></figure>

## Using Multiple languages across APIs

When requesting content over an API, the culture will fall back to the default, unless explicitly set.

To do this, you can use the IVariationContextAccessor.

```csharp
public class ExampleController : SurfaceController
{
private readonly ILanguageService _languageService;
private readonly IVariationContextAccessor _variationContextAccessor;

public ExampleController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider, ILocalizationService localizationService, IVariationContextAccessor variationContextAccessor) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
{
_localizationService = localizationService;
_variationContextAccessor = variationContextAccessor;
}

public IActionResult Index(string culture = null)
{
IEnumerable<ILanguage> UmbracoLanguages = _languageService.GetAllAsync().Result; //a helpful method to get all configured languages
var requestedCulture = UmbracoLanguages.FirstOrDefault(l => l.IsoCode == culture);

if (requestedCulture != null)
{
_variationContextAccessor.VariationContext = new VariationContext(requestedCulture.IsoCode);
}

//this will now be in the requested culture
var content = UmbracoContext.Content.GetAtRoot();

//Content requested in this View Component will now be in the requested culture
return ViewComponent();
}
}
```

### Creating a Language Switching Navigation

To navigate between languages, you need to do two key things:

1. Get all the languages that the site can provide
2. Identify the language used on the current page

Once you have these, you need to loop through the languages and provide links to each home node.

### Getting all the languages for a site

There are three ways to achieve this. The best one is to use `languageService.GetAllAsync();` which retrieves items from the cache.

Another is to use `localizationService.GetAllLanguages();` to call the database, which is expensive and ideally includes caching. This should only be done if you cannot use the ILanguage service. This service is marked as obsolete.

The alternative is to get the Home node and find all of the cultures associated with it. This has a few benefits including speed and providing us with a link to show the user. It is the process you will use when following this guide.

### Identify the language for the current page

This is achieved in `cs.html` files using `umbracoHelper.AssignedContentItem.GetCultureFromDomains();`

#### Steps

Now that you have what you need, create a view called `Navigation.cshtml`, and paste in the following:

```cshtml
@using Umbraco.Cms.Web.Common
@inject IUmbracoHelperAccessor _umbracoHelperAccessor;
@{
_umbracoHelperAccessor.TryGetUmbracoHelper(out var umbracoHelper);
var homePage = umbracoHelper.ContentAtRoot().FirstOrDefault(c => c.ContentType.Alias == "{{homeNodeContentAlias}}");
var cultures = homePage?.Cultures;
}
@if (cultures.Count > 1)
{
<ul aria-label="Language switcher">
@foreach (var cult in cultures)
{
//get the settings for this culture
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo(cult.Key);
//if the current page has a language variant, otherwise link to the homepage language variant
string langUrl = umbracoHelper.AssignedContentItem.Url(cult.Key, UrlMode.Relative) ?? homePage.Url(cult.Key, UrlMode.Relative);
<li>
@if (cult.Key.ToLower() == umbracoHelper.AssignedContentItem.GetCultureFromDomains().ToLower())
{
<span aria-current="true" >@culture.NativeName</span>
}
else
{
<a href="@langUrl" hreflang="@cult.Key" lang="@cult.Key" >@culture.NativeName</a>
}
</li>
}
</ul>
}
```

You need to replace `{{homeNodeContentAlias}}` with the Document Type alias of your Home node.

This will look at all the cultures available on the home node, and render links to either the language variant of the current page or the home node for the language variant. If the home node for a language variant is removed, it will not appear in the list.

Check warning on line 366 in 14/umbraco-cms/tutorials/multilanguage-setup.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [UmbracoDocs.SentenceLength] Write shorter sentences (less than 25 words). Raw Output: {"message": "[UmbracoDocs.SentenceLength] Write shorter sentences (less than 25 words).", "location": {"path": "14/umbraco-cms/tutorials/multilanguage-setup.md", "range": {"start": {"line": 366, "column": 1}}}, "severity": "WARNING"}
Copy link
Contributor

Choose a reason for hiding this comment

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

A suggestion to shorten this sentence a bit.

Suggested change
This will look at all the cultures available on the home node, and render links to either the language variant of the current page or the home node for the language variant. If the home node for a language variant is removed, it will not appear in the list.
This will look at all the cultures available on the home node. Links to either the language variant of the current page or the home node for the language variant will be rendered. If the home node for a language variant is removed, it will not appear in the list.


Additionally, `System.Globalization.CultureInfo` is used to obtain the native name of the language being rendered. This is useful if a user does not speak the default language.
Loading