41

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
kenn
  • 625
  • 1
  • 5
  • 10

5 Answers5

60

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
EirikW
  • 601
  • 1
  • 5
  • 2
  • 3
    Dockerfile is exactly what I needed this for. Thanks. – peedee Feb 15 '16 at 08:01
  • 12
    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 May 12 '16 at 23:11
  • Slightly neater version of this answer - specifically for Dockerfiles.. EDIT: since newlines don't work here, please refer to my answer http://serverfault.com/a/801162/89669 – mafrosis Sep 05 '16 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 May 29 '17 at 13:59
  • echo 'LANG="nb_NO.UTF-8"'>/etc/default/locale is redundant with update-locale LANG=nb_NO.UTF-8 – Olivier Tonglet Jun 05 '19 at 13:37
18

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
ESV
  • 155
  • 5
mafrosis
  • 361
  • 4
  • 8
  • 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"). – Olivier Tonglet Jun 05 '19 at 13:42
  • This worked for me after I replaced the line with `sed` by `echo "$LANG UTF-8" > /etc/locale.gen` – That Brazilian Guy Jun 08 '20 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 Jul 16 '20 at 21:23
17

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
Stone
  • 6,941
  • 1
  • 19
  • 33
  • 1
    Thanks, but I'm getting `File "/usr/share/apt-listchanges/ALChacks.py", line 32, in sys.stderr.write(_("Can't set locale; make sure $LC_* and $LANG are correct!\n"))`... – kenn Feb 23 '12 at 08:02
  • Try LANG=en_US.UTF-8 locale-gen --purge en_US.UTF-8 – Stone Feb 23 '12 at 09:36
  • This morning, with a clean state of VM, it worked! Thanks! – kenn Feb 23 '12 at 19:30
  • Hmm… when you run `locale-gen --purge en_GB.UTF-8` on a clean installation, you get this unexpected output: `Generating locales (this might take a while)... en_US.UTF-8... done Generation complete.` Any ideas how to set the list of locales as you do in dpkg-reconfigure locales non-interactively? – Benjamin Nolan Aug 01 '14 at 16:14
  • This both give permission denied errors.... – Cerin Apr 18 '17 at 23:01
  • 2
    Do this as root. – Stone Apr 19 '17 at 05:14
  • `locale-gen` doesn’t seem to accept any arguments AFAICT. – Rufflewind Jun 17 '17 at 10:32
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)

Mike Mitterer
  • 181
  • 1
  • 2
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.

luvr
  • 71
  • 1
  • 2