Skip to content

mwpowellhtx/Ellumination.NGettext.Wpf

Repository files navigation

ngettext-wpf

Proper internationalization (I18N) or localization (L10N) support for WPF, facilited by NGettext inside.

Review the change history, including what's new in the latest release and what will be included in the upcomming release.

GPL

Getting Started

Find the NuGet package. You may download the package itself, or add it among your <PackageReference/> notations, and so on.

Ellumination.NGettext.Wpf is intended to work with dependency injection. Integration occurs via the following entry point from your application:

NGettext.Wpf.CompositionRoot.Compose("ExampleDomainName");

The "ExampleDomainName" string is the domain name. This means that, when the current culture is set to "da-DK", localization shall occur from Locale\da-DK\LC_MESSAGES\ExampleDomainName.mo, relative to where your WPF application is running. You must include the corresponding .mo files in your application, ensuring that they are copied to the output directory.

Now you can do something like this in XAML:

<Button CommandParameter="en-US" 
        Command="{StaticResource ChangeCultureCommand}" 
        Content="{wpf:Gettext English}" />

Which demonstrates two features of this library. First, most importantly, is the Gettext markup extension, which will make sure the Content is set to the localization of "English", with respect to current culture, and update it when the current culture has changed. Second, another feature it demonstrates is the ChangeCultureCommand, which changes the current culture to the given culture, in this case "en-US".

Have a look at Ellumination.NGettext.Wpf.Example/UpdateLocalization.ps1 for how to extract MsgId's from both .xaml and .cs files.

Note: The script will silently fail (i.e. 2> $null), initially, because there is no .po file for the given language. In the gettext world, one is supposed to create that with the msginit command, which ships with the Gettext.Tools NuGet package, or PoEdit may be used to initialize the catalog from an intermediate .pot file created.

Here is what recently worked for me:

PM> mkdir -p Locale\en-GB\LC_MESSAGES\
PM> msginit --input=obj\result.pot --output-file=Locale\en-GB\LC_MESSAGES\ExampleDomainName.po --locale=en_GB

Conventions

Keep your compiled localizations in Locale\<LOCALE>\LC_MESSAGES\<DOMAIN>.mo. This library will force you to follow this convention. Or rather, NGettext forces you to follow a convention like "<PATH_TO_LOCALES>\<LOCALE>\LC_MESSAGES\<DOMAIN>.mo", and I refined it.

Keep your raw localizations in Locale\<LOCALE>\LC_MESSAGES\<DOMAIN>.po. This is not enforced, but when working with PoEdit, it will compile the .mo file into the correct location when following this convention, and it does not remember your previous choice, so stick with the defaults.

There are lots of GNU conventions related to I18N and L10N. One of them is the notion that the original program be written in US English, so you do not need to localize anything to facilitate I18N. The original text in US English is called the msgId.

One of the most important GNU convention related to I18N is providing a context to an Interpreter so they have a chance to do it right. For instance, the English word 'order' has a number of more or less related meanings and thus may be interpreted differently depending usage. For instance, in the context of sequential ordering, 'order' translates to 'rækkefølge' in da-DK, but the imperative for placing an order translates to 'bestil'. Here is an example of how this sort of circumstance may be clarified:

<!-- A button with the text 'Order' but with a helpful context for an Interpreters -->
<Button Command="{StaticResource PlaceOrderCommand}" 
        Content="{wpf:Gettext Imperative for placing an order|Order}" />
        <!--                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -->

Interpreters will rarely think of it, and just translate the first meaning that comes to mind, and as a programmer you might not know which words or sentenses need further context. Therefore, we strongly recommend to always provide a helpful context. At the very least grammatical usage, whether noun or verb, along these lines.


Future Directions

Further directions coming soon, I just wanted to get this supporting documentation somewhat refreshed and presentable, than put my future thinking cap on for the immediate road ahead.


Support

Have a question, want to participate, you get out of it what you contribute:

  1. By participating in the project discussions;
  2. By connecting with me on Github, following my work;
  3. By contacting me on Gab, where you may reach me, primarily;
  4. By following my Twitter feed; although I do not use this for contact;
  5. By networking with me via LinkedIn, always interested in solid business leads;
  6. By asking a StackOverflow question, and by including at least the annotated tags;
  7. Or, by opening a project issue

Sample Application

As presented by Ellumination.NGettext.Wpf.Example, you will discover a sample application which illustrates the key features of the packaged dotnet assembly.

Demo

Special Thanks

Big shout out to our colleague and peer, Robert Jørgensgaard Engdahl, without whom, in whose stead we are carrying the NGettext.Wpf torch forward.

Some other mentions via StackOverflow. His former LinkedIn unavailable at the time of this entry.

I am not personally aware of his whereabouts or well being today, but where ever life may find him, in this world in the here and now, or the Great Beyond, may GOD bless and GODSPEED, my friend.