Inserting Localised Lookup Data into a Fresh Database
-
Didn't really know where to ask this so went for the lowest common denominated forum! C# FTW! Anyway, I was wondering if this was a problem that had already been solved but I'm not aware of the generalised approach. I have an MvvmCross based solution that uses SQLite as the data store. All the common functional goodness is in a core PCL project, all fine and dandy. In this core PCL I have the data access stuff along with resx files containing any strings needed in the various application UI projects. When the application starts up it initialises a connection to the SQLite database. If the database doesn't yet exist and requires creation (think very first run of the application) it needs to create the database and populate it with some initial data (just for ease of setup with some generic lookup data). This data is fully editable by the user but this is more of a convenience task to get the user up and running quickly without burdening them with loads of config before being able to do something useful. What I'm looking at is using localised resx data for the source of this look-up data. I can think of a few ways of doing this but before I pop off and roll a solution I was wondering if there were any generalised approaches to this scenario that people had used before. Googling hasn't turned anything up thus far so I thought I'd cast the net out to you lot first.
"His master's voice": [Globalizing and Localizing .NET Framework Applications](https://msdn.microsoft.com/en-us/library/h6270d0z(v=vs.110).aspx)
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
-
"His master's voice": [Globalizing and Localizing .NET Framework Applications](https://msdn.microsoft.com/en-us/library/h6270d0z(v=vs.110).aspx)
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
-
-
The "recommended patterns" are there. I find it's not worth the effort to go against the grain in these situations. Adopt; then extend, if necessary.
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
I might not have explained my question properly to be honest. Localising an application using Resx and custom UI binders for XAML, iOS and Android Xamarin apps is fine. I've done all these things before. Handling RTL globalisation in WPF apps is also something I've done before as well. I was basically looking for inspiration regarding taking localised strings from RESX files and populating various database tables with lookup values for things. What I've ended up doing is implementing the Builder pattern to aggregate key value pairs from these RESX files and utilising my repository pattern bits to automatically populate these lookup tables on the initial creation of the SQLite db3 file. My base builder class looks like this (not perfect by a long shot, there is no abstraction of the connection I can use for instance):
public abstract class LookupBuilderBase where T : class, IEntity, new()
{
protected SQLiteAsyncConnection AsyncConnection;
protected IDictionary LookupData;
protected IRepository Repository;
protected readonly IList Data = new List();protected LookupBuilderBase(SQLiteAsyncConnection conn, IDictionary lookupData) { AsyncConnection = conn; LookupData = lookupData; } public async Task Execute() { CreateRepository(); BuildData(); await InsertData(); } protected abstract void BuildData(); protected virtual async Task InsertData() { foreach (var item in Data) { await Repository.Insert(item); } } private void CreateRepository() { Repository = new Repository(AsyncConnection); }
}
I can then write builders like this:
public class CategoryBuilder : LookupBuilderBase
{
public CategoryBuilder(SQLiteAsyncConnection conn, IDictionary lookupData)
: base(conn, lookupData)
{
}protected override void BuildData() { var values = LookupData.Where(x => x.Key.StartsWith("Category")); foreach (var keyValuePair in values) { Data.Add(new Category { Name = keyValuePair.Value }); } }
}
-
I might not have explained my question properly to be honest. Localising an application using Resx and custom UI binders for XAML, iOS and Android Xamarin apps is fine. I've done all these things before. Handling RTL globalisation in WPF apps is also something I've done before as well. I was basically looking for inspiration regarding taking localised strings from RESX files and populating various database tables with lookup values for things. What I've ended up doing is implementing the Builder pattern to aggregate key value pairs from these RESX files and utilising my repository pattern bits to automatically populate these lookup tables on the initial creation of the SQLite db3 file. My base builder class looks like this (not perfect by a long shot, there is no abstraction of the connection I can use for instance):
public abstract class LookupBuilderBase where T : class, IEntity, new()
{
protected SQLiteAsyncConnection AsyncConnection;
protected IDictionary LookupData;
protected IRepository Repository;
protected readonly IList Data = new List();protected LookupBuilderBase(SQLiteAsyncConnection conn, IDictionary lookupData) { AsyncConnection = conn; LookupData = lookupData; } public async Task Execute() { CreateRepository(); BuildData(); await InsertData(); } protected abstract void BuildData(); protected virtual async Task InsertData() { foreach (var item in Data) { await Repository.Insert(item); } } private void CreateRepository() { Repository = new Repository(AsyncConnection); }
}
I can then write builders like this:
public class CategoryBuilder : LookupBuilderBase
{
public CategoryBuilder(SQLiteAsyncConnection conn, IDictionary lookupData)
: base(conn, lookupData)
{
}protected override void BuildData() { var values = LookupData.Where(x => x.Key.StartsWith("Category")); foreach (var keyValuePair in values) { Data.Add(new Category { Name = keyValuePair.Value }); } }
}
I would have a single table (for a given "dimension") and have columns for each resource. At run-time, using Linq, or C# / SQL "views" (or some other magic), I would materialize only the column that the app's locale required. Adapters.
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
-
I would have a single table (for a given "dimension") and have columns for each resource. At run-time, using Linq, or C# / SQL "views" (or some other magic), I would materialize only the column that the app's locale required. Adapters.
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
It's either a case of filter what you're interested in on the way into the database or shove it all in there and filter on the way out of the database. I opted to only put relevant stuff into the database which means that considering the data is 99.99999999% handled in reads not writes I opted to make the read more efficient.
-
It's either a case of filter what you're interested in on the way into the database or shove it all in there and filter on the way out of the database. I opted to only put relevant stuff into the database which means that considering the data is 99.99999999% handled in reads not writes I opted to make the read more efficient.
-
"Shove it in there"? It becomes THE repository for your resources; and not just some "staging area".
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
-
Then why are you loading them into a table....
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
In the instance of Categories it's because they are simple lookup values loaded into a view model for, for example, binding to a combobox. BUT they are also useful as values used in foreign key relationship in the database. Resex is the best way to handle automatic localisation utilising standardised approaches for this in the .NET framework but also have value in the database.
-
In the instance of Categories it's because they are simple lookup values loaded into a view model for, for example, binding to a combobox. BUT they are also useful as values used in foreign key relationship in the database. Resex is the best way to handle automatic localisation utilising standardised approaches for this in the .NET framework but also have value in the database.
I see. I, however, would not think twice about loading it all into a database if I had to "share" in the ways you describe; let alone report on and cross-check all this stuff for any sizable project. Resx internals are simple; there is nothing stopping one from importing or exporting them. It's a question of which "smell" one prefers then. In any case, the "assets" are separated from the "code"; the whole point of "resource files" (whatever the implementation).
"(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal
-
Didn't really know where to ask this so went for the lowest common denominated forum! C# FTW! Anyway, I was wondering if this was a problem that had already been solved but I'm not aware of the generalised approach. I have an MvvmCross based solution that uses SQLite as the data store. All the common functional goodness is in a core PCL project, all fine and dandy. In this core PCL I have the data access stuff along with resx files containing any strings needed in the various application UI projects. When the application starts up it initialises a connection to the SQLite database. If the database doesn't yet exist and requires creation (think very first run of the application) it needs to create the database and populate it with some initial data (just for ease of setup with some generic lookup data). This data is fully editable by the user but this is more of a convenience task to get the user up and running quickly without burdening them with loads of config before being able to do something useful. What I'm looking at is using localised resx data for the source of this look-up data. I can think of a few ways of doing this but before I pop off and roll a solution I was wondering if there were any generalised approaches to this scenario that people had used before. Googling hasn't turned anything up thus far so I thought I'd cast the net out to you lot first.
Not sure if I understood your issue completely. Since you want to let the user edit the texts, you opted for storing them in a database instead of resx files, but still want to use resx files for development, isn't it? I'd suggest to get rid of those resx files here, handle the localization completely in the database (I think software translation shops can handle that, too), thus no need to feed them from the files into the database.