diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs index 8064ff99d2..5f53694177 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs @@ -16,10 +16,14 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations public string DefaultResourceName { get; set; } + public Dictionary> LanguagesMap { get; set; } + + public Dictionary> LanguageFilesMap { get; set; } + public ApplicationLocalizationConfigurationDto() { Values = new Dictionary>(); Languages = new List(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationContext.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationContext.cs index 5d45f9c7e8..98fe3546c5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationContext.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationContext.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Options; +using Volo.Abp.Localization; namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling { @@ -8,8 +11,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling { public List Files { get; } - public IServiceProvider ServiceProvider { get; } - public IFileProvider FileProvider { get; } public BundleConfigurationContext(IServiceProvider serviceProvider, IFileProvider fileProvider) @@ -18,5 +19,29 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling ServiceProvider = serviceProvider; FileProvider = fileProvider; } + + public IServiceProvider ServiceProvider { get; } + private readonly object _serviceProviderLock = new object(); + + private TRef LazyGetRequiredService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + lock (_serviceProviderLock) + { + if (reference == null) + { + reference = (TRef)ServiceProvider.GetRequiredService(serviceType); + } + } + } + + return reference; + } + + private IOptions _abpLocalizationOptions; + + public AbpLocalizationOptions LocalizationOptions => + LazyGetRequiredService(typeof(IOptions), ref _abpLocalizationOptions).Value; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs index ec82d4b3d6..617b5a28ff 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs @@ -1,4 +1,6 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker; +using Volo.Abp.Localization; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Packages @@ -6,6 +8,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages [DependsOn(typeof(AbpAspNetCoreMvcUiBundlingModule))] public class AbpAspNetCoreMvcUiPackagesModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddLanguageFilesMap(BootstrapDatepickerScriptContributor.PackageName, + new NameValue("zh-Hans", "zh-CN")); + }); + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs index fb29a8f2a5..ca852972d8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Globalization; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; +using Volo.Abp.Localization; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker @@ -9,11 +10,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker [DependsOn(typeof(JQueryScriptContributor))] public class BootstrapDatepickerScriptContributor : BundleContributor { - public static readonly Dictionary CultureMap = new Dictionary - { - {"zh-Hans", "zh-CN"} - }; - + public const string PackageName = "bootstrap-datepicker"; + public override void ConfigureBundle(BundleConfigurationContext context) { context.Files.AddIfNotContains("/libs/bootstrap-datepicker/bootstrap-datepicker.min.js"); @@ -26,12 +24,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker ? "en" : CultureInfo.CurrentUICulture.Name; - TryAddCultureFile(context, MapCultureName(cultureName)); + TryAddCultureFile(context, cultureName); } protected virtual bool TryAddCultureFile(BundleConfigurationContext context, string cultureName) { - var filePath = $"/libs/bootstrap-datepicker/locales/bootstrap-datepicker.{cultureName}.min.js"; + var fileName = context.LocalizationOptions.GetLanguageFilesMap(PackageName, cultureName); + var filePath = $"/libs/bootstrap-datepicker/locales/bootstrap-datepicker.{fileName}.min.js"; if (!context.FileProvider.GetFileInfo(filePath).Exists) { @@ -41,11 +40,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker context.Files.AddIfNotContains(filePath); return true; } - - protected virtual string MapCultureName(string cultureName) - { - return CultureMap.GetOrDefault(cultureName) ?? - cultureName; - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/JQueryValidation/JQueryValidationScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/JQueryValidation/JQueryValidationScriptContributor.cs index b4acf05ec6..586d8864cd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/JQueryValidation/JQueryValidationScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/JQueryValidation/JQueryValidationScriptContributor.cs @@ -2,6 +2,7 @@ using System.Globalization; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; +using Volo.Abp.Localization; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation @@ -11,6 +12,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation { public const string DefaultLocalizationFolder = "/libs/jquery-validation/localization/"; + public const string PackageName = "jquery-validation"; + public override void ConfigureBundle(BundleConfigurationContext context) { context.Files.AddIfNotContains("/libs/jquery-validation/jquery.validate.js"); @@ -25,7 +28,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation var cultureName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Replace('-', '_'); - if (TryAddCultureFile(context, MapCultureName(cultureName))) + var fileName = context.LocalizationOptions.GetLanguageFilesMap(PackageName, cultureName); + if (TryAddCultureFile(context, fileName)) { return; } @@ -35,7 +39,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation return; } - TryAddCultureFile(context, MapCultureName(cultureName.Substring(0, cultureName.IndexOf('_')))); + fileName = context.LocalizationOptions.GetLanguageFilesMap(PackageName, + cultureName.Substring(0, cultureName.IndexOf('_'))); + TryAddCultureFile(context, fileName); } protected virtual bool TryAddCultureFile(BundleConfigurationContext context, string cultureName) @@ -51,10 +57,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation context.Files.AddIfNotContains(filePath); return true; } - - protected virtual string MapCultureName(string cultureName) - { - return cultureName; - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs index 6ad5b3276e..5aa8f07059 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs @@ -171,6 +171,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations ); } + localizationConfig.LanguagesMap = _localizationOptions.LanguagesMap; + localizationConfig.LanguageFilesMap = _localizationOptions.LanguageFilesMap; + return localizationConfig; } @@ -267,4 +270,4 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations }; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs index aba376d773..8974237f7d 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs @@ -17,11 +17,17 @@ namespace Volo.Abp.Localization public List Languages { get; } + public Dictionary> LanguagesMap { get; } + + public Dictionary> LanguageFilesMap { get; } + public AbpLocalizationOptions() { Resources = new LocalizationResourceDictionary(); GlobalContributors = new TypeList(); Languages = new List(); + LanguagesMap = new Dictionary>(); + LanguageFilesMap = new Dictionary>(); } } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptionsExtensions.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptionsExtensions.cs new file mode 100644 index 0000000000..936642b1ff --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptionsExtensions.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Localization +{ + public static class AbpLocalizationOptionsExtensions + { + public static AbpLocalizationOptions AddLanguagesMap(this AbpLocalizationOptions localizationOptions, string packageName, params NameValue[] maps) + { + if (localizationOptions.LanguagesMap.TryGetValue(packageName, out var existMaps)) + { + existMaps.AddRange(maps); + } + else + { + localizationOptions.LanguagesMap.Add(packageName, maps.ToList()); + } + + return localizationOptions; + } + + public static string GetLanguagesMap(this AbpLocalizationOptions localizationOptions, string packageName, + string language) + { + return localizationOptions.LanguagesMap.TryGetValue(packageName, out var maps) + ? maps.FirstOrDefault(x => x.Name == language)?.Value ?? language + : language; + } + + public static AbpLocalizationOptions AddLanguageFilesMap(this AbpLocalizationOptions localizationOptions, string packageName, params NameValue[] maps) + { + if (localizationOptions.LanguageFilesMap.TryGetValue(packageName, out var existMaps)) + { + existMaps.AddRange(maps); + } + else + { + localizationOptions.LanguageFilesMap.Add(packageName, maps.ToList()); + } + + return localizationOptions; + } + + public static string GetLanguageFilesMap(this AbpLocalizationOptions localizationOptions, string packageName, + string language) + { + return localizationOptions.LanguageFilesMap.TryGetValue(packageName, out var maps) + ? maps.FirstOrDefault(x => x.Name == language)?.Value ?? language + : language; + } + } +} diff --git a/npm/packs/core/src/abp.js b/npm/packs/core/src/abp.js index 190143da03..fa5d27fe41 100644 --- a/npm/packs/core/src/abp.js +++ b/npm/packs/core/src/abp.js @@ -136,6 +136,38 @@ var abp = abp || {}; }; abp.localization.defaultResourceName = undefined; + abp.localization.currentCulture = { + cultureName: undefined + }; + + var getMapValue = function (packageMaps, packageName, language) { + language = language || abp.localization.currentCulture.cultureName; + if (!packageMaps || !packageName || !language) { + return language; + } + + var packageMap = packageMaps[packageName]; + if (!packageMap) { + return language; + } + + for (var i = 0; i < packageMap.length; i++) { + var map = packageMap[i]; + if (map.name === language){ + return map.value; + } + } + + return language; + }; + + abp.localization.getLanguagesMap = function (packageName, language) { + return getMapValue(abp.localization.languagesMap, packageName, language); + }; + + abp.localization.getLanguageFilesMap = function (packageName, language) { + return getMapValue(abp.localization.languageFilesMap, packageName, language); + }; /* AUTHORIZATION **********************************************/ @@ -330,7 +362,7 @@ var abp = abp || {}; }; /* opts: { - * + * * } */ abp.ui.unblock = function (opts) { @@ -584,7 +616,7 @@ var abp = abp || {}; * This is a simple implementation created to be used by ABP. * Please use a complete cookie library if you need. * @param {string} key - * @param {string} value + * @param {string} value * @param {Date} expireDate (optional). If not specified the cookie will expire at the end of session. * @param {string} path (optional) */