Localization
Add multi-language support to your nopCommerce plugins.
XML Resource Files (Recommended)
The recommended approach is to use XML resource files located in Localization/ folder:
File Structure
Localization/
└── pluginResources.en-us.xmlXML File Format
xml
<?xml version="1.0" encoding="utf-8"?>
<Language Name="English" Supported="true">
<LocaleResource Name="Plugins.Misc.PluginTemplate.Title">
<Value>My Plugin</Value>
</LocaleResource>
<LocaleResource Name="Plugins.Misc.PluginTemplate.Settings.Enabled">
<Value>Enable plugin</Value>
</LocaleResource>
<LocaleResource Name="Plugins.Misc.PluginTemplate.Settings.Enabled.Hint">
<Value>Check to enable the plugin functionality</Value>
</LocaleResource>
<LocaleResource Name="Plugins.Misc.PluginTemplate.Settings.ApiKey">
<Value>API Key</Value>
</LocaleResource>
</Language>Loading XML Resources in Plugin.cs
csharp
// Plugin.cs
using System.Text;
using Nop.Core.Infrastructure;
using Nop.Services.Localization;
public class Plugin : BasePlugin, IMiscPlugin
{
#region Fields
private readonly ILanguageService _languageService;
private readonly ILocalizationService _localizationService;
private readonly ILogger _logger;
#endregion
#region Ctor
public Plugin(
ILanguageService languageService,
ILocalizationService localizationService,
ILogger logger)
{
_languageService = languageService;
_localizationService = localizationService;
_logger = logger;
}
#endregion
#region Methods
public override async Task InstallAsync()
{
await InstallLocalResourcesFromXmlFileAsync();
await base.InstallAsync();
}
public override async Task UpdateAsync(string currentVersion, string targetVersion)
{
if (!currentVersion.Equals(targetVersion))
await InstallLocalResourcesFromXmlFileAsync();
await base.UpdateAsync(currentVersion, targetVersion);
}
#endregion
#region Utilities
private Language GetDefaultEnglishLanguage()
{
return _languageService.GetAllLanguages()
.FirstOrDefault(x => x.UniqueSeoCode
.Equals("en", StringComparison.InvariantCultureIgnoreCase));
}
private async Task InstallLocalResourcesFromXmlFileAsync()
{
var language = GetDefaultEnglishLanguage();
if (language == null)
{
_logger.Error("Can't add resource strings. Required language not found!");
return;
}
try
{
var fileProvider = EngineContext.Current.Resolve<INopFileProvider>();
var path = fileProvider.MapPath(PluginDefaults.XmlResourceStringFilePath);
using var sr = new StreamReader(path, Encoding.UTF8);
await _localizationService.ImportResourcesFromXmlAsync(language, sr);
}
catch (Exception ex)
{
_logger.Error("Error processing resource string XML file.", ex);
}
}
#endregion
}PluginDefaults.cs
csharp
namespace NopStation.Plugin.Misc.PluginTemplate;
public class PluginDefaults
{
public static string XmlResourceStringFilePath =>
"~/Plugins/NopStation.Plugin.Misc.PluginTemplate/Localization/pluginResources.en-us.xml";
public static string PluginSystemName => "NopStation.Plugin.Misc.PluginTemplate";
}Programmatic Approach
For simpler plugins, add resources directly:
csharp
public override async Task InstallAsync()
{
var localizationService = EngineContext.Current.Resolve<ILocalizationService>();
await localizationService.AddOrUpdateLocaleResourceAsync(new Dictionary<string, string>
{
["Plugins.Widgets.MyPlugin.Title"] = "My Plugin",
["Plugins.Widgets.MyPlugin.Settings.Enabled"] = "Enable plugin",
["Plugins.Widgets.MyPlugin.Settings.ApiKey"] = "API Key",
});
await base.InstallAsync();
}
public override async Task UninstallAsync()
{
var localizationService = EngineContext.Current.Resolve<ILocalizationService>();
await localizationService.DeleteLocaleResourcesAsync("Plugins.Widgets.MyPlugin");
await base.UninstallAsync();
}Using Localized Strings
In Controllers
csharp
var title = await _localizationService.GetResourceAsync("Plugins.Misc.PluginTemplate.Title");In Views
html
@inherits Nop.Web.Framework.Mvc.Razor.NopRazorPage<TModel>
<h1>@T("Plugins.Misc.PluginTemplate.Title")</h1>Best Practices
- Use XML files - Easier to manage and update across versions
- Use consistent naming - Follow
Plugins.{Type}.{Name}.{Key}pattern - Provide hints - Add
.Hintresources for complex fields - Update on plugin update - Reload resources when version changes
- Clean up on uninstall - Delete resources when uninstalling