anton.sodergren_pdx
Topic Author
Posts: 8
Joined: 24 Mar 2022, 17:10

Support for x:Shared property for localization

20 May 2022, 12:21

Hi,
tl;dr: Are there any plans for implementing support for the x:Shared property in Noesis? Or some alternative way to achieve the same thing?

I'm experimenting with how we are going to solve localization and text formatting in our UIs. My first thought was to create resource dictionaries with a resource for each localization key. However, since we need the text to be formatted with boldness, colors, text icons etc. it will not be enough to simply store string values in the resource dictionaries. We also want to be able to use bindings to properties of the data context in our loc entries. So I tried having each loc entry be a TextBlock, like this:
<TextBlock x:Key="[email protected]_GAME">New Game</TextBlock>
<TextBlock x:Key="[email protected]"><Bold>bold text</Bold> and images <InlineUIContainer><Image Source="{StaticResource paradox_logo}"/></InlineUIContainer></TextBlock>
<TextBlock x:Key="[email protected]_VALUE_PERCENTAGE"><Run Text="{Binding Path=Value, StringFormat=p0}"/></TextBlock>
Then I would use them like this:
<Button Content="{StaticResource [email protected]_GAME}"/>
<ContentControl Content="{StaticResource [email protected]}"/>
The issue is if I want to use the same resource in multiple places, like so:
<ContentControl Content="{StaticResource [email protected]}"/>
<ContentControl Content="{StaticResource [email protected]}"/>
Then the text only shows up once, because both content controls are literally referring to the same TextBlock instance, rather than instantiating copies of the TextBlock. This is fixed by using the x:Shared property, like so:
<TextBlock x:Key="[email protected]_GAME" x:Shared="False">New Game</TextBlock>
This works fine in Blend, but it seems like this property is not supported in Noesis. Are there any plans to implement it? Or do you have ideas on how to work around it in a nice way?
We have only just started experimenting with localization and text formatting in Noesis, so we still have the possibility to go down a different route entirely, but it certainly would be nice if we were able to use static resources in this manner.
 
Faerdan
Posts: 73
Joined: 02 Oct 2015, 09:11
Location: Galway, Ireland
Contact:

Re: Support for x:Shared property for localization

20 May 2022, 14:52

Hi Anton,

This is a bit of a tangent, but I thought I'd share how I have handled localization with formatted text.

We created a simple BBCode parser which generates Inline elements from a BBCode formatted string. This allows us to keep our localization text as strings, allowing us to store it in XAML but also in our database (for dynamic content). It is also easier to teach people how to edit the text, as BBCode is widely used across the internet.

A simple example:
"This is [b]bold[/b], this is [color=Red]red[/color] and here is an image [img]/GUI/Assets/Image/SomeImage.png[/img]"
Becomes something like:
<TextBlock>
  <TextBlock.Inlines>
    <Run>This is </Run>
    <Run FontWeight="Bold">bold</Run>
    <Run>, this is </Run>
    <Run Foreground="Red">red</Run>
    <Run> and here is an image </Run>
    <InlineUIContainer><Image Source="/GUI/Assets/Image/SomeImage.png" /></InlineUIContainer>
  </TextBlock>
</TextBlock>
For binding values we use an injection system where you pass values to the TextBlock via a DependencyProperty Let me know if you're interested in more details.
 
anton.sodergren_pdx
Topic Author
Posts: 8
Joined: 24 Mar 2022, 17:10

Re: Support for x:Shared property for localization

20 May 2022, 15:14

Thanks for sharing, Faerdan!

I'm guessing that you have a custom control that you use instead of TextBlock, something like "ParsedTextBlock", in which the parsing logic takes place and in which the inlines get populated via code whenever the "Text" property is updated? Do you also do any data binding within your localization strings? I suppose that should still be possible with this approach.

Having a "ParsedTextBlock" control is definitely an interesting approach, and probably the next thing I'll experiment with if I can't find a neat enough way to store the formatted strings as static resources.

Honestly, either way we would have to parse our original localization strings from our own format to translate them to XAML (or the equivalent code representation), since the files that the content designers and translators will work with will be YML files rather than XAML files. We have our own formatting language that we use in those files (not BBCode, but has similar functionality), which we've used in previous games, so the differences between the approaches is only rather when/where that parsing takes place.
 
Faerdan
Posts: 73
Joined: 02 Oct 2015, 09:11
Location: Galway, Ireland
Contact:

Re: Support for x:Shared property for localization

