I would like to determine if the user's locale uses UTF-8 encoding.
This seems a little bit ugly:
[[ $LANG =~ UTF-8$ ]] && echo "Uses UTF-8 encoding.."
is there a more general/portable way?
On POSIX system, you can use locale:
$ if (locale | grep -e 'utf8' -e 'UTF-8') >/dev/null 2>&1; then echo UTF8; fi UTF8
From Wikipedia :
On POSIX platforms, locale identifiers are defined similarly to the BCP 47 definition of language tags, but the locale variant modifier is defined differently, and the character encoding is included as a part of the identifier.
It is defined in this format: [language[_territory][.codeset][@modifier]]. (For example, Australian English using the UTF-8 encoding is en_AU.UTF-8.)
However, if the codeset suffix is missing in the locale identifier, for example as in
en_AG (see this question), then the codeset is defined by a default setting for that locale, which could very well be UTF-8. As a result, the current encoding cannot be determined by looking at the LANG environment variable.
locale command only shows the current values of the environment variables.. so it seems that that command cannot be used to determine the codeset either..
perl -MI18N::Langinfo=langinfo,CODESET -E 'say "Uses UTF-8 encoding .." if langinfo(CODESET()) eq "UTF-8"'
This Perl module is a wrapper for the C library function nl_langinfo.
charmap attribute in the LC_CTYPE locale category that can be used for this:
locale -k LC_CTYPE | grep -qi 'charmap="utf-\+8"' && echo "Uses UTF-8 encoding.."
It is a bit more robust that parse the locale name.
To take care of the cases in which the locale string contains a lowercase
utf8 substring, you can set
nocasematch option and make the dash optional:
shopt -s nocasematch [[ $LANG =~ UTF-?8$ ]] && echo "Uses UTF-8 encoding.."