Skip to content
Proper internationalization support for WPF (via NGettext)
C# PowerShell
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
NGettext.Wpf.Example
NGettext.Wpf.Tests Close #46 Aug 16, 2019
NGettext.Wpf Release 1.2.6-alpha Aug 16, 2019
XGetText.Xaml Merge pull request #45 from robert-j-engdahl/use-full-path Aug 13, 2019
.gitattributes merge Mar 13, 2019
.gitignore added GNOME glib syntax Feb 18, 2019
CHANGELOG.md Release 1.2.6-alpha Aug 16, 2019
LICENSE Create LICENSE Dec 28, 2017
NGettext.Wpf.sln CHANGELOG.md available from solution Feb 27, 2019
NGettext.Wpf.sln.DotSettings Localizer is a word AFAIK Jan 14, 2019
README.md Update README.md Mar 29, 2019
appveyor.yml Update appveyor.yml Sep 28, 2018
demo.gif Added support and animation of sample application to README Sep 25, 2018
ngettext.gif added anoying and crude gif showing roughly what this package does Apr 18, 2018

README.md

ngettext-wpf

Proper internationalization support for WPF (via NGettext)

See the change history here, including whats new in the latest release and what will be included in the upcomming release.

Build status

LGPL

Getting Started

Get the NuGet from here https://www.nuget.org/packages/NGettext.Wpf/.

NGettext.Wpf is intended to work with dependency injection. You need to call the following at the entry point of 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" translations will be loaded from "Locale\da-DK\LC_MESSAGES\ExampleDomainName.mo" relative to where your WPF app is running (You must include the .mo files in your application and make sure 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. The most important is the Gettext markup extension which will make sure the Content is set to the translation of "English" with respect to the current culture, and update it when the current culture is changed. The other feature it demonstrates is the ChangeCultureCommand which changes the current culture to the given culture, in this case "en-US".

Have a look at NGettext.Wpf.Example\UpdateTranslations.ps1 for how to extract msgids from both xaml and cs files.

Note that the script will initially silently fail (i.e. 2> $null) because there is no .po file for the given language. In the gettext world you are supposed to create that with the msginit command that ships with the Gettext.Tools nuget package, or PoEdit can be used to initialize the catalog from the 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 translations 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 translations 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 doesn't remember your previous choice, so stick with the defaults.

There are lots of GNU conventions related to internationalization (i18n) and localization (l10n). One of them is that the notion that the original program is written in US English, so you don't need to translate anything to facilitate internationalization. The original text in US English is called the msgId.

One of the most important GNU convention related to internationalization is providing a context to the translaters 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 different translations. 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 that can be fixed:

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

Translaters 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 needs a context, I therefore highly recommend to always provide a helpful context.


Support

Reach out to me at one of the following places!


Sample Application

In NGettext.Wpf.Example/ you will find a sample application that demonstrates all the features of this library.

Demo

You can’t perform that action at this time.