20 May 2022, 15:43

You got it exactly, right down to the name of the ParsedTextBlock control. 😂

For binding we inject the values.

Binding these values looks like this:
<common:ParsedTextBlock Text="The cost of fuel is: [b]{{fuelCost}}[/b].">
    <common:ParsedTextBlock.TextParameters>
        <common:ParameterViewData Key="fuelCost" Value="{Binding DataContext.CurrenciesData.Fuel, ElementName=textControl}" />
    </common:ParsedTextBlock.TextParameters>
</common:ParsedTextBlock>
The {{}} is parsed before BBCode.

This simplifies the formatting needed to bind data, since we use simple text keys in the string for each text parameter. The more complex binding syntax is then kept in the XAML.
 
Faerdan
Posts: 73
Joined: 02 Oct 2015, 09:11
Location: Galway, Ireland
Contact:

Re: Support for x:Shared property for localization

20 May 2022, 17:26

<TextBlock x:Key="[email protected]_VALUE_PERCENTAGE"><Run Text="{Binding Path=Value, StringFormat=p0}"/></TextBlock>
I do not think that you can use the Binding markup in a ResourceDictionary.

I have been trying to think of ways you might store the localizations in a ResourceDictionary, with bindings. Generating control templates seems like the only way, though it's unorthodox..

You could create a custom control with an observable dictionary DependencyProperty, and then fill this dictionary with text parameters as we do for our values. Then inside the control templates you could use a TemplateBinding markup to bind to these keys.
 
anton.sodergren_pdx
Topic Author
Posts: 8
Joined: 24 Mar 2022, 17:10

Re: Support for x:Shared property for localization

23 May 2022, 09:59

You got it exactly, right down to the name of the ParsedTextBlock control.
Hah! I had heard the name before from another studio actually, but it's a name that makes sense in the context.

I think I will try out this approach with a parsed textblock control actually. The more I think about it, the more advantages I see with it. It means that you can use it in the exact same way you would use a normal TextBlock, and apply styles to it as a normal TextBlock, which is not the case for the approach I outlined in my original post. It also means the parsing doesn't have to be done until it's actually needed.
Generating control templates seems like the only way, though it's unorthodox..
I actually tried doing it this way on Friday last week. It absolutely worked, but it feels weird to do. Our UI designers will give me strange looks if I propose that solution.
Binding these values looks like this:
Ahh interesting. That's a smart way to solve it, though it basically adds an additional layer of binding which I would like to avoid if possible. I think I will try first to see if I can do the binding directly in the loc strings. It should be possible to add bindings in code, though it requires additional parsing. Our content designers also tend to do some pretty advanced stuff in localization strings, so I want to make sure to support the things that they already do in our other games, if possible.
I do not think that you can use the Binding markup in a ResourceDictionary.
You can use Binding in resource dictionaries, as long as you are in the right data context at the point where you use your resource. This worked when I tried it last week, and we also do it a bit in templates that are stored in resource dictionaries. :)
 
Faerdan
Posts: 73
Joined: 02 Oct 2015, 09:11
Location: Galway, Ireland
Contact:

Re: Support for x:Shared property for localization

23 May 2022, 11:52

I think I will try out this approach with a parsed textblock control actually. The more I think about it, the more advantages I see with it. It means that you can use it in the exact same way you would use a normal TextBlock, and apply styles to it as a normal TextBlock, which is not the case for the approach I outlined in my original post. It also means the parsing doesn't have to be done until it's actually needed.
It has worked brilliantly for us, and we also have a heavily UI driven game.
I actually tried doing it this way on Friday last week. It absolutely worked, but it feels weird to do. Our UI designers will give me strange looks if I propose that solution.
We did a lot of things like this when we started using WPF. In the end it was too much work to manage and maintain, and it felt like we were constantly fighting how WPF "wanted" to do things.

You can use Binding in resource dictionaries, as long as you are in the right data context at the point where you use your resource. This worked when I tried it last week, and we also do it a bit in templates that are stored in resource dictionaries. :)
Yeah I was confusing things, as you the Binding markup does work in a ResourceDictionary. We avoid using the Binding markup in ResourceDictionary entries as we don't want to rely on having specific DataContext data in order to use them. This allows us to move ResourceDictionary entries around, from local to shared scope, without modifying the markup.
 
User avatar
sfernandez
Site Admin
Posts: 2530
Joined: 22 Dec 2011, 19:20

Re: Support for x:Shared property for localization

26 May 2022, 13:22

