Hi Greg,
We had used one of the resx approaches before but in the latest version of
NovaMind (www.novamind.com) we have invented our own very simplistic process
for localization. (a bit inspired by the Objective-C/Mac way of doing things
via NSLocalizedString)
Our XAML looks like this Text="{nm:Localize Here goes the text}" and in code
we use an extension method so you can write something like this
MessageBox.Show("Hello".Localize());
You could also specify comments like this:
var s = "This is a string".Localize("Comments to better clarify how and
where it is used.");
or (a bit more cumbersome in XAML):
<Label.Content>
<nm:Localize Comment="Comment goes here">
String goes here.
</nm:Localize>
</Label.Content>
We also have design time support for this were the original string will be
displayed.
We have a tool that scans through the files and gathers all strings from all
assemblies and projects within the solution. It creates a dictionary based
on the string and comment and then you can export it to, or merge it with
existing CSV files.
We send the CSV files to our translators and then simply include them into
our release. When requested by the application we load the file for the
current culture and create a dictionary.
The advantages over a .resx approach are:
- You don't need to manually manage multiple .resx files
- if a string is no longer in use the tool will know about it and remove it
from the files. (with .resx files it is hard to know which entries are
actually in use somewhere)
- if there is a new string you can easily generate a 'missing translations'
file for each language.
- you don't need to manage multiple .resx files for each part and each
assembly. Only one file is needed.
- As a developer it is far easier to spot any typos or other problems with
strings since you can see the original string.
- You don't have to define common strings in multiple places (example: OK,
Cancel only needs to be translated once). You can easily specify comments to
assist translators.
- It is easier to see problems with mismatching format strings ({0} etc.
because you can actually see the string and don't have to look it up in a
.resx file)
might not suite everyone but for us this approach has been a blessing. a lot
less pain.
cheers,
Patrick Klug
Development Manager
NovaMind
www.novamind.com
> Today's Topics:
>
> 1. RE: WPF Localization ([email protected])
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Mon, 1 Nov 2010 09:15:36 +0800
> From: [email protected]
> Subject: RE: WPF Localization
> To: [email protected]
> Message-ID: <[email protected]>
> Content-Type: text/plain; charset="us-ascii"
>
> +1
>
>
>
> From: [email protected] [mailto:[email protected]]
> On Behalf Of Martin Crimes <[email protected]>
> Sent: Friday, 29 October 2010 7:36 PM
> To: ozWPF <[email protected]>
> Subject: RE: WPF Localization
>
>
>
> We bind ours through the ViewModel into a resx.
>
> We have a modular app, so we split our resources into Common (external
> DLL) and Module Specific (same DLL as View/VM).
>
>
>
> So in our VM, we'd have something like this :
>
>
>
> #region Resource Strings
> public object Strings
> {
> get { return _strings; }
> }
> private readonly ResourceStrings _strings = new ResourceStrings();
> public object CommonStrings
> {
> get { return _commonStrings; }
> }
> private readonly ResourceCommonStrings _commonStrings =
> CommonStringFactory.GetResourceCommonStrings();
> #endregion //Resource Strings
>
> The XAML in the View would then bind like this (assuming DataContext is
> the VM) :
>
>
>
> <Button Content="{Binding Path=CommonStrings.V_Ok, Mode=OneTime}">
>
> Or
>
> <Button Content="{Binding Path=Strings.V_AddOrder, Mode=OneTime}">
>
>
>
> I mention the Common ones explicitly because there's an annoying bug
> from VS2008 which still seems present in VS2010 whereby the constructor
> of the resources class keeps being set to an internal method every
> change rather than being a public method. It's referenced in MSConnect
> as a bug to be addressed but I can't find the URL offhand.
>
> So we have to wrap access to a common app-wide set of resources with a
> factory :
>
>
>
> /// <summary>
>
> /// Factory to create an instance of <see
> cref="ResourceCommonStrings"/>.
>
> /// This is required because a Visual Studio 2008 bug sets the
> constructor of
>
> /// that class to be internal rather than public, so this is needed
> to allow
>
> /// other assemblies to access this resource assembly
>
> /// </summary>
>
> public static class CommonStringFactory
>
> {
>
> static ResourceCommonStrings _instance = new
> ResourceCommonStrings();
>
>
>
> /// <summary>
>
> /// Gets an instance of ResourceCommonStrings
>
> /// </summary>
>
> /// <returns>new instance</returns>
>
> public static ResourceCommonStrings GetResourceCommonStrings()
>
> {
>
> return _instance;
>
> }
>
> }
>
>
>
> Have been using this approach for a couple of years now with something
> in the region of 4000 localised strings. Splitting it out into a single
> Common resx and a resx per module (ie block of function) helps keep it
> manageable in the resource editor. The largest single resx I can see on
> a quick code scan looks to be about 300 strings or so, so there may be
> issues if you went for a single huge one which we haven't encountered.
>
>
>
> Not saying this is the best option - just the one we settled down and
> lived with after a brief period of experimentation.
>
>
>
> Martin
>
>
>
> Martin Crimes
> Clarity Retail Systems Limited
>
> www.claritycommerce.com <http://www.claritycommerce.com/>
>
>
>
> From: [email protected] [mailto:[email protected]]
> On Behalf Of Greg Keogh
> Sent: 29 October 2010 04:38
> To: 'ozWPF'
> Subject: WPF Localization
>
>
>
> I'm in a different part of the coding now. I'm looking of best practices
> in localise a WPF application. There are lots of articles around that
> discuss using locbaml or resx files and binding. The locbaml approach
> looks tedious and I won't consider it unless someone has something nice
> to say on its behalf.
>
>
>
> Using resources generated from resx files is more familiar to me. I
> wrote a little test IValueConverter that acted as both source and
> converter, it works, but the XAML to call it is ridiculous and would
> bloat the XAML terribly.
>
>
>
> <app:AppResourceConverter x:Key="rescon"/>
>
> ...
>
> Content="{Binding Path=Lookup,Source={StaticResource rescon},
> Mode=OneWay, Converter={StaticResource rescon},
> ConverterParameter='FooKey'}"
>
>
>
> So I set the resx generated class to be public and use XAML like this:
>
>
>
> xmlns:app="clr-namespace:MyCompany.MyApp"
> ...
> Content="{x:Static app:AppResources.StringFooKey}"
>
>
>
> Now this looks much crisper and readable, but I have to set the resx
> tool generated class to public and the class will grow to have huge
> numbers of public properties as the number of strings .
>
>
>
> Has anyone else had to localise a significant WPF application in anger?
> Are there other tricks I haven't thought of that make the process
> easier?
>
>
>
> I see Rick Strahl has written a markup extension
> (wpflocalization.codeplex.com) which looks hopeful and I'm reading about
> now.
>
>
>
> Greg
>
>
>
>
> Clarity Retail Systems Limited, Paterson House, Hatch Warren Farm, Hatch
> Warren Lane, Hatch Warren, Basingstoke,
> Hants, RG22 4RA, UK - Company Registration No: 02739937 - Registered in
> England
>
> The contents of this email are intended for the named addressee(s) only.
> It contains information which may be confidential and which may also be
> privileged. If you are not the intended recipient(s) please note that
> any form of disclosure, distribution, copying or use of this
> communication or the information in it or in any attachments is strictly
> prohibited and may be unlawful. If you have received it in error please
> notify the sender immediately by return email or by calling +44(0)1256
> 365150 and ask for the sender. Where the content of this email is
> personal or otherwise unconnected with Clarity Retail Systems Limited or
> our clients' business, Clarity Retail Systems Limited accepts no
> responsibility or liability for such content. It is your responsibility
> to verify that this email and any attachments are free of viruses, as we
> can take no responsibility for any computer viruses.
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email
> ______________________________________________________________________
>
> _______________________________________________
> ozwpf mailing list
> [email protected]
> http://prdlxvm0001.codify.net/mailman/listinfo/ozwpf
>
> ________________________________________________________________________
> _______
>
> This email has been scanned by the Bankwest Email Security System.
> ________________________________________________________________________
> _______
>
>
> _______________________________________________________________________________
> Unencrypted electronic mail is not secure and may not be authentic.
> If you have any doubts as to the contents please telephone to confirm.
>
> This electronic transmission including any attachments is intended only
> for those to whom it is addressed. It may contain copyright material or
> information that is confidential, privileged or exempt from disclosure by
> law.
> Any claim to privilege is not waived or lost by reason of mistaken
> transmission
> of this information. If you are not the intended recipient you must not
> distribute or copy this transmission and should please notify the sender.
> Your costs for doing this will be reimbursed by the sender.
>
> We do not accept liability in connection with computer virus, data
> corruption,
> delay, interruption, unauthorised access or unauthorised amendment.
>
> _______________________________________________________________________________
>
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email
> ______________________________________________________________________
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL:
> http://prdlxvm0001.codify.net/pipermail/ozwpf/attachments/20101101/afd47547/attachment.html
>
> ------------------------------
>
> _______________________________________________
> ozwpf mailing list
> [email protected]
> http://prdlxvm0001.codify.net/mailman/listinfo/ozwpf
>
>
> End of ozwpf Digest, Vol 10, Issue 2
> ************************************
>
_______________________________________________
ozwpf mailing list
[email protected]
http://prdlxvm0001.codify.net/mailman/listinfo/ozwpf