-
Notifications
You must be signed in to change notification settings - Fork 10
2.5 Localization
Language localization is the process of adapting text with translation to a specific country or region. It is the second phase of a larger process of product translation and cultural adaptation (for specific countries, regions, cultures or groups) to account for differences in distinct markets, a process known as internationalization and localization.
Signals offers multiple implementations for the Communication channels aspect out of the box:
- Signals.Aspects.Localization.File
- Signals.Aspects.Localization.Database
Only one implementation can be active at a time.
First we must define a file or database with key-value pairs with translated messages for each culture we need. Files must have property "Copy to Output Directory"
set to "Copy always"
.
File example in file example.en-US.app:
{
"MySpecification": "My property is required",
"MyKey": "My value",
}
When we implement any type of process a localization provider is automatically injected in the process context. Every time there is a falied specification the localization provider searches for a translation based on the failed specification class name and returns a user visible message with the translated value.
public class MyProcess : BusinessProcess<VoidResult>
{
/// <summary>
/// Authenticate process
/// </summary>
/// <returns></returns>
public override VoidResult Auth()
{
return Ok();
}
/// <summary>
/// Validate process
/// </summary>
/// <returns></returns>
public override VoidResult Validate()
{
// if the specification fails
// it will return failed result with error message "My property is required"
// based on the file described above
return BeginValidation()
.Validate(new MySpecification())
.ReturnResult();
}
/// <summary>
/// Handle process
/// </summary>
/// <returns></returns>
public override VoidResult Handle()
{
var translation = Context.LocalizationProvider.Get("MyKey");
return Ok();
}
}
Other more manual way of using the localization aspect is through the ILocalizationProvider
instance.
public string GetTranslation(string key)
{
var localizationProvider = SystemBootstrapper.GetInstance<ILocalizationProvider>();
var translation = localizationProvider.Get(key);
return translation ?? $"Translation for {key} was not found";
}
public string GetTranslationFromFile(string key, string file)
{
var localizationProvider = SystemBootstrapper.GetInstance<ILocalizationProvider>();
var translation = localizationProvider.Get(key, file);
return translation ?? $"Translation for {key} was not found";
}
public string GetTranslationFromFolderAndFile(string key, string file, string folder)
{
var localizationProvider = SystemBootstrapper.GetInstance<ILocalizationProvider>();
var translation = localizationProvider.Get(key, file, folder);
return translation ?? $"Translation for {key} was not found";
}
We configure the localization aspect by using an instance of Signals.Aspects.Localization.ILocalizationConfiguration
which we pass in the ApplicationBootstrapConfiguration
instance (web or background) at startup.
-
DirectoryPath
: Root directory of json files. Default AppDomain.CurrentDomain.BaseDirectory -
FileExtension
: File extension of localization files. Default “app”` -
LocalizationSources
: List of localization files -
Name
: Collection name -
SourcePath
: Subfolder name
-
ConnectionString
: Connection string to database -
LocalizationEntryTableName
: Default "LocalizationEntry" -
LocalizationCollectionTableName
: Default "LocalizationCollection" -
LocalizationCategoryTableName
: Default "LocalizationCategory" -
LocalizationKeyTableName
: Default "LocalizationKey" -
LocalizationLanguageTableName
: Default "LocalizationLanguage"
Using Signals.Aspects.Localization.File
services
.AddSignals(config =>
{
config.LocalizationConfiguration = new JsonDataProviderConfiguration
{
DirectoryPath = Path.Combine(AppContext.BaseDirectory, "system.resources"),
FileExtension = "app",
LocalizationSources = new List<LocalizationSource>
{
new LocalizationSource
{
Name = "Mail messages",
SourcePath = "mailmessages"
},
new LocalizationSource
{
Name = "Validation rules",
SourcePath = "validationrules"
},
new LocalizationSource
{
Name = "Pages",
SourcePath = "pages"
},
new LocalizationSource
{
Name = "Processes",
SourcePath = "processes"
}
}
};
});
Using Signals.Aspects.Localization.Database
services
.AddSignals(config =>
{
config.LocalizationConfiguration = new DatabaseDataProviderConfiguration(myConnectionString)
{
ConnectionString = myConnectionString,
LocalizationCategoryTableName = "LocalizationCategory",
LocalizationCollectionTableName = "LocalizationCollection",
LocalizationEntryTableName = "LocalizationEntry",
LocalizationKeyTableName = "LocalizationKey",
LocalizationLanguageTableName = "LocalizationLanguage"
};
});
- Install package Signals.Aspects.Localization
- Create class with implementation of
Signals.Aspects.Localization.ILocalizationConfiguration
/// <summary>
/// Localization configuration contract
/// </summary>
public class MyLocalizationConfiguration : ILocalizationConfiguration
{
public string MyProperty { get; set; }
}
- Create class with implementation of
Signals.Aspects.Localization.ILocalizationDataProvider
/// <summary>
/// Localization data provider ontract
/// </summary>
public class MyLocalizationDataProvider : ILocalizationDataProvider
{
private MyLocalizationConfiguration _configuraiton;
/// <summary>
/// CTOR
/// </summary>
/// <param name="configuraiton"></param>
public MyLocalizationDataProvider(MyLocalizationConfiguration configuraiton)
{
_configuraiton = configuraiton;
}
//
/// <summary>
/// Inserts new localization entry
/// </summary>
/// <param name="entry"></param>
void InsertLocalizationEntry(LocalizationEntry entry);
/// <summary>
/// Inserts new localization key
/// </summary>
/// <param name="localizationKey"></param>
void InsertLocalizationKey(LocalizationKey localizationKey);
/// <summary>
/// Inserts new localization language
/// </summary>
/// <param name="localizationLanguage"></param>
void InsertLocalizationLanguage(LocalizationLanguage localizationLanguage);
/// <summary>
/// Inserts new localization category
/// </summary>
/// <param name="localizationCategory"></param>
void InsertOrUpdateLocalizationCategory(LocalizationCategory localizationCategory);
/// <summary>
/// Inserts new localization collection
/// </summary>
/// <param name="localizationCollection"></param>
void InsertOrUpdateLocalizationCollection(LocalizationCollection localizationCollection);
/// <summary>
/// Inserts or updates list of localization entries
/// </summary>
/// <param name="entries"></param>
void InsertOrUpdateLocalizationEnties(List<LocalizationEntry> entries);
/// <summary>
/// Loads the localization categories
/// </summary>
List<LocalizationCategory> LoadLocalizationCategories();
/// <summary>
/// Loads the localization collections
/// </summary>
List<LocalizationCollection> LoadLocalizationCollections();
/// <summary>
/// Loads the localization entries
/// </summary>
List<LocalizationEntry> LoadLocalizationEntries();
/// <summary>
/// Loads the localizaiton keys
/// </summary>
List<LocalizationKey> LoadLocalizationKeys();
/// <summary>
/// Loads the localization languages
/// </summary>
List<LocalizationLanguage> LoadLocalizationLanguages();
/// <summary>
/// Updates all localization entries
/// </summary>
/// <param name="entries"></param>
void UpdateAll(List<LocalizationEntry> entries);
/// <summary>
/// Updates an existing localizaiton entry
/// </summary>
/// <param name="entry"></param>
void UpdateLocalizationEntry(LocalizationEntry entry);
}
- Use our implementation of
ILocalizationConfiguration
when configuring our application
public static IServiceProvider AddSignals(this IServiceCollection services)
{
services
.AddSignals(config =>
{
config.LocalizationConfiguration = new MyLocalizationConfiguration
{
MyProperty = "my_value"
};
});
}