Are there any plans for implementing support for the x:Shared property in Noesis?
Hi, this feature is not reported yet, could you please add a ticket in our bugtracker?

Anyway, following the conversation (thanks a lot @Faerdan for your participation here), I think there are better ways to approach this. In fact our plan for localization is to provide an official solution (see ticket #2355) based on a MarkupExtension that would be able to get localized strings from resource dictionaries. It will allow you to specify the source dictionary globally for a whole view, or locally for part of the UI using an inheritable attached property (and more things like fallback texts for design time), something like this:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:l="clr-namespace:Localization"
  l:Loc.Source="Languages/lang-en.xaml">
  <TextBlock Text="{l:Loc PageTitle, Id=Title}"/>
  ...
  <StackPanel l:Loc.Source="Languages/lang-fr.xaml">
    <TextBlock Text="{l:Loc Id=Name}"/>...
    <TextBlock Text="{l:Loc Id=Address}"/>...
  </StackPanel>
</Grid>
This could be combined with a rich text parser (we have plans for that: #1963), to get complex formatted texts, even with bindings:
<TextBlock noesis:Text.RichText="{l:Loc Id=FuelCost}"/>
<ResourceDictionary ...>
  <sys:String x:Key="FuelCost">The cost of fuel is: [b]{Fuel.Cost}[/b]</sys>
  ...
</ResourceDictionary>
This would be expanded by the rich text parser to something like this:
<TextBlock>
  <Run Text="The cost of fuel is:"/>
  <Bold><Run Text="{Binding Fuel.Cost}"/></Bold>
</TextBlock>
Do you think that approach could cover what you need?
 
anton.sodergren_pdx
Topic Author
Posts: 8
Joined: 24 Mar 2022, 17:10

Re: Support for x:Shared property for localization

15 Jun 2022, 12:22

Sorry for not responding, didn't check my notifications here.

So I've actually implemented a parsed text block control now, similar to what Faerdan suggested. And it seems to work really well.

For now I skipped the resource dictionary completely. Got some feedback that it seemed unnecessary to keep another copy of all the localization strings, since we have them in our central localization system anyway in the game engine. The textblock simply takes in the localization key as a property. So the current usage right now is something like this:
<jomini:ParsedTextBlock LocKey="MY_LOC_KEY"/>
The loc strings are then stored in .yml files, something like this:
MY_LOC_KEY: "This is some text with #bold bold text#! and #color:Orange colored text#! and bindings [Thing.Value]"
Which is the same formatting syntax that we use for our other games. Gets translated to something like this in the inlines of the textblock:
<jomini:ParsedtextBlock>
	<Run>This is some text with </Run>
	<Span FontWeight="Bold">bold text</Span>
	<Run> and </Run>
	<Span Foreground={StaticResource Brush_Orange}>colored text</Span>
	<Run> and bindings </Run>
	<Run Text={Binding Thing.Value}/>
</jomini:ParsedTextBlock>
The only real downside is that since all the localization and parsing logic is in the C++ game engine, the localized texts can't be previewed in Blend for now. So in my current implementation in Blend, the same text block is simply translated to something like this:
<jomini:ParsedTextBlock>MY_LOC_KEY</jomini:ParsedTextBlock>
Which is not really ideal ofc. Will look into maybe porting some of the logic to C#.
In fact our plan for localization is to provide an official solution (see ticket #2355) based on a MarkupExtension that would be able to get localized strings from resource dictionaries ...
This could be combined with a rich text parser (we have plans for that: #1963), to get complex formatted texts, even with bindings: ...
Do you think that approach could cover what you need?
This surely sounds like a nice feature to have in Noesis! But I don't think we will be using it for our game, since we have our own stuff (both for the actual localization and for the text parsing now).

Anyway, for the x:Shared property that this post was originally about. We don't need that either for the localization now since I went with a different approach. But nonetheless it could still be useful to have for other things. So I could make a ticket for it, though it's not a high priority for us now.
 
User avatar
jsantos
Site Admin
Posts: 3414
Joined: 20 Jan 2012, 17:18
Contact:

Re: Support for x:Shared property for localization

15 Jun 2022, 17:25

The only real downside is that since all the localization and parsing logic is in the C++ game engine, the localized texts can't be previewed in Blend for now.
Sorry for this inconvenience. We are totally aware of this and we are working on a solution (our own editor, based on Blend, but much better, implemented with Noesis, in-process with your game). 😀

Who is online

Users browsing this forum: No registered users and 0 guests