I'm struggling with this issue. I have a webservice that retrieves all the possible labels (with keys) for my application. This labels may vary from culture to culture (en, fr, de, pt, etc).
My doubt is how can I create/fill a resource file for that culture and fill with those labels/keys?
Those labels are managed by a backend server, and I have a GET to a REST webservice to get those strings.
Thanks
I don't think that there are any best practices for this. You need to write a mini-framework that could do one of the things listed bellow:
[If using MVVM] You could put the labels on your view model and bind to them in XAML. Involves writing lots of properties even when using snippets. Also, lots of properties are a pain when binding.
[If using MVVM] A better design similar to 1 where you store the labels in a separate class which is a property in your view model. Let your imagination go wild, use singleton, caching, etc. This is the most dangerous approach.
You could create one (or more classes) like any view model (at least with INotifyPropertyChanged), store it as a XAML resource and bind to it, populate it when you want. More XAML when binding labels but does what you're asking for and it's easily readable for others.
In all the options listed above you can change locale at runtime with translation being effective immediately (assuming you implemented INotifyPropertyChanged and bound label to take account of this), which you don't get with .resx and changing thread culture.
I would try all 3 as sample projects and see which would make a time-efficient way of manipulating label resources (adding, removing, changing, renaming them, and of course maintaining their contents).
Personally, I would go with 3. I listed the others just to be a little exhaustive.
Related
Having rather large project using Resources for internationalization (following this guide: ASP.NET MVC 2 Localization complete guide, using things like data attributes, and so on) we run into the need of translating the resource files. In the beggining of project I selected approach to have lot of small resource files - for each view, viewmodel, controller, ... So I ended up having hundreds of resources. During the translations (which is done by our partners using ResXManager tool we run into trouble identifying the context of the string (where is it displayed, to find out the correct form of translation to make sense when displayed).
So I was asked to make the mutation of application which do not display the localized values, but the keys (or string names). E.g. having string in resources TBL_NAME used somewhere in the view like #ResX.TBL_NAME and translated into english as "Name", I would like to show it in this special mutation as "TBL_NAME", so the translator may see the context - where exactly this string is used.
The best would be, if this is not special build of application, but rather the another "language" of the application available for translators, so he can switch between english and this "unlocalized" languages.
I'm looking some easy ideas of doing this. So far I was thinking of these approaches:
Override ResourceManager.GetString - cannot use, because we use generated Designer classes to access strings massively and so far I haven't find a way to change created ResourceManager (see this answer). Did I miss something?
Create resources for some unused language, which will contain pairs string name/translated value as TBL_NAME/TBL_NAME - viable, but very exhausting since we have hundreds of resources. Also the addition of new resource will require us to remeber that we need to add also this unused language resource will exact same strings name. You also have to do twice much work when adding single string to application.
At the moment, it seems for me, that using resources and current approach it is impossible to solve this task, so I decided to ask this as question (and I'm aware it is rather discussion than question) here, hoping, someone will give me some hint about other approach to solve this problem.
My preferred option would be to give the translators an environment where they can see what they are translating. Rigi requires a bit of setup (basically you need to add an additional UI language), but once you have done that translators can work within the live website - or in a test instance, which is what we did.
They can also work in screenshots, which is convenient when translators would have to access admin or other role specific pages but you do not want to bother giving them all kinds of user rights. These screenshots can be generated as part of automated UI tests or during manual UI testing.
I am afraid I can't say anything about the cost of the solution, but our translators are really happy with it. I am not sure if this is what you are looking for since you asked for an easy solution, but it definitely solves the issue of giving translators the context they need to do their job - better than displaying resource IDs.
I'm making a website for use by multiple clients and I need to offer the flexibility to change labels on various places. For example, if one client wants to call the login "Email" and another wants to call it "Employee ID." Though I've never used them, I thought that resx resource files used for localization would be a good idea, but I'm having problems setting it because what I'm doing isn't a real localization that maps to any culture.
My testing has these resource files:
Global.resx
Hello "Hello!"
Global.Casual.resx
Hello "Sup!"
Global.Formal.resx
Hello "Greetings!"
Then in my cshtml view, I can say #Resources.Global.Hello and that works as expected. My question is, how can I set it to display Casual by default? If I rename Casual and Formal to es and ru, I can do something like this:
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("es");
And that works just fine. But if I try that with "Casual" I get that it "is an invalid culture identifier." I can explicitly show it by saying #Resources.Global_Casual.Hello in the view, but that's obviously not what I'm after.
Am I going the complete wrong direction here, trying to use something for a purpose contrary to its design? I just want to load resource files by arbitrary string values. Do I need to roll my own database-driven approach?
This looks very similar to this SO question, which never got an answer: How to specify a custom culture?
Personally I feel that this kind of customisation belongs in the database - not least because you can then allow the clients to customise it themselves if required. If you are concerned about performance then you can cache the terms into a dictionary and even create a class that will expose the strings either from the dictionary (if the client has customised them) or from a resource file if not. This allows you to present reasonable defaults which can be changed on demand. Alternatively you could present a number of alternatives in the database, and a flag to allow selection per term of the word to be displayed in the UI.
I had a similar problem of allowing customisation within an application in the SO question Localization vs Customization which you may find useful.
Lets say there are bunch of forms: A.cs, B.cs, C.cs...
Each form is localized - A.resx, A.NL-nl.resx, etc.
These forms contain some specific labels and some common in all forms used labels. So specific strings go to A.resx (A.NL-nl.resx) and common ones - to lets say Common.resx (Common.NL-nl.resx)
Is there any way to force when form is initialized to use resource strings from A.resx and from Common.resx where all common strings go? Of course I could in some OnLoad method set captions for my form layout items, but then built in localization functionality would be lost.
The reason I would like such functionality, because there are lot of commonly used strings in different forms and it would much easier to manage/translate these *.resx files.
I've done some reading about localization in C#, but probably I am missing something.
From my experience I can say:
You will be better of to create one locatization resx file for all the forms.
Assign all localizable strings manually (I did that in constructor).
Store each string for each form in different localizable property, like Form1_OkButtonText, Form2_OkButtonText.
The last one really does matter, when you translate your app to different languages, because translation may really depend on context. And on one form default button may be named OK and on the other it should be named Accept. While in English both buttons may be named Ok, in some other languages, this will sound awkward, and different names will be required. This is be problematic, if you use same resource strings for all buttons.
And to mitigate the problems of translating several same strings many times, you should use some software for translator, that keep dictionary of string, and supply you with already translated ones.
Resources have a fully qualified name. Which means they have one source. If you want to use texts from Common.resx in your form, you must write code for that. Easy code but code nonetheless.
So I'm having some level of difficulty with architecting a particular solution with some dynamic data elements....
So I've got two places where I'm storing data -- a database and a pdf (although I only write to the pdf - I never read from it). You can think of the pdf working a lot like a database -- except that the schemas for the table and the pdf are different. Different fields will go into the database and the pdf. Users will be able to edit certain fields -- but not all fields. I'm trying hard to enforce a separation of UI and logic here, but I'm running into difficulties. My logic is essentially having to tell my UI what UI elements to create and what restrictions to enforce on them (required, options, etc) so I feel a bit like I'm making a UI from within my business logic; but I don't really know how else to do this with dynamic data elements. When this is done, I have to write to the database and then print the pdf.
You can essentially think of this question as... "I have a ton of disparate data. I need to do different things with different pieces of data. I can't figure out a way to do this generically without making some coding atrocity." Does anyone have any ideas?
What you're doing is developing an application framework, not an application. You might benefit from looking at other application frameworks (there are a billion of them) to see how others have approached the problem.
I can tell you right now that your project will be successful in direct proportion to how well you've designed the scheme for handling metainformation. Steve McConnell's general rule that data is easier to debug than code is pretty much the guiding beacon for this kind of project.
WPF is really, really well suited for this kind of thing. I've been porting over my own app framework from Windows Forms to WPF and am kind of amazed at how much code I don't have to write.
If I were you, I would look at all the information about fields users need to view/edit, and see what common themes I can see. Looking at your question I would probably create a class/structure that contains the following:
struct FieldInfo
{
string FieldName;
string DisplayName;
string DataType;
bool Required;
delegate Validator;
string OldValue;
}
delegate bool Validator(string input, out string message);
I would return FieldInfo[] from the Business Logic, then in the UI use that array to determine what to show the user. This way, even the validation login is the your business logis (using the delegate) and the UI only has to decide what elements to display for each type. You could even go a step farther and have the FieldInfo struct have an element name telling the UI what element to use for that field (Textbox, DDL, etc)
I'm just starting out in WPF and I'm building a simple movie library as a test project to help me find my feet.
I'm storing my movie information in XML, for example:
<movie id="1" title="Back To The Future" date="1985" ... />
The movies appear in a list and when clicked the fields will become editable. I've got that working by using two Data Templates to style the list items, applied via a Trigger on the ListBoxItem.IsSelected property.
But for binding and editing the data, I'd be really grateful for some advice. I've tried each of the approaches below with varying degrees of success. Which do you think makes the most sense? Are there any other things I could try?
Approach 1: Bind to XML directly using XMLDataProvider in XAML. In this case the ListBox binds to the XmlDataProvider and the individual control elements are bound via XPath expressions. It's very simple to get started, but this approach seems to become tricky when editing the data. We need rather a lot of ValueConverters just to ensure that the data is presented sensibly and saved back to the XML file in the appropriate format.
Approach 2: Create a custom Movie class that receives the XML and exposes all the movie attributes as public properties to which the controls are bound. This feels more robust and flexible, but seems to require a lot more work to implement. Every property needs to be explicitly exposed in code and validation is a pain.
Approach 3: A bit like approach 2 but with a Movie user control instead of the ListBox + Data Templates. I started with this and quickly abandoned it because I couldn't see any advantages over approach 2.
I realise it's not a straightforward question and that there are a lot of factors to consider, but any thoughts on the various pros/cons (or whether there are any tricks I'm missing) would be appreciated. Please let me know if you would like more info or code samples. And apologies if this question is inappropriate or unwelcome.
Many thanks.
If its just for displaying, whether or not you use templates, approach one is more efficient as the wpf engine works directly with the xml.
If your going to do editing operations on the data, it is best to go with Approach two as you have the flexibility to manipulate the data far better. Using a class you can do the exact same thing as in approach one with binding as the engine will read from the objects just like the xml file. This approach allows for easily binding the elements 2 way and if its from an IObservable Collection, you can ovveride the method that is called when the data is changed, so it updates the xml.