Today we’re visiting a very basic feature of computing and programming: converting text to data. Adding the complexity of different languages makes this much more complicated than it should be. Check the video for the details:

In this video, Erik demonstrates how to handle data evaluation in different languages within Business Central AL development. When you receive text data formatted according to a different locale — such as decimal numbers with commas instead of dots — the standard Evaluate function and even GlobalLanguage can produce unexpected results. Erik walks through the problem and introduces the TypeHelper codeunit as a reliable solution.
The Problem: Evaluating Data in Different Locales
When working with Business Central, you’ll often receive data as text that needs to be converted into proper data types like decimals or dates. The standard approach is to use the Evaluate function:
Evaluate(D, '123,456');
Message('Result: %1', D);
Think of the Evaluate function as the equivalent of writing D := ... — the parameters follow the same order as an assignment statement.
However, this is where things get tricky. If your Business Central environment is set to English (United States), the comma in '123,456' is interpreted as a thousand separator, giving you 123456 instead of the intended 123.456 (as it would be in French or many European locales).
Why GlobalLanguage Doesn’t Always Work
Your first instinct might be to switch the global language before evaluating:
GlobalLanguage(3084); // Switch to French Canadian
Evaluate(D, '123,456');
GlobalLanguage(1033); // Switch back to US English
Surprisingly, this doesn’t always produce the correct result. There’s something unpredictable about the GlobalLanguage function in certain scenarios. Erik suspects it has to do with the distinction between regional and global language settings — GlobalLanguage is supposed to switch both, but in some cases (like API calls), it doesn’t behave as expected.
The Solution: TypeHelper.Evaluate
The reliable approach is to use the TypeHelper codeunit, which has an Evaluate function that accepts an explicit culture name:
TypeHelper.Evaluate(Variant, String, Format, CultureName)
Finding the Culture Name
To get the culture name for a given language ID, you can use the Language codeunit:
// Example: Get culture name for French Canadian (3084)
Message('%1', Language.GetCultureName(3084));
// Returns: "fr-CA"
// For English US (1033):
Message('%1', Language.GetCultureName(GlobalLanguage()));
// Returns: "en-US"
How TypeHelper.Evaluate Works
There’s an important quirk to understand: if you look at the source code of TypeHelper.Evaluate (by pressing F12), you’ll see it starts with a case true of block that checks the type of the variant using methods like IsDate, IsDecimal, etc. This means you must assign a value of the correct type to the variant before calling the function, so it knows what type to evaluate into.
var
TypeHelper: Codeunit "Type Helper";
Language: Codeunit Language;
V: Variant;
D: Decimal;
// Initialize the variant with the target type
V := D; // D is 0 (uninitialized decimal), but this tells the variant it holds a Decimal
// Evaluate using French Canadian culture
TypeHelper.Evaluate(V, '123,456', '', Language.GetCultureName(3084));
// Convert back from variant to decimal
D := V;
Message('Result: %1', D);
// Returns: 123.456 ✓
Packaging It Nicely
Since working with variants is a bit awkward, Erik recommends wrapping this logic into a clean helper procedure:
procedure StringToDecimal(InputString: Text; LanguageID: Integer): Decimal
var
TypeHelper: Codeunit "Type Helper";
Language: Codeunit Language;
V: Variant;
D: Decimal;
begin
V := D;
if not TypeHelper.Evaluate(V, InputString, '', Language.GetCultureName(LanguageID)) then
Error('Could not convert to a decimal: %1, Language: %2', InputString, LanguageID);
D := V;
exit(D);
end;
Now you can use it simply:
Message('%1', StringToDecimal('123,45678', 3084));
Key Takeaways
- The standard
Evaluatefunction uses the current environment’s locale, which can misinterpret data formatted in other languages. GlobalLanguageis useful in many cases but can be unpredictable — particularly in API call scenarios where regional settings may not switch as expected.TypeHelper.Evaluatewith an explicit culture name is the reliable, predictable approach for converting text data from a known locale.- You must initialize the variant with the correct target type before calling
TypeHelper.Evaluate, since it uses the variant’s type to determine how to parse the string. - Use the
Languagecodeunit’sGetCultureNamefunction to convert language IDs (like 1033, 3084) into culture name strings (like “en-US”, “fr-CA”). - Wrap the variant-based logic in a clean helper procedure to keep your calling code simple and readable.