Jump to content

PSA: ExperienceTrait.Title and ExperienceTrait.TypeName are both localized, do not use in logic / persistence


cakepie

Recommended Posts

If you wrote/maintain any plugin that tests or manipulates kerbal's class/specialization, this is a thing you need to know about.

Credit goes to DMagic, IIRC, who was the first to point this out to me a couple of years ago, I think it was shortly after 1.3 dropped.
Came up again because I recently saw this crop up in USI-LS, and happened to be working on related stuff myself so ended up thoroughly re-testing it (to see if was fixed in subsequent releases, but nope)

A crude search on GitHub found quite a lot of code using these properties. It's not really feasible to trawl through all of them to identify which are actual issues and then notify the maintainers, so hopefully this PSA will suffice.

 

Overview

In the ExperienceTrait class (API link) that represents each Kerbal's specialization/class there are properties Title and TypeName.
You'd normally expect one of them (Title) to be a localized string, for display purposes, and the other (TypeName) to be the internal identifier for that Trait type.
But no! Both of these strings are localized. It's fine if you're just pulling them to display in the UI somewhere, but neither of them should be used in logic or persistence, e.g.:

Testing if a kerbal is of a certain class/specialization

if (pcm.experienceTrait.TypeName == "Engineer")

or backing up the original trait (before temporarily replacing it)

originalTrait = pcm.experienceTrait.TypeName;

If your mod has code similar to this, using either of the abovementioned properties, there will be problems for players using any language other than English.
(Even if your mod hasn't been localized, keep in mind that it can still be used in together with localized KSP.)

 

Recommendation: use only unlocalized for non-display, such as ExperienceTrait.Config.Name

 

Please don't: I saw some code that resorted to testing against localized strings, similar to the following. It works, but yikes. *cringe*

if (pcm.experienceTrait.TypeName == Localizer.Format("#autoLOC_XXXXXX"))

 

Full list of related properties

These are unlocalized:

  • ProtoCrewMember.trait
  • ExperienceTrait.Config.Name

Per above, ExperienceTrait.TypeName is localized, although it seems like it shouldn't be.

These are localized, and working as intended:

  • ProtoCrewMember.GetLocalizedTrait()
  • ExperienceTrait.Title
  • ExperienceTrait.Config.Title

The lists GameDatabase.Instance.ExperienceConfigs.TraitNames / .TraitNamesNoTourist are also the unlocalized ids, if you're not working with specific kerbals.

 

Test Code and Results

Here is some debug code that you can run for yourself to verify.
It adds the command /etdt to the debug console in spacecenter.
 

using System;
using UnityEngine;
using KSP.UI.Screens.DebugToolbar;

namespace ExperienceTraitDebug
{
	[KSPAddon(KSPAddon.Startup.SpaceCentre, false)]
	public class DebugConsole : MonoBehaviour

	{
		private const string Command = "etdt";
		private const string HelpString = "ExperienceTrait debug tool.";
		private void Awake()
		{
			DebugScreenConsole.AddConsoleCommand(Command, OnCommand, HelpString);
		}
		private void OnDestroy()
		{
			DebugScreenConsole.RemoveConsoleCommand(Command);
		}
		private void OnCommand(string argStr)
		{
			ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[0];
			Log("Trait Variables in {0}: \r\n  pcm.t    {1}\r\n  pcm.glt  {2}\r\n  et.tn    {3}\r\n  et.t     {4}\r\n  et.c.n   {5}\r\n  et.c.t   {6}\r\n  gd.ec.tn   {7}\r\n  gd.ec.tnnt {8}",
				Versioning.GetVersionStringFull(),
				pcm.trait,
				pcm.GetLocalizedTrait(),  // note: will throw MissingMethodException in KSP 1.3.X, remove to avoid
				pcm.experienceTrait.TypeName,
				pcm.experienceTrait.Title,
				pcm.experienceTrait.Config.Name,
				pcm.experienceTrait.Config.Title,
				GameDatabase.Instance.ExperienceConfigs.TraitNames[0],
				GameDatabase.Instance.ExperienceConfigs.TraitNamesNoTourist[0]
			);
		}
		private void Log(string msg, params object[] args)
		{
			Debug.LogFormat($"[DEBUG] {msg}", args);
		}
	}
}

 

Sample results on various KSP versions (Japanese localization)

[DEBUG] Trait Variables in 1.3.1.1891 (WindowsPlayer x64): 
  pcm.t    Pilot
  pcm.glt  // n/a
  et.tn    パイロット
  et.t     パイロット
  et.c.n   Pilot
  et.c.t   パイロット
  gd.ec.tn   Pilot
  gd.ec.tnnt Pilot

[DEBUG] Trait Variables in 1.4.5.2243 (WindowsPlayer x64): 
  pcm.t    Pilot
  pcm.glt  パイロット
  et.tn    パイロット
  et.t     パイロット
  et.c.n   Pilot
  et.c.t   パイロット
  gd.ec.tn   Pilot
  gd.ec.tnnt Pilot

[DEBUG] Trait Variables in 1.5.1.2335 (WindowsPlayer x64): 
  pcm.t    Pilot
  pcm.glt  パイロット
  et.tn    パイロット
  et.t     パイロット
  et.c.n   Pilot
  et.c.t   パイロット
  gd.ec.tn   Pilot
  gd.ec.tnnt Pilot

[DEBUG] Trait Variables in 1.6.1.2401 (WindowsPlayer x64): 
  pcm.t    Pilot
  pcm.glt  パイロット
  et.tn    パイロット
  et.t     パイロット
  et.c.n   Pilot
  et.c.t   パイロット
  gd.ec.tn   Pilot
  gd.ec.tnnt Pilot

 

 

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...