diff --git a/Oqtane.Client/Modules/Admin/Languages/Index.razor b/Oqtane.Client/Modules/Admin/Languages/Index.razor
index e98db7d9..f6126beb 100644
--- a/Oqtane.Client/Modules/Admin/Languages/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Languages/Index.razor
@@ -19,15 +19,17 @@ else
|
@context.Name |
@context.Code |
- |
-
+ | @context.Version |
+ |
+
@if (UpgradeAvailable(context.Code))
{
@@ -50,9 +52,6 @@ else
var cultures = await LocalizationService.GetCulturesAsync();
var culture = cultures.First(c => c.Name.Equals(Constants.DefaultCulture));
- // Adds English as default language
- _languages.Insert(0, new Language { Name = culture.DisplayName, Code = culture.Name, IsDefault = !_languages.Any(l => l.IsDefault) });
-
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
_packages = await PackageService.GetPackagesAsync("translation");
@@ -81,7 +80,7 @@ else
var upgradeavailable = false;
if (_packages != null)
{
- var package = _packages.Where(item => item.PackageId == (Constants.PackageId + ".Client." + code)).FirstOrDefault();
+ var package = _packages.Where(item => item.PackageId == (Constants.ClientAssemblyName + "." + code)).FirstOrDefault();
if (package != null)
{
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) == 0);
diff --git a/Oqtane.Client/Resources/Modules/Admin/Languages/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Languages/Index.resx
index 6b8e887f..f96a90cd 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Languages/Index.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Languages/Index.resx
@@ -144,4 +144,7 @@
Delete
+
+ Translation
+
\ No newline at end of file
diff --git a/Oqtane.Client/Services/Interfaces/ILanguageService.cs b/Oqtane.Client/Services/Interfaces/ILanguageService.cs
index fd062d81..7a57e203 100644
--- a/Oqtane.Client/Services/Interfaces/ILanguageService.cs
+++ b/Oqtane.Client/Services/Interfaces/ILanguageService.cs
@@ -17,6 +17,14 @@ namespace Oqtane.Services
///
Task> GetLanguagesAsync(int siteId);
+ ///
+ /// Returns a list of all available languages for the given and client assembly
+ ///
+ ///
+ ///
+ ///
+ Task> GetLanguagesAsync(int siteId, string clientAssemblyName);
+
///
/// Returns the given language
///
diff --git a/Oqtane.Client/Services/LanguageService.cs b/Oqtane.Client/Services/LanguageService.cs
index d9657420..413c568a 100644
--- a/Oqtane.Client/Services/LanguageService.cs
+++ b/Oqtane.Client/Services/LanguageService.cs
@@ -17,18 +17,27 @@ namespace Oqtane.Services
public async Task> GetLanguagesAsync(int siteId)
{
- var languages = await GetJsonAsync>($"{Apiurl}?siteid={siteId}");
+ return await GetLanguagesAsync(siteId, "");
+ }
- return languages?.OrderBy(l => l.Name).ToList() ?? Enumerable.Empty().ToList();
+ public async Task> GetLanguagesAsync(int siteId, string clientAssemblyName)
+ {
+ return await GetJsonAsync>($"{Apiurl}?siteid={siteId}&clientassemblyname={clientAssemblyName}");
}
public async Task GetLanguageAsync(int languageId)
- => await GetJsonAsync($"{Apiurl}/{languageId}");
+ {
+ return await GetJsonAsync($"{Apiurl}/{languageId}");
+ }
public async Task AddLanguageAsync(Language language)
- => await PostJsonAsync(Apiurl, language);
+ {
+ return await PostJsonAsync(Apiurl, language);
+ }
public async Task DeleteLanguageAsync(int languageId)
- => await DeleteAsync($"{Apiurl}/{languageId}");
+ {
+ await DeleteAsync($"{Apiurl}/{languageId}");
+ }
}
}
diff --git a/Oqtane.Client/Themes/Controls/Theme/LanguageSwitcher.razor b/Oqtane.Client/Themes/Controls/Theme/LanguageSwitcher.razor
index 41219b0b..7eb94f4d 100644
--- a/Oqtane.Client/Themes/Controls/Theme/LanguageSwitcher.razor
+++ b/Oqtane.Client/Themes/Controls/Theme/LanguageSwitcher.razor
@@ -24,13 +24,9 @@
@code{
private IEnumerable _supportedCultures;
- protected override async Task OnParametersSetAsync()
+ protected override void OnParametersSet()
{
- var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
- var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
-
- languages.Add(new Language { Code = defaultCulture.Name, Name = defaultCulture.DisplayName });
-
+ var languages = PageState.Languages;
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
}
diff --git a/Oqtane.Client/UI/PageState.cs b/Oqtane.Client/UI/PageState.cs
index 5b14ad00..46eacd49 100644
--- a/Oqtane.Client/UI/PageState.cs
+++ b/Oqtane.Client/UI/PageState.cs
@@ -8,6 +8,7 @@ namespace Oqtane.UI
{
public Alias Alias { get; set; }
public Site Site { get; set; }
+ public List Languages { get; set; }
public List Pages { get; set; }
public Page Page { get; set; }
public User User { get; set; }
diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor
index f66983e0..8d75dc4f 100644
--- a/Oqtane.Client/UI/SiteRouter.razor
+++ b/Oqtane.Client/UI/SiteRouter.razor
@@ -6,6 +6,7 @@
@inject INavigationInterception NavigationInterception
@inject ISyncService SyncService
@inject ISiteService SiteService
+@inject ILanguageService LanguageService
@inject IPageService PageService
@inject IUserService UserService
@inject IModuleService ModuleService
@@ -70,6 +71,7 @@
private async Task Refresh()
{
Site site;
+ List languages;
List pages;
Page page;
User user = null;
@@ -102,7 +104,7 @@
return;
}
}
-
+
// the refresh parameter is used to refresh the client-side PageState
if (querystring.ContainsKey("refresh"))
{
@@ -173,11 +175,13 @@
if (PageState == null || refresh == UI.Refresh.Site)
{
+ languages = await LanguageService.GetLanguagesAsync(site.SiteId);
pages = await PageService.GetPagesAsync(site.SiteId);
pages = pages.Where(item => !item.IsDeleted).ToList();
}
else
{
+ languages = PageState.Languages;
pages = PageState.Pages;
}
@@ -230,6 +234,7 @@
{
Alias = SiteState.Alias,
Site = site,
+ Languages = languages,
Pages = pages,
Page = page,
User = user,
diff --git a/Oqtane.Server/Controllers/LanguageController.cs b/Oqtane.Server/Controllers/LanguageController.cs
index cbe67896..8ab3bf5b 100644
--- a/Oqtane.Server/Controllers/LanguageController.cs
+++ b/Oqtane.Server/Controllers/LanguageController.cs
@@ -1,5 +1,7 @@
using System.Collections.Generic;
+using System.IO;
using System.Net;
+using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Oqtane.Enums;
@@ -7,6 +9,9 @@ using Oqtane.Infrastructure;
using Oqtane.Models;
using Oqtane.Repository;
using Oqtane.Shared;
+using System.Linq;
+using System.Diagnostics;
+using System.Globalization;
namespace Oqtane.Controllers
{
@@ -14,23 +19,40 @@ namespace Oqtane.Controllers
public class LanguageController : Controller
{
private readonly ILanguageRepository _languages;
+ private readonly ISyncManager _syncManager;
private readonly ILogManager _logger;
private readonly Alias _alias;
- public LanguageController(ILanguageRepository language, ILogManager logger, ITenantManager tenantManager)
+ public LanguageController(ILanguageRepository language, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
{
_languages = language;
+ _syncManager = syncManager;
_logger = logger;
_alias = tenantManager.GetAlias();
}
[HttpGet]
- public IEnumerable Get(string siteid)
+ public IEnumerable Get(string siteid, string clientassemblyname)
{
int SiteId;
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
{
- return _languages.GetLanguages(SiteId);
+ if (string.IsNullOrEmpty(clientassemblyname))
+ {
+ clientassemblyname = Constants.ClientAssemblyName;
+ }
+ var languages = _languages.GetLanguages(SiteId).ToList();
+ foreach (var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), clientassemblyname + ".resources.dll", SearchOption.AllDirectories))
+ {
+ var code = Path.GetFileName(Path.GetDirectoryName(file));
+ if (languages.Any(item => item.Code == code))
+ {
+ languages.Single(item => item.Code == code).Version = FileVersionInfo.GetVersionInfo(file).FileVersion;
+ }
+ }
+ var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
+ languages.Add(new Language { Code = defaultCulture.Name, Name = defaultCulture.DisplayName, Version = Constants.Version, IsDefault = !languages.Any(l => l.IsDefault) });
+ return languages.OrderBy(item => item.Name);
}
else
{
@@ -63,6 +85,7 @@ namespace Oqtane.Controllers
if (ModelState.IsValid && language.SiteId == _alias.SiteId)
{
language = _languages.AddLanguage(language);
+ _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Language Added {Language}", language);
}
else
@@ -82,6 +105,7 @@ namespace Oqtane.Controllers
if (language != null && language.SiteId == _alias.SiteId)
{
_languages.DeleteLanguage(id);
+ _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Language Deleted {LanguageId}", id);
}
else
@@ -89,7 +113,6 @@ namespace Oqtane.Controllers
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Language Delete Attempt {LanguageId}", id);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
-
}
}
}
diff --git a/Oqtane.Server/Infrastructure/LocalizationManager.cs b/Oqtane.Server/Infrastructure/LocalizationManager.cs
index 83a9cf25..ddc25096 100644
--- a/Oqtane.Server/Infrastructure/LocalizationManager.cs
+++ b/Oqtane.Server/Infrastructure/LocalizationManager.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -21,19 +22,20 @@ namespace Oqtane.Infrastructure
}
public string GetDefaultCulture()
- => String.IsNullOrEmpty(_localizationOptions.DefaultCulture)
- ? DefaultCulture
- : _localizationOptions.DefaultCulture;
+ {
+ if (string.IsNullOrEmpty(_localizationOptions.DefaultCulture))
+ {
+ return DefaultCulture;
+ }
+ else
+ {
+ return _localizationOptions.DefaultCulture;
+ }
+ }
public string[] GetSupportedCultures()
{
- var cultures = new List(DefaultSupportedCultures);
- foreach(var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Oqtane.Client.resources.dll", SearchOption.AllDirectories))
- {
- cultures.Add(Path.GetFileName(Path.GetDirectoryName(file)));
- }
-
- return cultures.OrderBy(c => c).ToArray();
+ return CultureInfo.GetCultures(CultureTypes.AllCultures).Select(item => item.Name).OrderBy(c => c).ToArray();
}
}
}
diff --git a/Oqtane.Server/Repository/LanguageRepository.cs b/Oqtane.Server/Repository/LanguageRepository.cs
index 7f92086b..fb252fd6 100644
--- a/Oqtane.Server/Repository/LanguageRepository.cs
+++ b/Oqtane.Server/Repository/LanguageRepository.cs
@@ -13,13 +13,16 @@ namespace Oqtane.Repository
_db = context;
}
- public IEnumerable GetLanguages(int siteId) => _db.Language.Where(l => l.SiteId == siteId);
+ public IEnumerable GetLanguages(int siteId)
+ {
+ return _db.Language.Where(l => l.SiteId == siteId);
+ }
public Language AddLanguage(Language language)
{
if (language.IsDefault)
{
- // Ensure all other languages are not set to current
+ // Ensure all other languages are not set to default
_db.Language
.Where(l => l.SiteId == language.SiteId)
.ToList()
@@ -32,7 +35,10 @@ namespace Oqtane.Repository
return language;
}
- public Language GetLanguage(int languageId) => _db.Language.Find(languageId);
+ public Language GetLanguage(int languageId)
+ {
+ return _db.Language.Find(languageId);
+ }
public void DeleteLanguage(int languageId)
{
diff --git a/Oqtane.Shared/Models/Language.cs b/Oqtane.Shared/Models/Language.cs
index ef81a78d..a75d0685 100644
--- a/Oqtane.Shared/Models/Language.cs
+++ b/Oqtane.Shared/Models/Language.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel.DataAnnotations.Schema;
namespace Oqtane.Models
{
@@ -34,6 +35,12 @@ namespace Oqtane.Models
///
public bool IsDefault { get; set; }
+ [NotMapped]
+ ///
+ /// Version of the satellite assembly
+ ///
+ public string Version { get; set; }
+
#region IAuditable Properties
///
diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs
index 1d1b4fe7..087cec0d 100644
--- a/Oqtane.Shared/Shared/Constants.cs
+++ b/Oqtane.Shared/Shared/Constants.cs
@@ -9,6 +9,7 @@ namespace Oqtane.Shared
public const string PackageId = "Oqtane.Framework";
public const string UpdaterPackageId = "Oqtane.Updater";
public const string PackageRegistryUrl = "https://www.oqtane.net";
+ public const string ClientAssemblyName = "Oqtane.Client";
public const string DefaultDBType = "Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer";
|