48

Usually, I run aptitude -y install locales then dpkg-reconfigure locales to set up locale.

Now I want to put it into a shell script, how can I reliably do the following, automatically / non-interactively?

  • Choose en_US.UTF-8 and set it as system default
  • Disable all other locales
  • (Optional) Verify if /etc/default/locale contains one-and-only entry of LANG=en_US.UTF-8 as expected

6 Answers 6

21

See locale-gen:

 locale-gen --purge en_US.UTF-8

and

 echo -e 'LANG="en_US.UTF-8"\nLANGUAGE="en_US:en"\n' > /etc/default/locale
7
  • 1
    Thanks, but I'm getting File "/usr/share/apt-listchanges/ALChacks.py", line 32, in <module> sys.stderr.write(_("Can't set locale; make sure $LC_* and $LANG are correct!\n"))...
    – kenn
    Commented Feb 23, 2012 at 8:02
  • Try LANG=en_US.UTF-8 locale-gen --purge en_US.UTF-8
    – Stone
    Commented Feb 23, 2012 at 9:36
  • This morning, with a clean state of VM, it worked! Thanks!
    – kenn
    Commented Feb 23, 2012 at 19:30
  • 2
    Do this as root.
    – Stone
    Commented Apr 19, 2017 at 5:14
  • 1
    locale-gen doesn’t seem to accept any arguments AFAICT.
    – Rufflewind
    Commented Jun 17, 2017 at 10:32
66

Could not get @stone's answer to work. Instead, I use this method (for Dockerfiles):

# Configure timezone and locale
echo "Europe/Oslo" > /etc/timezone && \
    dpkg-reconfigure -f noninteractive tzdata && \
    sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    sed -i -e 's/# nb_NO.UTF-8 UTF-8/nb_NO.UTF-8 UTF-8/' /etc/locale.gen && \
    echo 'LANG="nb_NO.UTF-8"'>/etc/default/locale && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=nb_NO.UTF-8
5
  • 4
    Dockerfile is exactly what I needed this for. Thanks.
    – peedee
    Commented Feb 15, 2016 at 8:01
  • 14
    Please don't refer to other answers as "above", "below" or similar. Answers move around as people vote for them, accept them, delete them, or just pick different orders. Always use the name of the person who posted the answer, or even better, use the share link under the answer you are commenting on to link to the answer explicitly.
    – rjmunro
    Commented May 12, 2016 at 23:11
  • Slightly neater version of this answer - specifically for Dockerfiles.. EDIT: since newlines don't work here, please refer to my answer serverfault.com/a/801162/89669
    – mafrosis
    Commented Sep 5, 2016 at 15:37
  • I needed to have en_GB.UTF-8 locale set up in CircleCI - this was the best answer that was working. Hoping that because of this comment, Google might show this as relevant when people try to search for the issue I was having.
    – Alex Szabo
    Commented May 29, 2017 at 13:59
  • 1
    echo 'LANG="nb_NO.UTF-8"'>/etc/default/locale is redundant with update-locale LANG=nb_NO.UTF-8 Commented Jun 5, 2019 at 13:37
22

Based on the fine work in @EirikW's answer. Specific to a Dockerfile:

ENV LANG=en_GB.UTF-8
RUN apt-get install -y locales && \
    sed -i -e "s/# $LANG.*/$LANG UTF-8/" /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=$LANG
