Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

CultureInfo.CurrentCulture always returning Invariant Language (Invariant Country)

Discussion in 'Scripting' started by CaponeUnity3D, Sep 13, 2018.

  1. CaponeUnity3D

    CaponeUnity3D

    Joined:
    May 15, 2017
    Posts:
    5
    I've been trying to get the country of the ios/android device but It's getting quite messy. This should return the country code but it's always returning: Invariant Language (Invariant Country).
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Globalization;
    3. void Start()
    4. {
    5.     string lg = CultureInfo.CurrentCulture.EnglishName;
    6. }
    I'm using Unity 2018.2.6 in a MAC Computer.
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    this should actually work. The
    CultureInfo.CurrentCulture
    points to
    Threading.CurentThread.CurrentCulture
    . This should be the Setting of the Operating System by default.

    However, it can be changed. And it often makes sense to change. E.g. when you are serializing floating point numbers you want them with a dot as separator (German would use a comma instead) to be sure it can be parsed later on.

    So maybe some code in your project sets the Current Culture to Invariant. You have to be faster than that.
    So rename your method to "Awake" rather than "Start" and add your script to the "Script Execution Order" settings in unity. Put it there as the very first one. If it still fails after that, it is probably a bug of the Scripting backend you are using (you should then try to use the .Net 4.x Equivalent) or with the operating system itself...
     
  3. CaponeUnity3D

    CaponeUnity3D

    Joined:
    May 15, 2017
    Posts:
    5
    After creating a new empty project only with this simple script and also changing "Start()" with "Awake()" CultureInfo.CurrentCulture is still returning: Invariant Language (Invariant Country). So I supose it's a Unity version bug.

    @Hosnkobf you can try it by yourself and see if it works for you.
     
  4. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    I noticed this was changed between 2017 and 2018
     
  5. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    maybe
    Application.systemLanguage
    is enough for your case!?
     
  6. CaponeUnity3D

    CaponeUnity3D

    Joined:
    May 15, 2017
    Posts:
    5
    No, I need the country code for analysis reasons. I thing I will try with a simple plugin for iOS and native Java code for Android.
     
    thienhaflash likes this.
  7. CaponeUnity3D

    CaponeUnity3D

    Joined:
    May 15, 2017
    Posts:
    5
    I'have finally recieved the iOS device country code by creating a simple plugin that returns it.

    Code (CSharp):
    1. #if UNITY_IOS
    2.     [DllImport("__Internal")]
    3.     private static extern string IOSgetPhoneCountryCode();
    4. #endif
    5.  
    6.     void Start () {
    7.             Debug.Log("Pais: " + IOSgetPhoneCountryCode());
    8.     }
    .mm file:

    #import <Foundation/Foundation.h>
    @interface MyPlugin: NSObject
    {
    //You have to put your variables here
    }
    @End
    @implementation MyPlugin
    //Converting String to char for UNITY
    //Rememeber that unity can't handle NSString variables
    char* cStringCopy(const char* string)
    {
    if (string == NULL)
    return NULL;
    char* res = (char*)malloc(strlen(string) + 1);
    strcpy(res, string);
    return res;
    }
    @End
    // This is the function we call from unity script
    extern "C"
    {
    char* IOSgetPhoneCountryCode()
    {
    NSLocale *locale = [NSLocale currentLocale];
    NSString *countryCode = [locale objectForKey: NSLocaleCountryCode];
    //NSString *countryName = [locale displayNameForKey: NSLocaleCountryCode value: countryCode];
    return cStringCopy([countryCode UTF8String]);
    }
    }
     
  8. CaponeUnity3D

    CaponeUnity3D

    Joined:
    May 15, 2017
    Posts:
    5
    For android devices:
    Code (CSharp):
    1. using (AndroidJavaClass cls = new AndroidJavaClass("java.util.Locale"))
    2.         {
    3.             using (AndroidJavaObject locale = cls.CallStatic<AndroidJavaObject>("getDefault"))
    4.             {
    5.                 string android_idioma1 = locale.Call<string>("getLanguage");        //El resultado: es
    6.                 string android_idioma2 = locale.Call<string>("getDisplayLanguage"); //El resultado: español
    7.                 string android_idioma3 = locale.Call<string>("getISO3Language");    //El resultado: spa
    8.  
    9.                 string android_pais1 = locale.Call<string>("getCountry");           //El resultado:ES
    10.                 string android_pais2 = locale.Call<string>("getDisplayCountry");    //El resultado:España
    11.                 string android_pais3 = locale.Call<string>("getISO3Country");       //El resultado:ESP
    12.  
    13.             }
    14.         }
     
  9. xmedeko

    xmedeko

    Joined:
    Jun 6, 2018
    Posts:
    23
  10. SaltwaterAssembly

    SaltwaterAssembly

    Joined:
    Mar 8, 2016
    Posts:
    95
  11. xmedeko

    xmedeko

    Joined:
    Jun 6, 2018
    Posts:
    23
  12. doctorpangloss

    doctorpangloss

    Joined:
    Feb 20, 2013
    Posts:
    270
    Use a localization plugin. Or write the native platform plugin. il2cpp platforms strip the culture info stuff because it's colossal and does a ton of initialization of first use with a bunch of allocations.
     
  13. xmedeko

    xmedeko

    Joined:
    Jun 6, 2018
    Posts:
    23
    @doctorpangloss Unity Technologies @JoshPeterson has written "it should be working on all platforms." So, either it's working or it's a bug. If IL2CPP strips some important CultureInfo initialization, then it should be fixed or documented.
     
  14. nmd2

    nmd2

    Joined:
    Mar 19, 2019
    Posts:
    13
    Just hit this too. We use swagger code generation for our API endpoints, so anything returning a System.String e.g. a Java spring ResponseEntity<String>, would be pushed into the System.Convert.ChangeType() conversion method which would try to compare against a null CultureInfo.CurrentCulture and crash on iOS devices.

    Got around it by responding with domain objects which would bypass that String conversion to a json deserialization method in the swagger code, but still, it was nasty bug that took over a day to resolve.
     
  15. austinborden

    austinborden

    Joined:
    Aug 5, 2016
    Posts:
    24
    On 2019.2.21 it looks like CurrentCulture is returning CultureInfo.InvariantCulture on Android. At least when using Hindi as the system language. Seems to work on iOS/Desktop though. @CaponeUnity3D 's solution above worked nicely as a workaround on Android.
     
  16. jcbadboy

    jcbadboy

    Joined:
    Mar 24, 2010
    Posts:
    57
    I'm using unity 2019.4.15f1

    Nothing works right on Android

    CultureInfo.CurrentCulture.Name == EMPTY
    CultureInfo.CurrentCulture.DisplayName == Invariant Language (Invariant Country)
    CultureInfo.CurrentCulture.EnglishName == Invariant Language (Invariant Country)
    CultureInfo.CurrentCulture.NativeName == Invariant Language (Invariant Country)

    CultureInfo.InstalledUICulture.Name == EMPTY
    CultureInfo.InstalledUICulture.DisplayName == Invariant Language (Invariant Country)
    CultureInfo.InstalledUICulture.EnglishName == Invariant Language (Invariant Country)
    CultureInfo.InstalledUICulture.NativeName == Invariant Language (Invariant Country)

    System.Threading.Thread.CurrentThread.CurrentCulture == EMPTY
    System.Threading.Thread.CurrentThread.CurrentUICulture == EMPTY


    The only attribute returning a value is from Application:

    Application.systemLanguage = "Portuguese"
     
  17. CortiWins

    CortiWins

    Joined:
    Sep 24, 2018
    Posts:
    150
    A slight warning: CultureInfo.CurrentCulture is used in a lot of stuff as a way to format things. If the static property "CurrentCulture", is somehow forced to invariant, i would not change it, as that may lead to issues you can't even see. This may be a bug, but it could as well be a dirty workaround, so leave it as it is.
     
    jcbadboy likes this.
  18. Noxury

    Noxury

    Joined:
    Mar 8, 2015
    Posts:
    22
    https://csharp.net-tutorials.com/working-with-culture-and-regions/application-culture-and-uiculture/

    However is there any method to convert from Application.systemLanguage to CultureInfo?

    Code (CSharp):
    1. CultureInfo GetCurrentCulture(SystemLanguage sysLang){
    2.     string englishName = sysLang.ToString();
    3.     return new CultureInfo(englishName); //this doesnt work because it expected IETF Language Code
    4. }
    Of course one could precache the language with the associated language code inside an Dictionary but it is annoying to do it for each language.
     
    Last edited: Apr 6, 2021
  19. FSpark

    FSpark

    Joined:
    Mar 4, 2015
    Posts:
    5
  20. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    515
    Doesn't work in my case at all. I use English as device language and stores locations set to Latvia. However, I always get Current Culture: us-US
     
    ilievant likes this.