Aller au contenu

Créer une recherche de lieux bilingue

Une lectrice à Montréal tape Montréal. Un lecteur à Toronto tape Montreal. Les deux parlent de la même ville, et votre page doit afficher un seul résultat, nommé dans la langue du lecteur. Dans unmap, c'est un seul enregistrement qui porte les deux noms : vous choisissez la langue au moment de l'affichage plutôt que de chercher dans un autre jeu de données.

résultat en direct
le code qui l'a produit
import { Unmap } from "@unmap/sdk";

const unmap = new Unmap({ key: "um_live_..." });

const results = await unmap.geocoder.search("Montreal", { limit: 3, lang: "fr" });

Le code est du TypeScript ordinaire. Pour le câblage React, Next.js, Vue ou Nuxt, partez des recettes par cadriciel.

Un enregistrement, deux noms

lang décide quel nom revient dans name. names porte tous les libellés de l'enregistrement : l'autre langue est donc déjà dans la réponse.

const [place] = await unmap.geocoder.search("Montreal", { limit: 1, lang: "fr" });
 
console.log(place?.name); // "Montréal"
console.log(place?.names?.en, place?.names?.fr); // "Montreal" "Montréal"

La langue de la requête n'a pas à correspondre à lang. Quebec City avec lang: "fr" revient sous la forme Québec, et Montreal comme Montréal trouvent la même localité, parce que les accents sont repliés de la même façon des deux côtés : Trois-Rivieres trouve Trois-Rivières.

name est résolu dans un ordre fixe : l'entrée de names pour votre lang, puis le nom français de l'enregistrement si vous avez demandé fr, puis son nom par défaut, puis names.en. Un enregistrement sans libellé français revient donc en anglais, quoi que vous demandiez. Ce n'est pas une erreur à traiter : c'est le seul nom que l'enregistrement possède.

Envoyez fr, pas fr-CA

Le navigateur annonce fr-CA. La carte lit cette étiquette par sa sous-étiquette principale et affiche les libellés en français. Le géocodeur cherche lang tel quel dans names, n'y trouve pas de clé fr-CA et se rabat sur le nom par défaut. Normalisez la langue une fois et envoyez la même valeur aux deux, comme le fait siteLang ci-dessous.

Étiquetez la carte dans la même langue

La carte prend le même lang. Passez la valeur normalisée à sa création, et les libellés, les résultats de recherche et votre propre interface concordent.

function siteLang(): "en" | "fr" {
  return navigator.language.toLowerCase().startsWith("fr") ? "fr" : "en";
}
 
const lang = siteLang();
 
const unmap = new Unmap({ key, container: "map", center: [-73.5673, 45.5017], zoom: 12, lang });
const results = await unmap.geocoder.search("vieux-port", { limit: 5, lang });

La langue fait partie de l'URL du style : la changer plus tard veut dire charger un nouveau style. unmapStyle construit cette URL à partir de ce que vous lui passez seulement : passez donc le style, le mode et le thème de la carte, sinon ils reviennent aux valeurs par défaut, base, light et aucun thème. setStyle remplace toutes les couches, y compris celles que vous avez ajoutées vous-même, alors ajoutez de nouveau les vôtres une fois le nouveau style chargé.

import { unmapStyle } from "@unmap/sdk";
 
// Le style, le mode et le thème de la carte (le thème seulement si vous en avez un).
const look = { style: "base", mode: "light" };
 
function switchMapLanguage(next: "en" | "fr") {
  unmap.map?.setStyle(unmapStyle({ key, ...look, lang: next }));
}

Affichez aussi l'autre nom

Une interface bilingue montre souvent les deux : Montréal (Montreal). Lisez l'autre langue dans names, et omettez-la quand c'est la même chaîne, ce qui est le cas des lieux qui ont un seul nom officiel dans les deux langues, comme Trois-Rivières ou Iqaluit.

import type { GeocodeResult } from "@unmap/sdk";
 
function otherName(place: GeocodeResult, lang: "en" | "fr"): string | undefined {
  const other = place.names?.[lang === "fr" ? "en" : "fr"];
  return other && other !== place.name ? other : undefined;
}

names contient aussi des graphies de rechange que les gens cherchent, sous des clés comme en-alt1 et fr-alt1. C'est grâce à elles que Old Montreal trouve le Vieux-Montréal, et elles ne servent jamais de libellé. Si vous parcourez names pour construire un sélecteur de langue, sautez les clés qui finissent par -alt ou -iata, avec ou sans chiffre final.

Cherchez des catégories dans l'une ou l'autre langue

La recherche à proximité accepte des mots courants en français ou en anglais et les résout dans l'API : une interface française peut envoyer ce que le lecteur a tapé.

const shops = await unmap.geocoder.nearby(["pharmacie", "depanneur"], {
  near: [-73.5673, 45.5017],
  limit: 5,
  lang: "fr",
});

Là où cette approche se trompe

  • Québec désigne deux lieux. Avec lang: "en", le premier résultat est la province. Ajoutez layers: "locality" quand vous voulez la ville.
  • Un type de voie français sur un enregistrement anglais correspond quand même, mais en partie. rue Slater Ottawa trouve Slater Street, marqué partial avec terms_unmatched, parce que l'enregistrement dit Slater St et que rue n'a rien trouvé. Affichez le résultat : partial n'est pas un échec.
  • La plupart des enregistrements d'adresse n'ont pas de nom propre. Leur libellé est composé de la rue et de la ville telles que la source les a écrites : il n'y a pas de seconde langue à afficher.

Voir aussi