3
  • 1
    I prefer to set the ENV after otherwise you'll get this error: "perl: warning: Setting locale failed. \ perl: warning: Please check that your locale settings: \ LANG = "en_US.UTF-8" \ are supported and installed on your system. \ perl: warning: Falling back to the standard locale ("C"). Commented Jun 5, 2019 at 13:42
  • This worked for me after I replaced the line with sed by echo "$LANG UTF-8" > /etc/locale.gen Commented Jun 8, 2020 at 20:26
  • The sed line should read `sed -i -e "s/# $LANG.*/$LANG UTF-8/" /etc/locale.gen && \` as ".UTF-8" is already included in $LANG
    – Ictus
    Commented Jul 16, 2020 at 21:23
8

For me it was necessary to set the additional 3 ENV-Vars:

# - Set the locale + timezone --------------------------------------------------
RUN echo "Europe/Vienna" > /etc/timezone && \
    dpkg-reconfigure -f noninteractive tzdata && \
    sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    sed -i -e 's/# de_AT.UTF-8 UTF-8/de_AT.UTF-8 UTF-8/' /etc/locale.gen && \
    echo 'LANG="de_AT.UTF-8"'>/etc/default/locale && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=de_AT.UTF-8

ENV LANG de_AT.UTF-8
ENV LANGUAGE de_AT.UTF-8
ENV LC_ALL de_AT.UTF-8

However Thanks to ErikWs for his answer: (https://serverfault.com/a/689947)

1
  • 1
    This is the only solution that worked for me, I'm on Docker version 17.06.1-ce, build 874a737
    – linuxatico
    Commented Sep 5, 2017 at 16:01
7

To reconfigure the timezone and locales non-interactively, from within a script, here is what works for me (under Debian):

  • For configuring the timezone, I first create '/etc/localtime' as a soft link to the appropriate zoneinfo file under the '/usr/share/zoneinfo' directory. Then, I run the dpkg-reconfigure command, and everything will be put in place. So, for instance, to set up timezone 'Europe/Brussels':

    AREA='Europe'
    ZONE='Brussels'
    
    ZONEINFO_FILE='/usr/share/zoneinfo/'"${AREA}"'/'"${ZONE}"
    ln --force --symbolic "${ZONEINFO_FILE}" '/etc/localtime'
    dpkg-reconfigure --frontend=noninteractive tzdata
    

    (Note that the AREA is a subdirectory under '/usr/share/info', and the ZONE is a file under the AREA subdirectory).

  • For configuring the locales, I first run a sed script that will create a new copy of the '/etc/locale.gen' file, based on the contents of the '/usr/share/i18n/SUPPORTED' file. Every line from the input file will be copied, but it will be turned into a comment unless it is an entry of a UTF-8 locale for a language that I wish to make available on my system (e.g., English, Dutch, French, and German):

    sed --regexp-extended --expression='
    
       1  {
             i\
    # This file lists locales that you wish to have built. You can find a list\
    # of valid supported locales at /usr/share/i18n/SUPPORTED, and you can add\
    # user defined locales to /usr/local/share/i18n/SUPPORTED. If you change\
    # this file, you need to rerun locale-gen.\
    \
    
    
          }
    
       /^(en|nl|fr|de)(_[[:upper:]]+)?(\.UTF-8)?(@[^[:space:]]+)?[[:space:]]+UTF-8$/!   s/^/# /
    
    ' /usr/share/i18n/SUPPORTED >  /etc/locale.gen
    

    Next, I set the default environment locale in the debconf database, e.g., to British English:

    debconf-set-selections <<< 'locales locales/default_environment_locale select en_GB.UTF-8'
    

    I subsequently remove the existing '/etc/default/locale' file (just to make sure that its old contents will not interfere with my new settings), and run the dpkg-reconfigure command to generate all of the locales that the sed script selected, and to create a new '/etc/default/locale' file with just an entry to set the 'LANG' variable to my selected default environment locale:

    rm --force --verbose /etc/default/locale
    dpkg-reconfigure --frontend=noninteractive locales
    

    Then, depending on my requirements, I may want to run a few update-locale commands, to override, e.g., the variables that affect the formatting of values, and set them to a different locale (such as Irish English):

    update-locale LC_NUMERIC='en_IE.UTF-8'
    update-locale LC_TIME='en_IE.UTF-8'
    update-locale LC_MONETARY='en_IE.UTF-8'
    update-locale LC_PAPER='en_IE.UTF-8'
    update-locale LC_NAME='en_IE.UTF-8'
    update-locale LC_ADDRESS='en_IE.UTF-8'
    update-locale LC_TELEPHONE='en_IE.UTF-8'
    update-locale LC_MEASUREMENT='en_IE.UTF-8'
    update-locale LC_IDENTIFICATION='en_IE.UTF-8'
    

    (I could have specified all of these parameters on a single invocation of the update-locale command, but apparently, the order in which the entries get written to the '/etc/default/locale' file is unpredictable if I do so. I prefer them to always be in the same order, which is why I generate them one by one.)

    And finally, I may want to run the update-locale command one last time, to set up the LANGUAGE variable (i.e., the list of languages in which I want translatable text messages to get displayed):

    update-locale LANGUAGE='en_GB:en_US:en'
    

Throw all this together into a bash script, and you can easily reconfigure your locale settings with a simple run of the script, which will not require any further user interaction.

In my experience, however, the new settings will not become entirely activated until after you reboot your system twice (at least on Debian Jessie Xfce). After the first reboot, the login manager will take the new settings alright, but after you login, your user session will continue to use the old settings; then, after the second reboot, your user session will take the new settings as well.

0

You can execute 2 DIRECTLY to set en_US.UTF-8 locales.

  1. Use cat or vim to see the tmp config file:
sudo EDITOR='cat' dpkg-reconfigure -f editor locales
sudo EDITOR='vim' dpkg-reconfigure -f editor locales
  1. Use sed to replace the config file automatically:
sudo EDITOR='sed -Ei "
    s|locales/locales_to_be_generated=.+|locales/locales_to_be_generated=\"en_US.UTF-8 UTF-8\"|; 
    s|locales/default_environment_locale=.+|locales/default_environment_locale=\"en_US.UTF-8\"|
    "' dpkg-reconfigure -f editor locales

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .