Search code examples
macosbundlelocale

How to use C++ std::locale in MacOS bundle application?


Summary: It seems that C++ std::locale function works OK only from the MacOS terminal application but not when bundled in a MacOS application bundle.

I have written a C++ application on MacOS High Sierra that uses the C++17 std::locale function.

For most of the program I want the default "C" locale which is already set. However for a special case I want to set the stream output of that class to use the system locale.

It works great in testing when I run from the command line but when I package the application up into a MacOS "application bundle" with the following structure:

MyApp.app/Contents/MacOS/MyApp

then it doesn't work correctly.

It APPEARS as if the LANG environment variable that is set in the MacOS Terminal application is not set for MacOS bundle applications.

#include <iostream>
#include <fstream>
#include <sstream>

void test( std::ostream &output_, int test_, bool useLocale_, const std::string &expected_ )
{
  int i = 1234;

  std::stringstream ss;

  if ( useLocale_ )
  {
    ss.imbue( std::locale( "" ) );
  }

  ss << i;

  if ( ss.str( ) == expected_ )
  {
    output_ << "Test " << test_ << ": Passed" << std::endl;
  }
  else
  {
    output_ << "Test " << test_ << ": Expected '" << expected_ << "' but got '" << ss.str( ) << "'" << std::endl;
  } 
}

int main( )
{
  std::ofstream output( "/Users/david/test.txt" );

  test( output, 1, false, "1234"  );
  test( output, 2, true,  "1,234" );

  return 0;
}

The expected results (and the results obtained when running from MacOs Terminal):

Test 1: Passed
Test 2: Passed

However, what I get when double-clicking on the MacOS MyApp.app icon:

Test 1: Passed
Test 2: Expected '1,234' but got '1234'

So the question is: How to get the MacOS Bundle application to either set the LANG environment variable to the same thing that the MacOS terminal application is using or some other work around that accomplishes the same thing?

I've spent a couple of days scouring the Internet for an answer and have seen some related issues but none that directly matched my issue.

How to either set LANG for MacOS bundle applications or get the system LOCALE some other way?

EDIT: I've done some more testing and the problem is that the LANG environment variable is not getting set on a bundled application.

So now the question may come down to: How to get the LANG information from the MacOS system without the LANG environment variable being set?


Solution

  • Thank you.

    That solved my problem.

    #ifdef __APPLE__
    // MACOS needs a special routine to get the locale for bundled applications.
    if ( getenv( "LANG" ) == nullptr )
    {
      const char *lang = get_mac_locale( );
      setenv( "LANG", lang, 1 );
    }
    
    #endif
    

    Now my program runs correctly from both Apple Terminal and as a bundled application.