I am new to MFC and I need to build a multi-language application that should be able to change the language at runtime.
AFAIK the common way for internationalization with MFC is to create resource-only DLLs. But there seems to be no simple way (that means, load DLL, call some function, and MFC updates all stuff automatically or something like that) to switch resource-DLLs at runtime, right?
So I will have to update all controls and so on manually. I already managed to load strings from the string-table of a DLL but since captions of controls like buttons are stored in the corresponding dialog (if I trust my resource-hacker :)) I thought there must be a way to load them and avoid storing an additional string in the string-table manually.
Or is there another way I don't know about?
If it makes any difference...I have to use MS embedded visual c++ 4
I work on a large localized MFC project. Here is our strategy:
A dictionary of key -> localized string, specific to each language. There are a few ways to implement this, more later.
Control IDs or captions in the dialog resource are set to the key used to look up the translation
Create a base CDialog, CFormView, etc and in at init call ::EnumChildWindows. In the callback, look up the translation and replace the control's caption with the translation.
For your dictionary, you can go a few ways.
If you want to rely on the built-in localized resource selection and string tables, you have to somehow match the control to the string ID. You can carefully ensure that the control ID matches the string ID, or you can ASCII-encode the ID in the caption and then use atoi to parse the int value.
You can forgo the built-in localized string table deal and maintain your own string -> string dictionary for each language. This lets you set the caption to the non-localized string in the resource which makes layout easier (although you'll still need to test in all languages.) It will require you to do your own "dependency injection" to make sure you load up the right dictionary. You want to be able to release updated/additional languages without rebuilding the core binaries.
If you don't want to require a restart of the application (by far the easiest solution, and the one you should use IMO), you can use resource dll's and recreate the main windows when the user switches languages. That way MFC will recreate the menus etc. in the new language. New dialogs will be displayed in the new language already anyway, from the moment you've switched the resource handle around.
I'm not sure how this relates to the embedded world, my experiences are from the desktop MFC.
Related
Just like TImageList contains a collection of images, is there a similar component for generic files?
I know I can embed files as resources, but I'd like the convenience of storing different groups of files in different "TFileList" components, and to be able to retrieve files by name or by their position in the list.
Extra points if such a component allowed some sort of design time preview of the file content (just like TImageList lets you see what each image looks like, at design time).
(I come from Delphi where I wrote my own component to do the above, but before I rewrite and port the property editor and all that to Lazarus, maybe there is already something that is tried and tested...)
Thanks!
You can use pre-defined lazarus TFPGList to specialize list of the type, that you want, for example - UTF8String
But, there's no T<>List as a component, only as object.
So, yes, this feature will be useful and i can implement, if have time,
also, there's a very limited RTTI, which has been updated only a few months ago, so you can access Methods and Properties now, so FP is more systemized, than delphi pascal, but also not so enterprise-developed, which limits it to implementations for common opensource and shareware project problems.
Nevertheless, it is more stable and supported, even my friends can contribute.
I often have the situation where the wording of specific strings from various modules or core features needs to be changed for specific tenants & themes in Orchard CMS.
For example, I may have a client that prefers to have the shopping cart checkout button say "Checkout Now" rather than "Go to checkout" which is a string contained within a view in a shopping module.
I can simply override the razor view in my theme and change the string, however views often are quite complex, and it doesn't feel right overriding a view just to change one string.
Another approach I have tried is to define a po translation file within my theme to override the string from the module. This works because the strings in the module are defined using the T() syntax. However, I've noticed that as soon as I define an override for a string within my theme, this override effects all tenants, instead of just the one tenant that has this theme enabled. I'm inclined to think that translations within modules/themes should be ignored from tenants where they are not enabled.
So I'm left wondering what the best approach for this scenario is?
The localisation/po file approach would be ok if tenants ignored po files from themes that aren't enabled, but then again, it would be really nice if there was a module or feature in core that allowed you to specify string overrides via the admin interface. I guess it's more of a "rewording" task than a "translation" task.
The preferred way of doing this is through template overrides. If you don't want to do that, you can actually break shapes down, and delegate the rendering to smaller templates that are easier to override. This is done by simply refactoring the part of a template that you want to be able to override individually into a separate template. This post explains how to do that: http://weblogs.asp.net/bleroy/creating-shapes-on-the-fly
If you're not willing to do that, you can use this module to get strings from the database instead of po files: http://gallery.orchardproject.net/List/Modules/Orchard.Module.Q42.DbTranslations It should be possible to modify it to fit your sceanrio.
The generated designer.cs properties are private by default (at least without manual tweaking of generated code). This makes coding against something like a UITableViewCell feel much different than if I were doing this in Objective-C.
The popular way in the case of UIxxxViewCells, at least from what I can tell, is for the UIxxxViewDataSource to populate the IBOutlet properties, and that the cell should only be responsible for anything related to drawing/rendering the view.
With Xamarin.iOS, we are unable to access these properties from the data source, and instead are required to provide additional setter methods to populate the cell. In this way, the cell is responsible for setting it's own properties.
Is this just "The .NET way" of doing things?
It's so that we don't break encapsulation by default.
The outlets belong to the object they're on, it should be able to choose whether they're able to be modified from the outside. The fact that they're properties is an implementation detail of the Xamarin.iOS outlets system - you should think of them as private fields.
If you wish to expose them, you can create properties that do so - preferably read-only.
It was probably done that way because that's how the other GUI designers in MonoDevelop worked at the time (still do). Auto-generated bindings to the native controls used by the user-designed control for toolkits like Gtk# are also created as private.
I'm not sure if other UI designers for .NET work (I've never used Visual Studio to develop GUI apps using Windows.Forms or WPF).
Feel free to file a feature request on https://bugzilla.xamarin.com to make them public - I'll gladly implement it, I think it probably makes more sense for them to be public. I haven't changed it mostly because no one has expressed that they wanted it be any other way.
A vanilla Windows Phone device is populated with many string resources - for example 'Settings' and beneath 'Settings' lies 'location' among others. At least this is the case for the en-GB UI language. I would like to access the full list of device-loaded strings, not just for en-GB, but for every UI-supported language. That is, I'm looking for the full list of en-GB UI strings, plus their parallel translations in the full set of UI-supported languages. Can anyone help me find them? Do I need a special SDK? Does Microsoft simply 'publish' them somewhere? Or do I need to write some C# to query an on-phone assembly?
The strings used by the OS and the native apps are not available via any public method.
If you are looking to translate your app you need to translate text in context to where you use it. It is not a straight copy and paste exercise. This means you can't just reuse the translations from another source. (Unless it's the exact same context.)
I am creating a series of window mockup templates based on the excellent Mockups library available on CodePlex.
I'm using their BaseMockup as the base for my control as well, and I followed the same outline of the steps listed here for sub-deriving from existing controls (Create a new empty class, add your default style to /Themes/generic.xaml, etc.)
The control is working great - the only thing is that it doesn't show up in the Assets library. I think this is because it's sub-derived, or because I need some attribute (the equivalent of the ToolboxItemAttribute for WinForms controls? ... which didn't work) to get it hooked up.
When I modify the code to derive directly from Control, it shows up - no custom attribute necessary. Of course that defeats the purpose of what I'm trying to do though...
The only thing I can find are several articles telling me to muck with registry keys, and none of them are clear or suggest a definitive way to do this with Blend 4. That last one advertises as a Blend 4 tips article, but admits at the end that it plagiarizes the content from the other two (for Blend 3).
Is that my only option - register my DLL? Is there a better way to do this?
A while ago I wrote a blogpost about this. I've included a .reg file and a .bat file for setting up the register and some directories. I think that's what you are looking for.
I believe you do need to muck with registry keys. Specifically,
32 bit: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NET Framework\v4.0.30319\AssemblyFoldersEx
64 bit: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NET Framework\v4.0.30319\AssemblyFoldersEx
Create a new key with the name of your control assembly. Then edit the Default string value under this key and set the value to the directory where the control assemblies are installed. See here for a full example (using the Silverlight paths).
Found it - there is an analogue attribute after all, it's ToolboxBrowsableAttribute.
You have to go through a little more rigmarole to get it set up, but it works great - no registry mucking necessary. It requires creating a designer metadata provider class, attributing your assembly so it's designer-discoverable, and then adding the attributes to your sub-derived controls inside your metadata provider.
Make sure you choose the appropriate version of the page for your version of Visual Studio, because the interface changes a good bit between 2008 and 2010.
This article on CodeProject has some good, real-world examples of setting this up. They're all in the 2008 style though, so bear that in mind if you're using 2010.