diff --git a/AdminMenu.cs b/AdminMenu.cs index dcfdfd9..5ca0de3 100644 --- a/AdminMenu.cs +++ b/AdminMenu.cs @@ -11,14 +11,15 @@ public class AdminMenu : INavigationProvider public void GetNavigation(NavigationBuilder builder) { - builder - .AddImageSet("Translations") - .Add(T("Translations"), "20", menu => menu.Action("Index", "Admin", new { area = "Q42.DbTranslations" }) - .Add(T("Translate"), "0", item => item.Action("Index", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) - .Add(T("Import"), "1", item => item.Action("Import", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) - .Add(T("Export"), "2", item => item.Action("Export", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) - .Add(T("Search"), "3", item => item.Action("Search", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) - ); + builder + .AddImageSet("Translations") + .Add(T("Translations"), "20", menu => menu.Action("Index", "Admin", new { area = "Q42.DbTranslations" }) + .Add(T("Translate"), "0", item => item.Action("Index", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) + .Add(T("Import"), "1", item => item.Action("Import", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) + .Add(T("Export"), "2", item => item.Action("Export", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) + .Add(T("Search"), "3", item => item.Action("Search", "Admin", new { area = "Q42.DbTranslations" }).LocalNav()) + .Add(T("Extra"), "4", item => item.Action("Extra", "Admin", new { area = "Q42.DbTranslations"}).LocalNav()) + ); } } diff --git a/Controllers/AdminController.cs b/Controllers/AdminController.cs index 791ae7e..6a0b7fb 100644 --- a/Controllers/AdminController.cs +++ b/Controllers/AdminController.cs @@ -90,6 +90,31 @@ public ActionResult Search(string querystring, string culture) return View(cultures); } + public ActionResult Extra(string moduleName = "") + { + if (!Services.Authorizer.Authorize(Permissions.UploadTranslation)) + return RedirectToAction("Index"); + ViewBag.selectedModule = ""; + if (moduleName != "") + { + ViewBag.selectedModule = moduleName; + var selectedAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(item => item.FullName.Contains(moduleName)).FirstOrDefault(); + + if (selectedAssembly != null) + { + ViewBag.Assemblies = selectedAssembly.GetReferencedAssemblies().OrderBy(e => e.Name); + + } + } + + var extensions = _extensionManager.AvailableExtensions(); + ViewBag.Modules = extensions + .Where(e => DefaultExtensionTypes.IsModule(e.ExtensionType)) + .OrderBy(e => e.Name); + + return View(); + } + public ActionResult Culture(string culture) { if (culture == null) throw new HttpException(404, "Not found"); @@ -338,5 +363,22 @@ public ActionResult FromFeature(string culture, string path, string type) _localizationService.ResetCache(); return RedirectToAction("Import"); } + + public ActionResult FromAssembly(string referencedAssemblyName, string selectedModule) + { + //do stuff to get translations + var translations = ManagementService.ExtractTranslationsFromAssembly(referencedAssemblyName, selectedModule); + + //Save the strings to the database + _localizationService.SaveStringsToDatabase(translations, false); + + //do the notifier thing + Services.Notifier.Add(NotifyType.Information, T("Imported {0} translatable strings", translations.Count())); + + //Reset Cache + _localizationService.ResetCache(); + //do the redirect + return RedirectToAction("Extra"); + } } } \ No newline at end of file diff --git a/Q42.DbTranslations.csproj b/Q42.DbTranslations.csproj index 88dbc7f..eb0307b 100644 --- a/Q42.DbTranslations.csproj +++ b/Q42.DbTranslations.csproj @@ -137,6 +137,7 @@ + diff --git a/Services/LocalizationManagementService.cs b/Services/LocalizationManagementService.cs index b1a5b23..ac3f2a4 100644 --- a/Services/LocalizationManagementService.cs +++ b/Services/LocalizationManagementService.cs @@ -8,6 +8,8 @@ using Orchard; using Q42.DbTranslations.Models; using Path = Fluent.IO.Path; +using System.ComponentModel.DataAnnotations; +using Orchard.Localization; namespace Q42.DbTranslations.Services { @@ -16,6 +18,7 @@ public interface ILocalizationManagementService : IDependency void InstallTranslation(byte[] zippedTranslation, string sitePath); byte[] PackageTranslations(string cultureCode, string sitePath); IEnumerable ExtractDefaultTranslation(string sitePath, string targetSitePath); + IEnumerable ExtractTranslationsFromAssembly(string assemblyName, string moduleName); void SyncTranslation(string sitePath, string cultureCode); } @@ -75,6 +78,59 @@ public byte[] PackageTranslations(string cultureCode, string sitePath) p => site.Combine(p).ReadBytes()); } + /// + /// This method goes through a selected assembly to get all data-Annotations (validation) for that assembly. + /// + /// The name (not fullname) of the referenced Assembly + /// The name (not fullname) of the module where the keys are needed + /// A list of StringEntries to be instered into the Q42 DB + public IEnumerable ExtractTranslationsFromAssembly(string assemblyName, string moduleName) + { + var result = new List(); + + var stringList = new List(); + //declarations + var referencedAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(e => e.FullName.Contains(assemblyName)).FirstOrDefault(); + var annotationList = new List {"Required", "RegularExpression", "Range", "StringLength" }; + var path = GetModuleLocalizationPath(null, moduleName).Replace('\\', '/'); + + //Get the Data-Annotations Error Msgs for the Assembly using Reflection + if(referencedAssembly != null){ + var Types = referencedAssembly.GetTypes(); + foreach (var t in Types) + { + var properties = t.GetProperties(); + foreach (var propertyInfo in properties) + { + foreach (var customAttr in propertyInfo.GetCustomAttributesData()) + { + if(annotationList.Any(customAttr.Constructor.DeclaringType.Name.Contains)) + { + var firstOrDefault = customAttr.NamedArguments.Where(i => i.MemberInfo.Name.ToString() == "ErrorMessage").Select(i => i.TypedValue.Value).FirstOrDefault(); + if (firstOrDefault != null) + { + var key = (firstOrDefault.ToString() + ); + result.Add(new StringEntry + { + Culture = null, + Context = customAttr.Constructor.DeclaringType.FullName, + Key = key, + English = key, + Translation = key, + Path = path + }); + } + } + } + } + } + } + + //done --> return result + return result; + } + public IEnumerable ExtractDefaultTranslation(string sitePath, string targetSitePath) { var result = new List(); diff --git a/Views/Admin/Extra.cshtml b/Views/Admin/Extra.cshtml new file mode 100644 index 0000000..bd2c942 --- /dev/null +++ b/Views/Admin/Extra.cshtml @@ -0,0 +1,49 @@ +@using System.Globalization + +@{ + Layout.Title = "Database translations"; +} + + +
+

@T("Generate from referenced Assemblies")

+

@T("This will get the translation keys for DataAnnotations from the referenced Assemblies. Select the module, then select the referenced Assembly you want to parse")

+

+

+ + +
+

+ @{ + if (ViewBag.Assemblies != null) + { +

+

+ + + +
+

+ } + } + +
+

 

+