1

I have worked in companies that to achieve translations based on the user's localization they use a file to store those translations. However, when they try to access a translation on that file they commonly do it with "magic" strings like this:

Translate("$global.name")

Translate(string keyword); is a function that looks up into these files with that keyword and the current user language code.

the xml file to access that translation looks like this:

<word code="$global.name">
    <localization lang="es-MX">
        <![CDATA[nombre]]>
    </localization>
</word>

I have read that using magic strings is a bad practice since is subject to run-time errors and becomes a nightmare when you have to change a magic string in multiple locations.

How magic strings should be avoided in this situation?

Laiv
  • 14,283
  • 1
  • 31
  • 69
  • 5
    That actually looks like a pretty good approach to me. – Robert Harvey Dec 31 '19 at 18:34
  • 2
    I don’t think your example code contains a magic string. Not according to the wikipedia definition anyway. – Rik D Dec 31 '19 at 18:47
  • It should be fairly easy to write a static analyzer that could verify all these strings at compile time, avoiding runtime errors. – Dave M Dec 31 '19 at 18:53
  • 1
    You could take it one step further and have constants with values of the the "magic strings". If they were properties on a static class, e.g., you could also use them to create tests to verify each supported language has a value. – ps2goat Dec 31 '19 at 19:25
  • 4
    Those aren't magic strings. This is a clumsy-looking-but-better-than-the-alternative technique for **avoiding** magic strings. – Kilian Foth Jan 01 '20 at 07:22
  • 2
    If you were using traditional .resx files for your internationalized string resources, you could leverage the [PublicResxFileCodeGenerator](http://www.guysmithferrier.com/post/2008/06/Public-Strongly-Typed-Resources-With-PublicResXFileCodeGenerator.aspx), which generates compile-time symbols for each of those "magic strings" so that you can use them in code. – John Wu Jan 02 '20 at 03:50
  • 1
    According to Wikipedia's definition for [magic string](https://en.wikipedia.org/wiki/Computer_programming): `In computer programming, a magic string is an input that a programmer believes will never come externally and which activates otherwise hidden functionality.` Your case doesn't look like a magic string to me. You are equaling *magic numbers* and *magic strings*. Curiously, Wikipedia also warns you to don't do that `Not to be confused with Magic number (programming)` – Laiv Jan 02 '20 at 13:34

2 Answers2

2

Your example is not the much maligned "magic string", rather its a bit like a Translation Dictionary, where you supply the dict key (which is a string) and get back a value. Now, your code is not ideal because I could mistype string value "$globl.name" and not know until runtime that I messed up, but that's not the worst thing in the world.

Here's an example of what I would call a magic string, by which I mean that for all possible string choices, there is a non-obvious one that triggers the code to do something else:

void DoThing(string inputString) {
    if (inputString == "foobar") {
        dbConnection.DoSomethingUnusual();
    }
    dbConnection.MakeSomeWidgets(inputString);
}

In the above example, I would have to read every line of the function to know how it would behave based on different values for the input string param. Some values of the param 'magically' trigger the function to do different things, with the type system being of no help to let me know ahead of time what's going to happen.

Back to your example, as has been said by others, you could resolve your concerns about the strings by using constants or enums to lock down the Translate() callsites in some manner.

// Somewhere global
public const string Translate_Name = "$global.name";

// At callsite
Translate(Translate_Name)
Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Graham
  • 3,833
  • 1
  • 21
  • 18
0

There is no such thing as a "magic string" all the definitions on the web would be better called "hard-coded values"

A magic number is a hard-coded value that has no relation to the information it is encoding.

int Port = 80 // hard-coded value, literally the value to use for the port

where UserType == 7 // magic number

You don't get magic strings because its trivial to make the string explanatory

where UserType == "admin" // literally the type of user

You would have to be a super genius HaX0r to code something like

where UserType == "seven" //mind blown!

In your translation example the strings and their values are not hard coded but held in a configuration file. Only the key value is hard coded in the code which retrieves the value.

Obviously hard-coded values are also a bad thing and it would be great to have compile time checking of the existence of the key, say for example by using static classes, but often the jobs of writing the code and doing or updating the translations are separated. So in practice this is not preferred.

Ewan
  • 70,664
  • 5
  • 76
  • 161