Snark

Preferred way to put C# format strings in localization config?

Recommended Posts

So I'm authoring a mod, and since I'd like to be a well-behaved global citizen, I'm setting it up so that all of the user-facing strings are in a localization file (even though I'm only releasing it in English).  The config file for localization looks like this:

Localization
{
    en-us
    {
        #MyModName_someTag = This is a user-facing string.
        #MyModName_someOtherTag = This is another user-facing string.
        // etc.
    }
}

So far, so good.

But let's say that the user-facing string I want to store is a format specifier, i.e. it's something like this:

You have {0} seconds until the universe explodes!

...where the "{0}" is an insertion point for some parameter.

I say "{0}" because that syntax ("{0}", "{1}", etc.) is the standard syntax for C# format strings; it plays nice with the string.Format() function.

Well, what I'd like to do is just put it into config, like this:

Localization
{
    en-us
    {
        // Message displayed to user when the universe is about to explode.
        // The {0} is the number of seconds remaining.
        #MyModName_universeExplodeFormat = You have {0} seconds until the universe explodes!
    }
}

...The problem, though, is that curly braces are part of config syntax, so if I literally just use the string "{0}", the KSP config parser interprets it as a child node and hilarity ensues.

I can certainly hack my way around it-- for example, I could pick some other bracket type that the config parser doesn't care about, e.g. use [0] instead of {0}, and in my code that reads this, I just do a search-and-replace to swap out the brackets before passing it to string.Format().  So it's not... blocking me, exactly, but it's kludgy and idiosyncratic, both of which I dislike when I'm coding.

So, my question is:  How do people usually deal with this?  Is there a common practice that people tend to follow?  Surely this must be a thing that comes up?

 

Share this post


Link to post
Share on other sites
Posted (edited)

The Lingoona format for that is <<1>>, and then pass the argument as an extra parameter to KSP.Localization.Localizer.Format:

https://github.com/HebaruSan/Astrogator/blob/674952ab884a6b8c087d81957a36ce02c8cb0205/assets/lang/en-us.cfg#L10

		astrogator_outboundHyperbolicError = <<1>> is on an escape trajectory.\nCapture to see transfers.

https://github.com/HebaruSan/Astrogator/blob/674952ab884a6b8c087d81957a36ce02c8cb0205/src/ViewTools.cs#L1112-L1115

using KSP.Localization;

	return Localizer.Format(
		"astrogator_outboundHyperbolicError",
		TheName(model.origin)
	);

The documentation for this stuff, such as it is:

http://lingoona.com/cgi-bin/grammar#l=en&amp;oh=1

Edited by HebaruSan

Share this post


Link to post
Share on other sites

Thanks, makes sense. The downside of having Lingoona do it for me is that I don't get the benefit of the rich format specifiers (e.g. numeric formats, etc.) that C# formatting provides. Anyway, though, good to know about. Thanks!

Share this post


Link to post
Share on other sites

Also note that the Lingoona format start with 1 for argument numbers, rather than 0 like everything else.

As for not being able to specify the numerical format in the config, you can take a little bit of solace in the fact that you can avoid a few bytes of garbage allocation for each string by avoiding the boxing inherent in using something like: :wink:

string text = String.Format("{0:N2}", 45.234}; //The float is boxed and generates garbage

string text = String.Format("{0}", 45.235.ToString("N2"); //The argument is no longer boxed and doesn't generate garbage (though ToString will always generate a little bit of garbage)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now