# Locale (Français)

From ArchWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Related articles

- Environment variables
- Localization

glibc, comme la plupart des programmes ou API gérant l'affichage de textes ou de messages en français s'appuie, pour l'affichage des lettres accentuées, des dates, des montants ou de la ponctuation, sur des fichiers de paramètres régionaux (en anglais : Locales). Cette page dédiée à la configuration d'une ou plusieurs locales.

## Introduction

Sous Linux, les locales sont utilisées pour définir la langue que vous désirez utiliser sur votre système, et bénéficier ainsi des possibilités d'édition (lettres accentuées, ponctuation, etc.) correspondantes.

Le nom des locales est construit comme suit:

    langage[_pays][.encodage][@modification]

## Activer les locales

Les locales doivent être générées à l'aide de la commande `locale-gen`. Cette dernière récupère les locales à générer depuis le fichier `/etc/locale.gen`.

Pour configurer un système UTF-8 en français, nous allons activer `fr_FR.UTF-8`.

Décommentons les locales suivantes du fichier :

    /etc/locale.gen

    fr_FR.UTF-8 UTF-8

Puis générons les locales :

    # locale-gen

    Generating locales...
      fr_FR.UTF-8... done
    Generation complete.

Note: Bien que vous n'utilisiez souvent qu'une langue sur votre ordinateur, il peut être pratique ou même nécessaire d'activer d'autres locales. Par exemple, pour des utilisateurs ne parlant pas la même langue.

Vous pouvez avoir la liste des locales de votre système avec la commande :

    locale -a

Et celle que vous utilisez avec :

    locale

## Configurer la locale pour tout le système

La configuration se fait dans le fichier `/etc/locale.conf`.

Vous pouvez spécifier une ou plusieurs catégories de locale (`man 7 locale` pour avoir la liste) :

    /etc/locale.conf

    # Spécifier fr par défaut
    LANG="fr_FR.UTF-8"
    # Préférer l'anglais à la langue par défaut si la traduction fr n'existe pas
    LANGUAGE="fr_FR:en_US"
    # Mais garder un tri par défaut
    LC_COLLATE=C

Il est aussi possible de définir la locale en passant un paramètre au noyau (pour un live par exemple) :

    locale.LANG=fr_FR.UTF-8 locale.LC_COLLATE=C

## Configurer la locale par utilisateur

Pour configurer une locale (qui peut être différente de celle du système) seulement pour votre session, il faut exporter la bonne variable dans votre `~/.bashrc`, par exemple, pour avoir le système en anglais, mais les dates en français :

    export LANG=en_US.UTF-8
    export LC_TIME=fr_FR

Votre locale sera mis à jour aussitôt que votre `~/.bashrc` sera re-sourcé soit, en vous connectant ou si vous lancez la commande :

    source ~/.bashrc

## Ordre de tri

L'ordre de tri d'une liste (de fichier/répertoire par exemple) peut aussi être influencé par les locales.

    $ touch E e é f
    $ LC_COLLATE=fr_FR.iso8859-1 ls
    é  e  E  f
    $ LC_COLLATE=fr_FR.utf8 ls
    e  E  é  f
    $ LC_COLLATE=C ls
    E  e  f  é

Si vous voulez avoir un comportement unique quel que soit l'environnement, assurez vous de définir `LC_COLLATE` (ou `LC_ALL` à `C`).

## Vérification

