Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
71 changes: 34 additions & 37 deletions src/OrchardCoreContrib.DataLocalization/AdminMenu.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,46 @@
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Localization;
using OrchardCore.Navigation;

namespace OrchardCoreContrib.DataLocalization;

using OrchardCoreContrib.Navigation;

namespace OrchardCore.DataLocalization
/// <summary>
/// Represents a localization menu in the admin site.
/// </summary>
/// <remarks>
/// Creates a new instance of the <see cref="AdminMenu"/>.
/// </remarks>
/// <param name="S">The <see cref="IStringLocalizer"/>.</param>
public class AdminMenu(IStringLocalizer<AdminMenu> S) : AdminNavigationProvider
{
using OrchardCoreContrib.Navigation;

/// <summary>
/// Represents a localization menu in the admin site.
/// </summary>
public class AdminMenu : AdminNavigationProvider
private static readonly RouteValueDictionary _routeValues = new()
{
private readonly IStringLocalizer S;
{ "area", "OrchardCoreContrib.DataLocalization" }
};

/// <summary>
/// Creates a new instance of the <see cref="AdminMenu"/>.
/// </summary>
/// <param name="localizer">The <see cref="IStringLocalizer"/>.</param>
public AdminMenu(IStringLocalizer<AdminMenu> localizer)
{
S = localizer;
}

///<inheritdocs />
public override void BuildNavigation(NavigationBuilder builder)
{
builder
.Add(S["Configuration"], NavigationConstants.AdminMenuConfigurationPosition, localization => localization
.Add(S["Settings"], settings => settings
.Add(S["Localization"], localization => localization
.AddClass("localization").Id("localization")
.Add(S["Data Resources"], S["Data Resources"].PrefixPosition(), data => data
.AddClass("data-resources").Id("data-resources")
.Add(S["Content Types"], S["Content Types"].PrefixPosition(), type => type
.Action("ManageContentTypeResources", "Admin", new { area = "OrchardCoreContrib.DataLocalization" })
.LocalNav()
)
.Add(S["Content Fields"], S["Content Fields"].PrefixPosition(), type => type
.Action("ManageContentFieldResources", "Admin", new { area = "OrchardCoreContrib.DataLocalization" })
.LocalNav()
)
///<inheritdocs />
public override void BuildNavigation(NavigationBuilder builder)
{
builder
.Add(S["Configuration"], NavigationConstants.AdminMenuConfigurationPosition, localization => localization
.Add(S["Settings"], settings => settings
.Add(S["Localization"], localization => localization
.AddClass("localization").Id("localization")
.Add(S["Data Resources"], S["Data Resources"].PrefixPosition(), data => data
.AddClass("data-resources").Id("data-resources")
.Add(S["Content Types"], S["Content Types"].PrefixPosition(), type => type
.Action("ManageContentTypeResources", "Admin", _routeValues)
.LocalNav()
)
.Add(S["Content Fields"], S["Content Fields"].PrefixPosition(), type => type
.Action("ManageContentFieldResources", "Admin", _routeValues)
.LocalNav()
)
)
)
);
}
)
);
}
}
220 changes: 100 additions & 120 deletions src/OrchardCoreContrib.DataLocalization/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,160 +8,140 @@
using OrchardCoreContrib.DataLocalization.ViewModels;
using OrchardCoreContrib.Localization;
using OrchardCoreContrib.Localization.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace OrchardCoreContrib.DataLocalization.Controllers
namespace OrchardCoreContrib.DataLocalization.Controllers;

public class AdminController(
IContentDefinitionService contentDefinitionService,
IEnumerable<IDataResourceStringProvider> dataResourceStringProviders,
TranslationsManager translationsManager,
IMemoryCache memoryCache,
IHtmlLocalizer<AdminController> H,
INotifier notifier) : Controller
{
public class AdminController : Controller
private const string ResourcesCachePrefix = "OCC-CultureDictionary-";
private const string AntiForgeryTokenKey = "__RequestVerificationToken";

public async Task<ActionResult> ManageContentTypeResources([FromQuery] string selectedCulture)
{
private const string ResourcesCachePrefix = "OCC-CultureDictionary-";
private const string AntiForgeryTokenKey = "__RequestVerificationToken";

private readonly IContentDefinitionService _contentDefinitionService;
private readonly IEnumerable<IDataResourceStringProvider> _dataResourceStringProviders;
private readonly TranslationsManager _translationsManager;
private readonly IMemoryCache _memoryCache;
private readonly INotifier _notifier;
private readonly IHtmlLocalizer H;

public AdminController(
IContentDefinitionService contentDefinitionService,
IEnumerable<IDataResourceStringProvider> dataResourceStringProviders,
TranslationsManager translationsManager,
IMemoryCache memoryCache,
IHtmlLocalizer<AdminController> htmlLocalizer,
INotifier notifier)
{
_contentDefinitionService = contentDefinitionService;
_dataResourceStringProviders = dataResourceStringProviders;
_translationsManager = translationsManager;
_memoryCache = memoryCache;
_notifier = notifier;
H = htmlLocalizer;
}
var resourcesNames = await GetResourcesNamesAsync(ContentTypeResourceStringProvider.Context);

var translationsDocument = await translationsManager.GetTranslationsDocumentAsync();

public async Task<ActionResult> ManageContentTypeResources([FromQuery] string selectedCulture)
var viewModel = new ContentTypeResourcesViewModel
{
var resourcesNames = await GetResourcesNamesAsync(ContentTypeResourceStringProvider.Context);
ResourcesNames = resourcesNames,
Translations = [],
SelectedCulture = selectedCulture
};

var translationsDocument = await _translationsManager.GetTranslationsDocumentAsync();
if (!string.IsNullOrEmpty(selectedCulture) &&
translationsDocument.Translations.TryGetValue(selectedCulture, out IEnumerable<Translation> value))
{
viewModel.Translations = value;
}

var viewModel = new ContentTypeResourcesViewModel
{
ResourcesNames = resourcesNames,
Translations = Enumerable.Empty<Translation>(),
SelectedCulture = selectedCulture
};
return View(viewModel);
}

if (!String.IsNullOrEmpty(selectedCulture) && translationsDocument.Translations.ContainsKey(selectedCulture))
{
viewModel.Translations = translationsDocument.Translations[selectedCulture];
}
[HttpPost]
[ActionName(nameof(ManageContentTypeResources))]
public async Task<ActionResult> ManageContentTypeResourcesPost([FromQuery] string selectedCulture)
{
await UpdateResourcesAsync(ContentTypeResourceStringProvider.Context, selectedCulture);

return View(viewModel);
}
return RedirectToAction(nameof(ManageContentTypeResources), new { selectedCulture });
}

[HttpPost]
[ActionName(nameof(ManageContentTypeResources))]
public async Task<ActionResult> ManageContentTypeResourcesPost([FromQuery] string selectedCulture)
{
await UpdateResourcesAsync(ContentTypeResourceStringProvider.Context, selectedCulture);
public async Task<ActionResult> ManageContentFieldResources([FromQuery] string selectedCulture, [FromQuery] string contentType)
{
var context = $"{contentType}-{ContentFieldResourceStringProvider.Context}";
var resourcesNames = await GetResourcesNamesAsync(context);

return RedirectToAction(nameof(ManageContentTypeResources), new { selectedCulture });
}
var translationsDocument = await translationsManager.GetTranslationsDocumentAsync();

public async Task<ActionResult> ManageContentFieldResources([FromQuery] string selectedCulture, [FromQuery] string contentType)
var viewModel = new ContentFieldResourcesViewModel
{
var context = $"{contentType}-{ContentFieldResourceStringProvider.Context}";
var resourcesNames = await GetResourcesNamesAsync(context);
ContentTypes = (await contentDefinitionService.GetTypesAsync()).Select(t => t.Name),
ResourcesNames = resourcesNames,
Translations = [],
SelectedContentType = contentType,
SelectedCulture = selectedCulture
};

if (!string.IsNullOrEmpty(selectedCulture) &&
translationsDocument.Translations.TryGetValue(selectedCulture, out IEnumerable<Translation> value))
{
viewModel.Translations = value;
}

var translationsDocument = await _translationsManager.GetTranslationsDocumentAsync();
return View(viewModel);
}

var viewModel = new ContentFieldResourcesViewModel
{
ContentTypes = (await _contentDefinitionService.GetTypesAsync()).Select(t => t.Name),
ResourcesNames = resourcesNames,
Translations = Enumerable.Empty<Translation>(),
SelectedContentType = contentType,
SelectedCulture = selectedCulture
};

if (!String.IsNullOrEmpty(selectedCulture) && translationsDocument.Translations.ContainsKey(selectedCulture))
{
viewModel.Translations = translationsDocument.Translations[selectedCulture];
}
[HttpPost]
[ActionName(nameof(ManageContentFieldResources))]
public async Task<ActionResult> ManageContentFieldResourcesPost([FromQuery] string selectedCulture, [FromQuery] string contentType)
{
var context = $"{contentType}-{ContentFieldResourceStringProvider.Context}";

await UpdateResourcesAsync(context, selectedCulture);

return View(viewModel);
}
return RedirectToAction(nameof(ManageContentFieldResources), new { selectedCulture, contentType });
}

[HttpPost]
[ActionName(nameof(ManageContentFieldResources))]
public async Task<ActionResult> ManageContentFieldResourcesPost([FromQuery] string selectedCulture, [FromQuery] string contentType)
private async Task<IEnumerable<string>> GetResourcesNamesAsync(string context)
{
IEnumerable<string> resourcesNames = null;
foreach (var dataResourceStringProvider in dataResourceStringProviders)
{
var context = $"{contentType}-{ContentFieldResourceStringProvider.Context}";

await UpdateResourcesAsync(context, selectedCulture);
resourcesNames = (await dataResourceStringProvider.GetAllResourceStringsAsync(context))
.Select(r => r.GetMessageId());

return RedirectToAction(nameof(ManageContentFieldResources), new { selectedCulture, contentType });
if (resourcesNames.Any())
{
break;
}
}

private async Task<IEnumerable<string>> GetResourcesNamesAsync(string context)
{
IEnumerable<string> resourcesNames = null;
foreach (var dataResourceStringProvider in _dataResourceStringProviders)
{
resourcesNames = (await dataResourceStringProvider.GetAllResourceStringsAsync(context))
.Select(r => r.GetMessageId());
return resourcesNames;
}

if (resourcesNames.Any())
{
break;
}
}
private async Task UpdateResourcesAsync(string context, string culture)
{
var translations = new List<Translation>();

return resourcesNames;
}
var translationsDocument = await translationsManager.GetTranslationsDocumentAsync();

private async Task UpdateResourcesAsync(string context, string culture)
if (translationsDocument.Translations.TryGetValue(culture, out IEnumerable<Translation> translationsValue))
{
var translations = new List<Translation>();
translations = [.. translationsValue];
}

var translationsDocument = await _translationsManager.GetTranslationsDocumentAsync();
foreach (var key in Request.Form.Keys.Where(k => !k.Equals(AntiForgeryTokenKey)))
{
var value = Request.Form[key].ToString();
var index = translations.FindIndex(t => t.Context == context && t.Key == key);

if (translationsDocument.Translations.ContainsKey(culture))
if (index > -1)
{
translations = translationsDocument.Translations[culture].ToList();
translations[index].Value = value;
}

foreach (var key in Request.Form.Keys.Where(k => !k.Equals(AntiForgeryTokenKey)))
else
{
var value = Request.Form[key].ToString();
var index = translations.FindIndex(t => t.Context == context && t.Key == key);

if (index > -1)
{
translations[index].Value = value;
}
else
translations.Add(new Translation
{
translations.Add(new Translation
{
Context = context,
Key = key,
Value = value
});
}
Context = context,
Key = key,
Value = value
});
}
}

await _translationsManager.UpdateTranslationAsync(culture, translations);
await translationsManager.UpdateTranslationAsync(culture, translations);

// Purge the resource cache
_memoryCache.Remove(ResourcesCachePrefix + culture);
// Purge the resource cache
memoryCache.Remove(ResourcesCachePrefix + culture);

await _notifier.SuccessAsync(H["The resource has been saved successfully."]);
}
await notifier.SuccessAsync(H["The resource has been saved successfully."]);
}
}
Loading
Loading