Locale (Français)
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.
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