Don't you just love a good plugin? I
know I do because it makes my life so much easier as a developer and
it saves me a ton of time. So in this video, we're going to look
at the LocalizationResourceManager for .NET MAUI, which makes it very easy to
add localization, so translating your .NET MAUI app. LocalizationResourceManager.Maui is
a plugin that will help you with translating your app,
adding localization to your .NET MAUI application. Now, if you're
watching this video and you're coming from the Xamarin world, this all
might look very familiar because this functionality, I think it is almost
identical lived and still lives in the Xamarin
Community Toolkit, then a good question would be why is this not
portable to the .NET MAUI Community Toolkit? Well, I'm glad you asked. So
we didn't do that because now with the CommunityToolkit.Maui as we also
call it, we have bundled our powers and
everything with the Community.Toolkit.Net or Windows because there's also the Windows
Community Toolkit and maybe there will be others in the future. So we're trying
to look at like, hey, how can we leverage stuff that might
have a broader audience? Right? So this functionality, this specific
functionality, we've added a proposal to the broader Community
Toolkit package so that other ecosystems like WinUI and other XAML based
languages can also benefit from this. So that's why it
hasn't been added to the .NET MAUI Community Toolkit yet. But as kind of
a stop gap solution, Johan Svensson from Sweden, if I'm not
mistaken, he has created this plugin which
basically takes the functionality from the Xamarin Community Toolkit, makes it
available for .NET MAUI while we are waiting for the
implementation on the Community Toolkit one. So let's just dive into Visual Studio and
let's see how you can use it right now, today to make your .NET MAUI app
speak Spanish or English or Dutch or
whatever you want. (inaudible). Okay, so here we
are in Visual Studio 2022. I just created a File, New .NET MAUI application.
You can see the beautiful, beautiful XAML in the background in
Visual Studio. In the foreground you can see the Android emulator running that
same app with the waving .NET bot that we've seen many times before.
Now the first thing that we want to do is stop running. That's what we
want to do because we need to install a plugin, right?
I've been talking about this already. So let's go to the Solution Explorer
and I'm going to right click on the project and I'm
going to do Manage NuGet Packages. Then I'm going to go to the browse and
I'm going to LocalizationResource Manager .Maui. And if you search for that, I
think there's exactly one result which you can see here and
there's a lot of contributors already. So that's great because this is a
community packet, right? So that's really amazing. So, latest version at
the time of recording 1.0.3. Let's just install that, make
sure that we read all the license agreements here, click OK and it's
going to be installed on our project. Now, as with many, many
plugins third party libraries with .NET MAUI these days, we need to
initialize this a little bit in the MauiProgram and that also
gives us a lot of options already. So let's go over to our
Solution Explorer and go to the MauiProgram.cs. And here we need to add a little
initialization line so just after the UseMauiApp or you can do it after
the ConfigureFonts or if you have other stuff in here, we're going
to do add UseLocalizationResource Manager, and I think it's not going to add it
automatically. So I'm going to use IntelliSense here, click the light bulb, do using
LocalizationResource Manager.Maui; is going to add it here
at the top so you can do that manually as well. And here I
can configure actually I have to configure a couple of settings
here, which has been done through a lambda. So let's just do settings.
It's going to act as input here and I'm going to do a
couple of brackets. And now I can say settings and we can see a couple
of configuration options, so we can say RestoreLatestCulture. Which
is a pretty cool option if you ask me, because this automatically
restores the latest culture that has been used inside of the app. So
you're going to switch, we'll see that in a minute. Switch through a
different culture at runtime to make the translations in the app happen and the
last one that the user picked is going to be restored
automatically. No need for you to save that it's just going to be loaded
automatically. You can do AddResources or AddResource rather, which takes a
ResourceManager, I'll get to that in a little bit. You
can AddFileResource so you can load things from a file if that's
what you want. You can set the InitialCulture so the initial culture
that's going to be used. So if you have a specific culture, let's stay in the cultures of Johan who created this
library, let's say with Swedish, if Swedish is your primary language,
your primary target audience, you're going to set the initial culture to Swedish
and the app will startup with that culture
basically. So you have a couple of those things and well I
think in the documentation you should
definitely check it out. I will put the GitHub link for this library down below as
well. The InitialCulture and the RestoreLatestCulture, that kind
of is kind of like conflicting functionality so I
think one overrides the other. So make sure that you check
the documentation on how to use that exactly. I'm going to say RestoreLatestCulture is true. Is this a setter? What is this? Is
this not a property cannot assign because it's a method
group. Okay, so, I forgot how to program. Right here
right now. And what I'm also going to do is do settings
and I want to of course add the resources. So
AddResource and I'm going to say AppResources because that's
already a thing. ResourceManager. Now I've already done a previous video
on translating all this stuff on
localization but then doing it manually. And there I've
created the AppResources inside of your .NET
MAUI app as you would do in any other .NET project basically. So
the app resources is just something, it could be any name.
Let me just click the IntelliSense here using MauiLocalizationResource
ManagerSample. That's the name of my project, Resources. So when I
import that it starts recognizing this. And here
in my Solution Explorer there is under the Resources folder I have
this AppResources.nl.resx. So I'm going to do a little Dutch
here and AppResource.resx which is the culture whenever all the
resources that are going to be used whenever a culture is not found, right. And if we
go in there you can see this designer. So I have already the
CounterClicked setup which is going to translate our counter click button and a Hello
World text which is going to translate our Hello World thing. So these app
resources are already here and this resources file,
this resx file generates some code in the background, right?
And what it also does is it generates a ResourceManager and we're going to
make this resource manager, these app resources,
we're going to make them known to our localization resource manager by
saying add resource. You can add multiples here, you can
add multiple of these lines and it will just compile the whole list of
resources here and it's called Amp resources just because I call this
file App Resources, right? So if I would name this
Gerald's Resources it would say Gerald's Resources here. So that's kind of like
how that all works together. I go about it in a little bit more detail in the
other video which should pop up on your screen right now. So we've got
that set up, let's just save this. And now
LocalizationResourceManager.Maui is ready for use. So the easiest thing and probably
the most common thing that you're going to do is use
this in XAML. So let's go over to our XAML right here and go to
this label where we say Hello World. But now I'm going to actually import
this plug in here in my example as well. So I'm
going to add this XML namespace, that's how you typically do it. And
I'm going to call this loc for localization. But I don't want to have the whole
localization word in here. And then I'm going to just search here.
LocalizationResourceManager.Maui. That's the one that you want to
import. It will automatically fill that in for you. And now I can use that loc
thing. So go back to my text and you're going to use the
same syntax as for bindings and all kinds of other extensions. So I'm
going to say loc and you can already see loc:translate. So translate is a
thing that's built into this plugin and now I can just
specify the key from the resources. So I have the HelloWorld
and the CounterClicked. So I'm going to use the HelloWorld here and this
is it. And this is it. Now I'm going to get
the translation of this HelloWorld text. You also notice
there is this string format. Also again check that other video that
was just linked. It's also linked down below where you can do things with the
string format that works exactly the same here so that you can use variables
inside of your strings. We'll also see that a little bit later
when I use this stuff from code. So if I run this again on my Android
emulator, we're actually going to see the exact same app. So it's not
going to be looking really impressive actually, but it's going to now load this from
our resources file. Now while this is loading, let
me take you through to the next step because we actually want to switch
this stuff at runtime, right, right now it's already going to
switch whenever I switch languages on the device. So whenever I say in my
Android device. Of course this is also supported on iOS and all the
platforms that are supported by .NET MAUI. Whenever I switch the language
of my device and I restart the app probably, I'm not really sure
if that's necessary, it's going to automatically pick up
those resources and translate that stuff for me. But the chances are
that you probably want to dynamically translate your app while
the user is actually in here. So I was
talking long enough for the app to be actually deployed. So
let's go check that out first. And again we should see nothing
changed. The Hello World string should just be there and nothing has changed.
Right, here we go. So that's still there. But now what we can do if
I stop running this and I want to switch the language
dynamically, what the initialization line in my Maui program also did is
add the ILocalization ResourceManager, the interface to my
dependency injection container. So what I can do is just
inject that here. The ILocalization ResourceManager. And let's call
that localization ResourceManager, because why not? And
I'm going to use ILocalizationResourceManager with _localizationResourceManager... I've said
localization resource manager too many times At this point
So here we have this private field and I'm going to assign it here so that I
can use it anywhere and boom, we've done that. So now I have
this LocalizationResourceManager and what I can do here whenever I
click the button, which is a counter button, I can say, hey, if this
_localizationResourceManager. CurrentCulture.TwoLetterIsoLanguage name is NL. So whenever it's Dutch, I'm going to switch it over, set the
current culture to new CultureInfo and I'm going to set it
to well en-US. That's kind of like also very
specific. I'm just going to set it to en also there is a lot to discover with
how all the localization actually works and else I'm going to
set it to NL, right? So CurrentCulture is new CultureInfo and I'm going to set it
to NL. So now it's going to toggle between English
and Dutch and actually the English one is kind of funny because I haven't
specified English as English. That's just going to be the default one. So it's
going to fall back to the one without the identifier here, right? So
the AppResources without any identifier here. So this should
toggle that thing. So whenever I run it again, let's just do that
really quickly. Whenever I tap the button you will see that hello world
string going to toggle, right? So it's going to do that and there we go.
Actually no parameterless constructor defined for type MainPage. That's
because I forgot something. I'll just leave this in. This is fun. I'm not
perfect as well, so I forgot something because if we want to use this
constructor injection, I also need to register my MainPage, right? So
let's go to our MauiProgram and I'm going to say builder.Services AddTransient. You typically want to
add your pages as transient. And now it's
able to resolve those things as well. I'm going to
register this. Now it's going to see, hey, I need to create a MainPage and
in my dependency injection container there's also the
ILocalizationResourceManager. I'm going to inject that in my MainPage
constructor and that's how the whole dependency injection works. I got a video on that
as well. It should pop up on your screen or you can find it down
below. I've got this and it says hello world. And whenever
I tap the click me now it's going to go to Hallo Werld, right? So I didn't
show you that value but this is the Dutch value for hello world. So
that works. It Dutch now, switches around it, updates all the
stuff at runtime. So pretty cool. Add the plugin, add three lines of
code or something like that and boom. We have our localized resources right
here. So now if you want to use this from code, you
kind of like have to leverage that LocalizationResourceManager as
well. But there is a cool thing. We have a LocalizedString which is a specialized version of a string
basically. And let's call this, I don't know, _counterClicked, something like that. _counterClicked,
it's not the best name but it'll do for now. And what I can do here is
_counterClicked = new() so it's going to create a new
LocalizedString. And then in the parameter in the constructor, I
have to specify a function that will actually get the
value for me, right? So I'm just going to do this lambda expression
again and I'm going to say _localizationResourceManager. And you can use this
as a kind of collection, right, as a dictionary.
So whenever I do this block parentheses here, you can specify the
key that you actually want to get from the
resources. So here I also have that counter clicked one. And this is going to be
used to actually get that counter clicked resource, put it in that
localized string. And now I can use this as well. Actually this
one has. So let's pull up open the resources. Actually here you
can see that this has these brackets, the curly brackets
zero. And that is what you can use with the string
format. So whenever I do this, I have this _counterClicked. I'm going to use
that here for the counter button. I'm not going to do things with the
times and that kind of stuff. You can totally do
that, but I'm not going to do it for now. And I can say here
string.Format and I'm going to say that
_counterClicked.Localized, right? So that's the actual string
that's going to be the string value because the string format is not suddenly
going to understand our LocalizedString object. So I'm going to do that and
here I'm going to set that count, right? And this is important. So in
that string, in the resources, I have that curly brackets
zero, I could also add more angle brackets 1, 2, 3, 4. And then you have to
have the same number of parameters here, right? So
if I could do the count a couple of times, it's going to fill that in 0, 1, 2 now, right? And it probably doesn't make
sense to have the same value in here, but that's how you can use string
format and that's also how you can use the string format from XAML. It
works the same way. So whenever I do this now you're going to see the
CounterBtn.Text. Also flip around between the localized version
and it will have the actual value of count in there. So that is pretty
cool. Here we go. And click me, click, click. You can
see "4 keer geklikt" that's Dutch and whenever I flip it
around it's clicked 5 times. So you can see it flips around actually during
runtime. So that is pretty nice. Now this is actually
using the string from the actual like code behind, which is probably if you're
going to show dialogues and that kind of stuff, this is very helpful. But you
can also use still get some strings from your code behind and
then bind it to your XAML, right? So you can definitely do
that as well. Then you have to say something like you have to turn this
_counterClicked into a property. So it's going to be a public Localized
String and you're going to use the get and set, probably something
like that. And then you want to set this to is
new this. Okay, that works. Now the naming
doesn't really match it and you should say something
here like button, text, click me. But what you can now
say is just use a regular binding and you can say
that counterClicked.Localized string. I think this is how it
actually works. And now you can use that. I think actually XAML doesn't like
this stuff. So let's just do this and update it here as well just to see if
the IntelliSense agrees with me. So now you can say localized string,
it probably doesn't pick up on the IntelliSense localized string
and now it will update at runtime also automatically. So that's another
way of combining the code behind and the sample here as well.
All this code you can find in GitHub, the link is down below. And
that is how you can easily translate your .NET MAUI app with the
use of this amazing plugin. I'm a big fan of understanding how
stuff works under the hood, so I definitely recommend that you
watch the other video on how to do the localization yourself where you're
.NET MAUI app. And then basically forget about all of that and just
install this plug in because it's freaking amazing, because it saves you so much
time and it's so very easy to use. It just translates your
whole app just like that. And I've just showed you strings. You
can also use this for files, for images, for all kinds of things
that you want to translate. I remember that one of the things that
people were asking me on the other video is like, hey, how do I
translate all the other system stuff? So for iOS you have some system
controls, maybe for Android as well. If that's something
that you're interested in or anything else, please just let me know down in
the comments for this plugin. Thank you Johan, for putting this
together. It's really amazing. And hopefully we can get this
into a Community Toolkit soon so that it will probably reach an
even broader audience. But at least now you know how to get used,
get along with this basically. Thank you so much for
watching again one of my videos. Please click the like button subscribe to my
channel. If you haven't done so already and if you haven't had enough of me just yet,
go check out this playlist with all kinds of video
about .NET MAUI. This recommended video especially just for you on this day.
And I will hope to see you for the next one. See you for
the next one.