Skip to content

🌟 Introduction

Le sélecteur de langue permet à l’utilisateur de choisir la langue dans laquelle est affichée le contenu du site, si celui-ci est disponible en plusieurs langues.

Il prend la forme d’un bouton déclenchant l’ouverture d’une liste déroulante, présent dans l’en-tête dans le groupe des accès rapides.

Important

Ce composant est utilisé en interne dans DsfrHeader (avec la prop languageSelector) et ne devrait pas être utilisé directement.

🏅 La documentation sur le sélecteur de langue sur le DSFR

La story sur le sélecteur de langue sur le storybook de VueDsfr

📐 Structure

  • <DsfrLanguageSelector> : Le composant principal.
    • Contient un bouton qui ouvre ou ferme un menu déroulant de langues.
    • Affiche une liste des langues disponibles, permettant à l'utilisateur de sélectionner la langue désirée.

🛠️ Props

PropriétéTypeDescriptionValeur par défaut
idstringIdentifiant unique pour les éléments de contrôle d'accessibilité.getRandomId('translate')
languagesDsfrLanguageSelectorElement[]Liste des langues disponibles. Chaque langue est représentée par un objet contenant un codeIso et un label.[]
currentLanguagestringCode ISO de la langue actuellement sélectionnée.'fr'

📡 Événements

  • select : Événement émis lorsqu'une langue est sélectionnée. Passe l'objet DsfrLanguageSelectorElement de la langue sélectionnée en tant que payload.

🧩 Slots

  • default : Ce slot permet d'insérer du contenu personnalisé dans le bouton qui affiche la langue sélectionnée.

📝 Exemples

vue
<script lang="ts" setup>
import { ref } from 'vue'

import DsfrLanguageSelector, { type DsfrLanguageSelectorElement } from '../DsfrLanguageSelector.vue'

const languages = [
  { label: 'Français', codeIso: 'fr' },
  { label: 'English', codeIso: 'en' },
  { label: 'Deutsch', codeIso: 'de' },
]
const currentLanguage = ref('fr')

const selectLanguage = (language: DsfrLanguageSelectorElement) => {
  currentLanguage.value = language.codeIso
}
</script>

<template>
  <div class="fr-container fr-my-2v">
    <DsfrLanguageSelector
      id="language-selector"
      :languages
      :current-language
      @select="selectLanguage($event)"
    />
  </div>
</template>

⚙️ Code source du composant

vue
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'

import { useCollapsable } from '../../composables'
import { getRandomId } from '../../utils/random-utils'

import type { DsfrLanguageSelectorElement, DsfrLanguageSelectorProps } from './DsfrLanguageSelector.types'

export type { DsfrLanguageSelectorElement, DsfrLanguageSelectorProps }

const props = withDefaults(defineProps<DsfrLanguageSelectorProps>(), {
  id: () => getRandomId('translate'),
  languages: () => [],
  currentLanguage: 'fr',
})

const emit = defineEmits<{ (e: 'select', payload: DsfrLanguageSelectorElement): void }>()

const {
  collapse,
  collapsing,
  cssExpanded,
  doExpand,
  onTransitionEnd,
} = useCollapsable()

const expanded = ref(false)

function selectLanguage (language: DsfrLanguageSelectorElement) {
  expanded.value = false
  emit('select', language)
}

const currentLanguageObject = computed(
  () => props.languages.find(({ codeIso }) => codeIso === props.currentLanguage),
)

watch(expanded, (newValue, oldValue) => {
  if (newValue !== oldValue) {
    doExpand(newValue)
  }
})
</script>

<template>
  <nav
    role="navigation"
    class="fr-translate  fr-nav"
  >
    <div class="fr-nav__item">
      <button
        class="fr-translate__btn fr-btn fr-btn--tertiary"
        :aria-controls="id"
        :aria-expanded="expanded"
        title="Sélectionner une langue"
        type="button"
        @click.prevent.stop="expanded = !expanded"
      >
        {{ currentLanguageObject?.codeIso.toUpperCase() }}<span class="fr-hidden-lg">&nbsp;- {{ currentLanguageObject?.label }}</span>
      </button>
      <div
        :id="id"
        ref="collapse"
        class="fr-collapse fr-translate__menu fr-menu"
        :class="{ 'fr-collapse--expanded': cssExpanded, 'fr-collapsing': collapsing }"
        @transitionend="onTransitionEnd(expanded)"
      >
        <ul class="fr-menu__list">
          <li
            v-for="language, idx in languages"
            :key="idx"
          >
            <a
              class="fr-translate__language  fr-nav__link"
              :hreflang="language.codeIso"
              :lang="language.codeIso"
              :aria-current="currentLanguage === language.codeIso ? true : undefined"
              :href="`#${language.codeIso}`"
              @click.prevent.stop="selectLanguage(language)"
            >{{ `${language.codeIso.toUpperCase()} - ${language.label}` }}</a>
          </li>
        </ul>
      </div>
    </div>
  </nav>
</template>
ts
export type DsfrLanguageSelectorElement = {
  codeIso: string
  label: string
}

export type DsfrLanguageSelectorProps = {
  id?: string
  languages: DsfrLanguageSelectorElement[]
  currentLanguage?: string
}