Il est possible de vérifier la configuration des locales à l'aide du script suivant, qu'il est possible de télécharger directement :

    $ curl -o locale-check.sh http://ix.io/ksS # POTENTIELLEMENT NON SÛR, VÉRIFIEZ LE CONTENU
    $ bash ./locale-check.sh

    locale-check.sh

    #!/usr/bin/env bash

    warn() { printf "\e[31mwarning:\e[m %s\n" "$*"; ((++n_warnings)); } >&2

    note() { printf "\e[33mnotice:\e[m %s\n" "$*"; ((++n_notices)); }

    problem() { (( ++sy_total )); printf "\n\e[33mproblem:\e[m %s\n" "$*"; }

    is_locale_supported() {
            locale -a 2>/dev/null | grep -qsxF "$(get_locale "$1")"
    }

    get_locale() {
            local locale=$1
            if [[ $locale == *.* ]]; then
                    locale=${locale%%.*}.$(get_charset "$locale")
            fi
            echo "$locale"
    }

    get_charset() {
            local locale=$1 charset=''
            if [[ $locale == *.* ]]; then
                    charset=${locale#*.}
                    charset=${charset//-/}
                    charset=${charset,,}
            else
                    charset='default'
            fi
            echo "$charset"
    }

    check_setting() {
            local name=$1 value=$2

            [[ -z $value ]] && return

            if ! is_locale_supported "$value"; then
                    warn "$name: unsupported locale \"$value\""
                    (( ++sy_missing ))
                    local xlocale=$(get_locale "$value")
                    sy_missing_locs["$xlocale"]=y
            fi

            local charset=$(get_charset "$value")
            if [[ $charset != "utf8" ]]; then
                    warn "$name: non-UTF8 locale \"$value\""
                    sy_nonutf8_vars["$name"]=y
                    (( ++sy_nonutf8 ))
            fi

            if [[ "$charset" != "$main_charset" ]]; then
                    if [[ "${name##* }" == "LANG" ]]; then
                            return
                    fi
                    warn "$name: charset does not match LANG ($charset | $main_charset)"
                    (( ++sy_charmismatch ))
            fi
    }

    shopt -s extglob

    checking_term=0
    checking_parent=0
    guessing_parent=""

    declare -i pid_shell=$PPID
    declare -i pid_term=$(ps -o 'ppid=' $pid_shell)
    declare -i pid_parent=$(ps -o 'ppid=' $pid_term)

    if (( pid_term > 1 )) && [[ -r "/proc/$pid_term/environ" ]]; then
            checking_term=1
            if (( pid_parent > 1 )); then
                    if [[ -r "/proc/$pid_parent/environ" ]]; then
                            checking_parent=1
                    fi
            elif [[ $SESSION_MANAGER == */tmp/.ICE-unix/+([0-9]) ]]; then
                    guessing_parent="from \$SESSION_MANAGER"
                    pid_parent=${SESSION_MANAGER##*/tmp/.ICE-unix/}
                    if [[ -r "/proc/$pid_parent/environ" ]]; then
                            checking_parent=1
                    fi
            fi
    fi

    ps_shell=$(ps -o 'pid=,command=' $pid_shell)
    ps_terminal=$(ps -o 'pid=,command=' $pid_term)
    ps_parent=$(ps -o 'pid=,command=' $pid_parent)

    echo " * Parent:   $ps_parent"
    echo " * Terminal: $ps_terminal"
    echo " * Shell:    $ps_shell"
    echo ""

    unset ${!sy_*}
    declare -A sy_missing_locs
    declare -A sy_nonutf8_vars

    # Read terminal's environment

    vars=("LC_CTYPE" "LC_NUMERIC" "LC_TIME" "LC_COLLATE" "LC_MONETARY" "LC_MESSAGES"
            "LC_PAPER" "LC_NAME" "LC_ADDRESS" "LC_TELEPHONE" "LC_MEASUREMENT"
            "LC_IDENTIFICATION" "LC_ALL")

    if (( checking_term )); then
            unset ${!TERM_*}
            while IFS='=' read -d '' name value; do
                    if [[ $name == LANG || $name == LC_* ]]; then
                            declare "TERM_$name"="$value"
                    fi
            done < "/proc/$pid_term/environ"
    elif [[ $ps_terminal == *' sshd:'* ]]; then
            warn "I cannot check your terminal's settings over SSH, skipping."
    else
            warn "Terminal's environment is inaccessible, skipping shell=term checks."
    fi

    if (( checking_parent )); then
            if [[ $guessing_parent ]]; then
                    note "Tried to guess parent process $guessing_parent."
            fi
            unset ${!PARN_*}
            while IFS='=' read -d '' name value; do
                    if [[ $name == LANG || $name == LC_* ]]; then
                            declare "PARN_$name"="$value"
                    fi
            done < "/proc/$pid_parent/environ"
    elif (( checking_term )); then
            warn "Parent's environment is inaccessible, skipping term=parent checks."
    else
            note "Also skipping term=parent checks."
    fi

    # Basic checks

    if [[ -z $LANG ]]; then
            warn "(shell) LANG: not set"
            main_charset='default'
            (( ++sy_nolang ))
    else
            main_charset=$(get_charset "$LANG")
    fi

    if (( checking_term )); then
            if [[ -z $TERM_LANG ]]; then
                    warn "(term) LANG: not set"
                    t_main_charset='default'
                    (( ++sy_nolang ))
            else
                    t_main_charset=$(get_charset "$TERM_LANG")
            fi
    fi

    if (( checking_parent )); then
            if [[ -z $PARN_LANG ]]; then
                    warn "(parent) LANG: not set"
                    p_main_charset='default'
                    (( ++sy_nolang ))
            else
                    p_main_charset=$(get_charset "$PARN_LANG")
            fi
    fi

    for name in LANG "${vars[@]}"; do
            if [[ "$name" == "LC_COLLATE" ]]; then
                    # skip LC_COLLATE on purpose, having it as 'C' is fine
                    continue
            fi

            value=${!name}
            locale=$(get_locale "$value")
            charset=$(get_charset "$value")
            (( checking_term )) && {
                    t_name="TERM_$name"
                    t_value=${!t_name}
                    t_locale=$(get_locale "$t_value")
                    t_charset=$(get_charset "$t_value")
            }
            (( checking_parent )) && {
                    p_name="PARN_$name"
                    p_value=${!p_name}
                    p_locale=$(get_locale "$p_value")
                    p_charset=$(get_charset "$p_value")
            }

            check_setting "(shell) $name" "$value"
            (( checking_term )) &&
                    check_setting "(term) $name" "$t_value"
            (( checking_parent )) &&
                    check_setting "(parent) $name" "$p_value"

            if [[ "$name" == "LC_ALL" && -n "$value" ]]; then
                    warn "$name: should not be set ($value)"
                    (( ++sy_lcall ))
            fi

            (( checking_term )) && {
                    if [[ -n "$value" && -z "$t_value" ]]; then
                            warn "$name: set by shell but not terminal ($value | none)"
                            (( ++sy_mismatch ))
                    elif [[ -z "$value" && -n "$t_value" ]]; then
                            warn "$name: set by terminal but not shell (none | $t_value)"
                            (( ++sy_mismatch ))
                    elif [[ "$charset" != "$t_charset" ]]; then
                            warn "$name: charset mismatch between shell and terminal ($locale | $t_locale)"
                            (( ++sy_mismatch ))
                    elif [[ "$locale" != "$t_locale" ]]; then
                            warn "$name: lang mismatch between shell and terminal ($locale | $t_locale)"
                            (( ++sy_mismatch ))
                    fi
            }

            (( checking_parent )) && {
                    if [[ -n "$t_value" && -z "$p_value" ]]; then
                            warn "$name: set by terminal but not parent ($t_value | none)"
                            (( ++sy_p_mismatch ))
                    elif [[ -z "$t_value" && -n "$p_value" ]]; then
                            warn "$name: set by parent but not terminal (none | $p_value)"
                            (( ++sy_p_mismatch ))
                    elif [[ "$t_charset" != "$p_charset" ]]; then
                            warn "$name: charset mismatch between terminal and parent ($t_locale | $p_locale)"
                            (( ++sy_p_mismatch ))
                    elif [[ "$t_locale" != "$p_locale" ]]; then
                            warn "$name: lang mismatch between terminal and parent ($t_locale | $p_locale)"
                            (( ++sy_p_mismatch ))
                    fi
            }
    done

    if [[ ${LANG,,} == *'.utf8' ]]; then
            (( ++sy_utf8_dash ))
    fi

    # Display final results

    if (( sy_nolang )) && [[ $LANG && -z $TERM_LANG ]]; then
            problem "Your terminal is missing \$LANG in its environment."
            echo " * Locale variables must be set for the terminal emulator itself"
            echo "   (and for the entire session), not only for the shell."
    elif (( sy_nolang )) && [[ -z $LANG && $TERM_LANG ]]; then
            problem "Your shell is missing \$LANG in its environment."
            echo " * Even though your terminal has the correct \$LANG ($TERM_LANG),"
            echo "   it was removed by your shell's .profile, .bashrc or similar files."
    elif (( sy_nolang )); then
            problem "You do not have \$LANG set."
            echo " * It must be set to a <lang>.utf-8 locale."
    fi

    if (( sy_mismatch )); then
            problem "Shell and terminal have different locale settings."
            echo " * Your .bashrc or similar startup scripts may be overriding them."
    fi

    if (( sy_p_mismatch )); then
            : ${parn_locale:=$PARN_LC_ALL}; : ${parn_locale:=$PARN_LC_CTYPE}
            : ${parn_locale:=$PARN_LANG};   : ${parn_locale:=empty}
            : ${term_locale:=$TERM_LC_ALL}; : ${term_locale:=$TERM_LC_CTYPE}
            : ${term_locale:=$TERM_LANG};   : ${term_locale:=empty}
            problem "Terminal and its parent have different locale settings."
            echo " * Your session doesn't have the right locale set, and your window manager"
            echo "   is launching all programs using the $parn_locale locale. But your terminal"
            echo "   hides the problem by setting its own locale to $term_locale."
            echo " * Fix your system to set the locale at login or session startup time."
    fi

    if (( sy_lcall )); then
            problem "You have \$LC_ALL set; it overrides all other settings."
            echo " * Do not set \$LC_ALL unless absolutely required."
            echo "   For normal usage, setting \$LANG should be enough."
    fi

    if (( sy_nonutf8 )); then
            problem "Your current locale is using a legacy charset."
            echo " * The incorrect variables are:"
            for var in "${!sy_nonutf8_vars[@]}"; do
                    varname=${var#* }
                    printf '   - %-20s (currently "%s")\n' "$var" "${!varname}"
            done
            echo " * Change your locales to their UTF-8 variants."
    fi

    if (( sy_charmismatch )) && [[ $LANG ]]; then
            problem "Your locale settings use different charsets."
            echo " * If any \$LC_* variables are set, they should use the same charset as \$LANG."
    fi

    if (( sy_missing )); then
            problem "Your current locale is missing from the system."
            echo " * The missing locales are:"
            printf '   - \e[1m%s\e[m\n' "${!sy_missing_locs[@]}"
            echo " * Make sure /etc/locale.gen has the apropriate lines uncommented."
            echo "   After editing the file, run 'locale-gen' as root."
    fi

    if (( sy_utf8_dash )); then
            problem "\$LANG is missing a dash in the charset."
            echo " * Even though 'utf-8' and 'utf8' are equivalent, some poorly-written programs"
            echo "   (such as 'tree') consider them different and will not work with the latter."
            echo " * To fix this, change \$LANG from \"$LANG\" to \"${LANG%.*}.utf-8\""
    fi

    if (( n_warnings + n_notices )); then
            echo ""
    fi

    if (( sy_total > 0 )); then
            echo -e "\e[1m$sy_total problems found.\e[m Here's a quick UTF-8 test for you:  --> \xe2\x98\x85 <--"
    elif (( !checking_term )); then
            echo -e "Looks good, but you still need to check your terminal:  --> \xe2\x98\x85 <--"
    else
            printf "Looks good. \xe2\x99\xa5\n"
            echo " * You are using the $LANG locale."
            echo " * Shell's locale matches terminal's locale."
            if (( checking_parent )); then
                    echo " * Terminal's locale matches parent process locale."
            else
                    echo " * Could not check if terminal and parent's locale settings match."
            fi
    fi

    if (( sy_total > 0 || !checking_term )); then
            echo " * a star             -- font and terminal are okay."
            echo " * 3 question marks   -- your terminal does not correctly interpret UTF-8".
            echo " * a box or rectangle -- UTF-8 works fine, but you need a better font."
            echo " * empty area         -- you ${B}really${R} need a better font or something."
    fi

Category:

- Localization (Français)