Golang get system language

On unix-like systems (Mac OS, Linux) you can use the os package to get environment variables with LookupEnv. So for example you could get the system language/encoding with:

s, ok := os.LookupEnv("LANG")
println(s, err)
=> en_US.UTF-8 true

There's also a blog article which may be of interest to you on the golang.org blog (more about choosing languages once you know the system language setting):

https://blog.golang.org/matchlang

On windows you might be able to use this package to get the language from the registry if the above doesn't work (I'd try os.LookupEnv first).

https://godoc.org/golang.org/x/sys/windows/registry


There is a nice cross-platform library called jibber_jabber which looks up for $LC_ALL or $LANG env variables in Unix systems and, for Windows, loads Kernel32 and calls some procedures like GetUserDefaultLocaleName or GetSystemDefaultLocaleName inside. For Windows, all is done in the getWindowsLocale() function. Be advised that Kernel32 library comes built-in in Windows OS kernel.

By the way, should you need to convert locale-format'd language strings like en_US and fr_FR, you can utilize the x/text/language and x/text/language/display packages to get fully qualified name of the language.

lang := "ru_RU"
tag := language.MustParse(lang)

inEng := display.English.Languages()
inTur := display.Turkish.Languages()
inSelf := display.Self

fmt.Println(inEng.Name(tag))
fmt.Println(inSelf.Name(tag))
fmt.Println(inTur.Name(tag))

   // Output:
   // Russian
   // русский
   // Rusça

One approach would be to try the following strategies in sequence:

  1. See if the LANG environment variable is set and use that value (common on UNIX systems).
  2. Execute powershell on Windows and extract the Get-Culture "Name" property.

For example:

func main() {
  locale, err := GetLocale()
  fmt.Printf("OK: locale=%q, err=%v\n", locale, err)
  // OK: locale="en-US", err=nil
}

func GetLocale() (string, error) {
  // Check the LANG environment variable, common on UNIX.
  // XXX: we can easily override as a nice feature/bug.
  envlang, ok := os.LookupEnv("LANG")
  if ok {
    return strings.Split(envlang, ".")[0], nil
  }

  // Exec powershell Get-Culture on Windows.
  cmd := exec.Command("powershell", "Get-Culture | select -exp Name")
  output, err := cmd.Output()
  if err == nil {
    return strings.Trim(string(output), "\r\n"), nil
  }

  return "", fmt.Errorf("cannot determine locale")
}

Doing these actions in this sequence is convenient because it lets you easily change the locale (e.g. for testing) and should work on both UNIX and Windows operating systems.