From 4b894363afd062a82dcbfa54edb61180da45806c Mon Sep 17 00:00:00 2001 From: MartinBraquet Date: Thu, 19 Feb 2026 12:19:35 +0100 Subject: [PATCH] Translate saved searches --- .../choices.tsx => common/src/choices.ts | 11 - common/src/searches.ts | 197 ++++++++++++++++-- web/components/filters/diet-filter.tsx | 2 +- web/components/filters/education-filter.tsx | 2 +- web/components/filters/gender-filter.tsx | 2 +- web/components/filters/language-filter.tsx | 2 +- web/components/filters/mbti-filter.tsx | 2 +- web/components/filters/political-filter.tsx | 2 +- web/components/filters/pref-gender-filter.tsx | 2 +- .../filters/relationship-filter.tsx | 2 +- .../filters/relationship-status-filter.tsx | 2 +- web/components/filters/religion-filter.tsx | 2 +- web/components/filters/romantic-filter.tsx | 2 +- web/components/optional-profile-form.tsx | 2 +- web/components/profile-about.tsx | 17 +- web/components/searches/button.tsx | 47 +++-- web/lib/profile/seeking.ts | 2 +- web/lib/util/convert-types.ts | 2 +- web/messages/de.json | 17 +- web/messages/fr.json | 17 +- 20 files changed, 268 insertions(+), 66 deletions(-) rename web/components/filters/choices.tsx => common/src/choices.ts (94%) diff --git a/web/components/filters/choices.tsx b/common/src/choices.ts similarity index 94% rename from web/components/filters/choices.tsx rename to common/src/choices.ts index f89ff292..2d4941aa 100644 --- a/web/components/filters/choices.tsx +++ b/common/src/choices.ts @@ -1,7 +1,4 @@ import {invert} from "lodash"; -import {FaHeart, FaUsers} from "react-icons/fa"; -import {FiUser} from "react-icons/fi"; -import {GiRing} from "react-icons/gi"; export const RELATIONSHIP_CHOICES = { // Other: 'other', @@ -18,14 +15,6 @@ export const RELATIONSHIP_STATUS_CHOICES = { 'In open relationship': 'open', }; -export const RELATIONSHIP_ICONS = { - single: FiUser, - married: GiRing, - casual: FaHeart, - long_term: FaHeart, - open: FaUsers, -} as const; - export const ROMANTIC_CHOICES = { Monogamous: 'mono', Polyamorous: 'poly', diff --git a/common/src/searches.ts b/common/src/searches.ts index ae59b2ab..6332e27a 100644 --- a/common/src/searches.ts +++ b/common/src/searches.ts @@ -2,28 +2,40 @@ import {FilterFields, initialFilters} from 'common/filters' import {wantsKidsNames} from 'common/wants-kids' import {hasKidsNames} from 'common/has-kids' -import {milesToKm} from "common/measurement-utils"; +import {milesToKm} from 'common/measurement-utils' +import { + INVERTED_DIET_CHOICES, + INVERTED_EDUCATION_CHOICES, + INVERTED_GENDERS, + INVERTED_LANGUAGE_CHOICES, + INVERTED_MBTI_CHOICES, + INVERTED_POLITICAL_CHOICES, + INVERTED_RELATIONSHIP_CHOICES, + INVERTED_RELATIONSHIP_STATUS_CHOICES, + INVERTED_RELIGION_CHOICES, + INVERTED_ROMANTIC_CHOICES, +} from 'common/choices' +import {capitalize} from 'lodash' const filterLabels: Record = { geodbCityIds: '', location: '', name: 'Searching', genders: '', + pref_gender: 'Gender they seek', education_levels: 'Education', pref_age_max: 'Max age', pref_age_min: 'Min age', - drinks_max: 'Max drinks', - drinks_min: 'Min drinks', relationship_status: '', has_kids: '', - wants_kids_strength: 'Kids', + wants_kids_strength: '', is_smoker: '', pref_relation_styles: 'Seeking', + pref_romantic_styles: '', interests: '', causes: '', work: '', religion: '', - pref_gender: '', orderBy: '', diet: 'Diet', political_beliefs: 'Political views', @@ -48,29 +60,49 @@ const skippedKeys = [ 'lat', 'lon', 'radius', + // Big Five min/max keys are handled separately + 'big5_openness_min', + 'big5_openness_max', + 'big5_conscientiousness_min', + 'big5_conscientiousness_max', + 'big5_extraversion_min', + 'big5_extraversion_max', + 'big5_agreeableness_min', + 'big5_agreeableness_max', + 'big5_neuroticism_min', + 'big5_neuroticism_max', + // Drinks min/max keys are handled separately + 'drinks_min', + 'drinks_max', ] export function formatFilters( filters: Partial, location: locationType | null, choicesIdsToLabels: Record, - measurementSystem?: 'metric' | 'imperial' + measurementSystem?: 'metric' | 'imperial', + t?: (key: string, fallback: string) => string ): String[] | null { const entries: String[] = [] + // Helper function to translate UI text + const translate = (key: string, fallback: string): string => { + return t ? t(key, fallback) : fallback + } + let ageEntry = null let ageMin: number | undefined | null = filters.pref_age_min if (ageMin == 18) ageMin = undefined let ageMax = filters.pref_age_max if (ageMax == 100) ageMax = undefined if (ageMin || ageMax) { - let text: string = 'Age: ' + let text: string = translate('filter.age.label', 'Age') + ': ' if (ageMin) text = `${text}${ageMin}` if (ageMax) { if (ageMin) { text = `${text}-${ageMax}` } else { - text = `${text}up to ${ageMax}` + text = `${text}${translate('filter.age.up_to', 'up to')} ${ageMax}` } } else { text = `${text}+` @@ -88,13 +120,81 @@ export function formatFilters( const label = filterLabels[typedKey] ?? key + // Translate the label if it exists and we have a translation function + let translatedLabel = label + if (label && t) { + const labelKey = `filter.label.${typedKey}` + translatedLabel = t(labelKey, label) + } + + console.log(key, value) let stringValue = value - if (key === 'has_kids') stringValue = hasKidsNames[value as number] - if (key === 'wants_kids_strength') - stringValue = wantsKidsNames[value as number] + if (key === 'has_kids') + stringValue = translate( + `profile.has_kids.${value}`, + hasKidsNames[value as number] + ) + else if (key === 'wants_kids_strength') + stringValue = translate( + `profile.wants_kids_${value}`, + wantsKidsNames[value as number] + ) + else if (key === 'is_smoker') + stringValue = translate( + `profile.smoker.${value ? 'yes' : 'no'}`, + value ? 'Smoker' : 'Non-smoker' + ) if (Array.isArray(value)) { if (choicesIdsToLabels[key]) { value = value.map((id) => choicesIdsToLabels[key][id]) + } else if (key === 'mbti') { + value = value.map((s) => INVERTED_MBTI_CHOICES[s]) + } else if (key === 'pref_romantic_styles') { + value = value.map((s) => + translate(`profile.romantic.${s}`, INVERTED_ROMANTIC_CHOICES[s]) + ) + } else if (key === 'pref_relation_styles') { + value = value.map((s) => + translate( + `profile.relationship.${s}`, + INVERTED_RELATIONSHIP_CHOICES[s] + ) + ) + } else if (key === 'relationship_status') { + value = value.map((s) => + translate( + `profile.relationship_status.${s}`, + INVERTED_RELATIONSHIP_STATUS_CHOICES[s] + ) + ) + } else if (key === 'political_beliefs') { + value = value.map((s) => + translate(`profile.political.${s}`, INVERTED_POLITICAL_CHOICES[s]) + ) + } else if (key === 'diet') { + value = value.map((s) => + translate(`profile.diet.${s}`, INVERTED_DIET_CHOICES[s]) + ) + } else if (key === 'education_levels') { + value = value.map((s) => + translate(`profile.education.${s}`, INVERTED_EDUCATION_CHOICES[s]) + ) + } else if (key === 'religion') { + value = value.map((s) => + translate(`profile.religion.${s}`, INVERTED_RELIGION_CHOICES[s]) + ) + } else if (key === 'languages') { + value = value.map((s) => + translate(`profile.language.${s}`, INVERTED_LANGUAGE_CHOICES[s]) + ) + } else if (key === 'pref_gender') { + value = value.map((s) => + translate(`profile.gender.${s}`, INVERTED_GENDERS[s]) + ) + } else if (key === 'genders') { + value = value.map((s) => + translate(`profile.gender.${s}`, INVERTED_GENDERS[s]) + ) } stringValue = value.join(', ') } @@ -106,11 +206,81 @@ export function formatFilters( const display = stringValue - entries.push(`${label}${label ? ': ' : ''}${display}`) + entries.push(`${translatedLabel}${translatedLabel ? ': ' : ''}${display}`) }) if (ageEntry) entries.push(ageEntry) + // Process Big Five personality traits as ranges + const big5Traits = [ + {name: 'openness', min: 'big5_openness_min', max: 'big5_openness_max'}, + { + name: 'conscientiousness', + min: 'big5_conscientiousness_min', + max: 'big5_conscientiousness_max', + }, + { + name: 'extraversion', + min: 'big5_extraversion_min', + max: 'big5_extraversion_max', + }, + { + name: 'agreeableness', + min: 'big5_agreeableness_min', + max: 'big5_agreeableness_max', + }, + { + name: 'neuroticism', + min: 'big5_neuroticism_min', + max: 'big5_neuroticism_max', + }, + ] as const + + big5Traits.forEach(({name, min, max}) => { + const minValue = filters[min as keyof FilterFields] as number | undefined + const maxValue = filters[max as keyof FilterFields] as number | undefined + + if (minValue !== undefined || maxValue !== undefined) { + const traitName = translate(`profile.big5_${name}`, capitalize(name)) + let rangeText: string + + if (minValue !== undefined && maxValue !== undefined) { + // Both min and max: "12-78" + rangeText = `${minValue}-${maxValue}` + } else if (minValue !== undefined) { + // Only min: "12+" + rangeText = `${minValue}+` + } else { + // Only max: "up to 82" + rangeText = `${translate('filter.age.up_to', 'up to')} ${maxValue}` + } + + entries.push(`${traitName}: ${rangeText}`) + } + }) + + // Process drinks as range + const drinksMin = filters.drinks_min + const drinksMax = filters.drinks_max + if (drinksMin !== undefined || drinksMax !== undefined) { + const drinksLabel = translate('filter.label.drinks', 'Drinks') + const perMonth = translate('filter.drinks.per_month', 'per month') + let drinksText: string + + if (drinksMin !== undefined && drinksMax !== undefined) { + // Both min and max: "12-78" + drinksText = `${drinksMin}-${drinksMax}` + } else if (drinksMin !== undefined) { + // Only min: "12+" + drinksText = `${drinksMin}+` + } else { + // Only max: "up to 82" + drinksText = `${translate('filter.age.up_to', 'up to')} ${drinksMax}` + } + + entries.push(`${drinksLabel}: ${drinksText} ${perMonth}`) + } + if (location?.location?.name) { const radius = location?.radius || 0 let formattedRadius: string @@ -123,7 +293,8 @@ export function formatFilters( entries.push(locString) } - if (entries.length === 0) return ['Anyone'] + if (entries.length === 0) + return [translate('filter.any_new_users', 'Any new user')] return entries } diff --git a/web/components/filters/diet-filter.tsx b/web/components/filters/diet-filter.tsx index 6079d721..34542394 100644 --- a/web/components/filters/diet-filter.tsx +++ b/web/components/filters/diet-filter.tsx @@ -3,7 +3,7 @@ import {convertDietTypes, DietType,} from 'web/lib/util/convert-types' import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text' import {MultiCheckbox} from 'web/components/multi-checkbox' -import {DIET_CHOICES} from 'web/components/filters/choices' +import {DIET_CHOICES} from 'common/choices' import {FilterFields} from 'common/filters' import {useT} from 'web/lib/locale' diff --git a/web/components/filters/education-filter.tsx b/web/components/filters/education-filter.tsx index ee8802ba..3af5582a 100644 --- a/web/components/filters/education-filter.tsx +++ b/web/components/filters/education-filter.tsx @@ -2,7 +2,7 @@ import clsx from 'clsx' import {MultiCheckbox} from 'web/components/multi-checkbox' import {FilterFields} from "common/filters"; -import {EDUCATION_CHOICES} from "web/components/filters/choices"; +import {EDUCATION_CHOICES} from "common/choices"; import {convertEducationTypes} from "web/lib/util/convert-types"; import stringOrStringArrayToText from "web/lib/util/string-or-string-array-to-text"; import {getSortedOptions} from 'common/util/sorting' diff --git a/web/components/filters/gender-filter.tsx b/web/components/filters/gender-filter.tsx index adf9294e..3f62b5a5 100644 --- a/web/components/filters/gender-filter.tsx +++ b/web/components/filters/gender-filter.tsx @@ -5,7 +5,7 @@ import {Row} from 'web/components/layout/row' import {MultiCheckbox} from 'web/components/multi-checkbox' import {useT} from 'web/lib/locale' import {FilterFields} from "common/filters"; -import {GENDERS_PLURAL} from "web/components/filters/choices"; +import {GENDERS_PLURAL} from "common/choices"; export function GenderFilterText(props: { gender: Gender[] | undefined diff --git a/web/components/filters/language-filter.tsx b/web/components/filters/language-filter.tsx index fef9ebf2..e2d2e973 100644 --- a/web/components/filters/language-filter.tsx +++ b/web/components/filters/language-filter.tsx @@ -3,7 +3,7 @@ import {convertLanguageTypes,} from 'web/lib/util/convert-types' import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text' import {MultiCheckbox} from 'web/components/multi-checkbox' -import {LANGUAGE_CHOICES} from 'web/components/filters/choices' +import {LANGUAGE_CHOICES} from 'common/choices' import {FilterFields} from 'common/filters' import {getSortedOptions} from 'common/util/sorting' import {useT} from 'web/lib/locale' diff --git a/web/components/filters/mbti-filter.tsx b/web/components/filters/mbti-filter.tsx index c5f7f52a..81ddef53 100644 --- a/web/components/filters/mbti-filter.tsx +++ b/web/components/filters/mbti-filter.tsx @@ -1,5 +1,5 @@ import clsx from 'clsx' -import {MBTI_CHOICES} from 'web/components/filters/choices' +import {MBTI_CHOICES} from 'common/choices' import {FilterFields} from 'common/filters' import {getSortedOptions} from 'common/util/sorting' import {MultiCheckbox} from 'web/components/multi-checkbox' diff --git a/web/components/filters/political-filter.tsx b/web/components/filters/political-filter.tsx index 8a5a5677..41ba27c1 100644 --- a/web/components/filters/political-filter.tsx +++ b/web/components/filters/political-filter.tsx @@ -3,7 +3,7 @@ import {convertPoliticalTypes,} from 'web/lib/util/convert-types' import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text' import {MultiCheckbox} from 'web/components/multi-checkbox' -import {POLITICAL_CHOICES} from 'web/components/filters/choices' +import {POLITICAL_CHOICES} from 'common/choices' import {FilterFields} from 'common/filters' import {getSortedOptions} from 'common/util/sorting' import {useT} from 'web/lib/locale' diff --git a/web/components/filters/pref-gender-filter.tsx b/web/components/filters/pref-gender-filter.tsx index 99cd4bf8..db23443d 100644 --- a/web/components/filters/pref-gender-filter.tsx +++ b/web/components/filters/pref-gender-filter.tsx @@ -5,7 +5,7 @@ import {Row} from 'web/components/layout/row' import {MultiCheckbox} from 'web/components/multi-checkbox' import {FilterFields} from 'common/filters' import {useT} from 'web/lib/locale' -import {GENDERS_PLURAL} from "web/components/filters/choices"; +import {GENDERS_PLURAL} from "common/choices"; export function PrefGenderFilterText(props: { pref_gender: Gender[] | undefined diff --git a/web/components/filters/relationship-filter.tsx b/web/components/filters/relationship-filter.tsx index afd43d7e..3e7bb14a 100644 --- a/web/components/filters/relationship-filter.tsx +++ b/web/components/filters/relationship-filter.tsx @@ -4,7 +4,7 @@ import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-te import {MultiCheckbox} from 'web/components/multi-checkbox' import {useT} from 'web/lib/locale' -import {RELATIONSHIP_CHOICES} from "web/components/filters/choices"; +import {RELATIONSHIP_CHOICES} from "common/choices"; import {FilterFields} from "common/filters"; export function RelationshipFilterText(props: { diff --git a/web/components/filters/relationship-status-filter.tsx b/web/components/filters/relationship-status-filter.tsx index 7c8dba2f..3428bd77 100644 --- a/web/components/filters/relationship-status-filter.tsx +++ b/web/components/filters/relationship-status-filter.tsx @@ -3,7 +3,7 @@ import {convertRelationshipStatusTypes,} from 'web/lib/util/convert-types' import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text' import {MultiCheckbox} from 'web/components/multi-checkbox' -import {RELATIONSHIP_STATUS_CHOICES} from "web/components/filters/choices" +import {RELATIONSHIP_STATUS_CHOICES} from "common/choices" import {FilterFields} from "common/filters" import {getSortedOptions} from "common/util/sorting" import {useT} from 'web/lib/locale' diff --git a/web/components/filters/religion-filter.tsx b/web/components/filters/religion-filter.tsx index 6be3b4a0..d4a03c7c 100644 --- a/web/components/filters/religion-filter.tsx +++ b/web/components/filters/religion-filter.tsx @@ -2,7 +2,7 @@ import clsx from 'clsx' import {MultiCheckbox} from 'web/components/multi-checkbox' import {FilterFields} from 'common/filters' -import {RELIGION_CHOICES} from 'web/components/filters/choices' +import {RELIGION_CHOICES} from 'common/choices' import {convertReligionTypes} from 'web/lib/util/convert-types' import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text' import {getSortedOptions} from 'common/util/sorting' diff --git a/web/components/filters/romantic-filter.tsx b/web/components/filters/romantic-filter.tsx index e7998b8d..625d7a44 100644 --- a/web/components/filters/romantic-filter.tsx +++ b/web/components/filters/romantic-filter.tsx @@ -3,7 +3,7 @@ import {convertRomanticTypes, RomanticType,} from 'web/lib/util/convert-types' import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text' import {MultiCheckbox} from 'web/components/multi-checkbox' -import {ROMANTIC_CHOICES} from 'web/components/filters/choices' +import {ROMANTIC_CHOICES} from 'common/choices' import {FilterFields} from 'common/filters' import {useT} from 'web/lib/locale' import {toKey} from "common/parsing"; diff --git a/web/components/optional-profile-form.tsx b/web/components/optional-profile-form.tsx index 990df8de..6de47a45 100644 --- a/web/components/optional-profile-form.tsx +++ b/web/components/optional-profile-form.tsx @@ -40,7 +40,7 @@ import { RELATIONSHIP_STATUS_CHOICES, RELIGION_CHOICES, ROMANTIC_CHOICES, -} from 'web/components/filters/choices' +} from 'common/choices' import toast from 'react-hot-toast' import {db} from 'web/lib/supabase/db' import {fetchChoices} from 'web/hooks/use-choices' diff --git a/web/components/profile-about.tsx b/web/components/profile-about.tsx index b5824e32..344a3b21 100644 --- a/web/components/profile-about.tsx +++ b/web/components/profile-about.tsx @@ -10,8 +10,7 @@ import { INVERTED_POLITICAL_CHOICES, INVERTED_RELATIONSHIP_STATUS_CHOICES, INVERTED_RELIGION_CHOICES, - RELATIONSHIP_ICONS, -} from 'web/components/filters/choices' +} from 'common/choices' import {BiSolidDrink} from 'react-icons/bi' import {BsPersonHeart, BsPersonVcard} from 'react-icons/bs' import {FaChild} from 'react-icons/fa6' @@ -30,12 +29,13 @@ import {UserActivity} from 'common/user' import {ClockIcon} from '@heroicons/react/solid' import {formatHeight, MeasurementSystem} from 'common/measurement-utils' import {MAX_INT, MIN_INT} from 'common/constants' -import {GiFruitBowl} from 'react-icons/gi' -import {FaBriefcase, FaHandsHelping, FaHeart, FaStar} from 'react-icons/fa' +import {GiFruitBowl, GiRing} from 'react-icons/gi' +import {FaBriefcase, FaHandsHelping, FaHeart, FaStar, FaUsers} from 'react-icons/fa' import {useLocale, useT} from 'web/lib/locale' import {useChoices} from 'web/hooks/use-choices' import {getSeekingGenderText} from 'web/lib/profile/seeking' import {TbBulb, TbCheck, TbMoodSad, TbUsers} from 'react-icons/tb' +import {FiUser} from "react-icons/fi" export function AboutRow(props: { icon: ReactNode @@ -538,3 +538,12 @@ const capitalizeAndRemoveUnderscores = (str: string) => { const withSpaces = str.replace(/_/g, ' ') return withSpaces.charAt(0).toUpperCase() + withSpaces.slice(1) } + + +export const RELATIONSHIP_ICONS = { + single: FiUser, + married: GiRing, + casual: FaHeart, + long_term: FaHeart, + open: FaUsers, +} as const \ No newline at end of file diff --git a/web/components/searches/button.tsx b/web/components/searches/button.tsx index bacbe974..0d6bfcf7 100644 --- a/web/components/searches/button.tsx +++ b/web/components/searches/button.tsx @@ -77,6 +77,7 @@ function ButtonModal(props: { onClose={() => { refreshBookmarkedSearches() }} + size={'lg'} >

{t('saved_searches.title', 'Saved Searches')}

@@ -89,34 +90,36 @@ function ButtonModal(props: { )}

-
    - {(bookmarkedSearches || []).map((search) => ( -
  1. + {(bookmarkedSearches || []).map((search) => ( + +
    {formatFilters( search.search_filters as Partial, search.location as locationType, choicesIdsToLabels, - measurementSystem + measurementSystem, + t )?.join(' • ')} - -
  2. - ))} -
+ + + + ))} ) : ( diff --git a/web/lib/profile/seeking.ts b/web/lib/profile/seeking.ts index 047b4cf6..00b715b7 100644 --- a/web/lib/profile/seeking.ts +++ b/web/lib/profile/seeking.ts @@ -1,7 +1,7 @@ import {convertRelationshipType, RelationshipType} from "web/lib/util/convert-types"; import stringOrStringArrayToText from "web/lib/util/string-or-string-array-to-text"; import {Profile} from "common/profiles/profile"; -import {INVERTED_ROMANTIC_CHOICES} from "web/components/filters/choices"; +import {INVERTED_ROMANTIC_CHOICES} from "common/choices"; export function getSeekingGenderText(profile: Profile, t: any) { const relationshipTypes = profile.pref_relation_styles diff --git a/web/lib/util/convert-types.ts b/web/lib/util/convert-types.ts index ca766f46..87472fb2 100644 --- a/web/lib/util/convert-types.ts +++ b/web/lib/util/convert-types.ts @@ -8,7 +8,7 @@ import { INVERTED_RELATIONSHIP_STATUS_CHOICES, INVERTED_RELIGION_CHOICES, INVERTED_ROMANTIC_CHOICES -} from "web/components/filters/choices"; +} from "common/choices"; export type RelationshipType = keyof typeof INVERTED_RELATIONSHIP_CHOICES diff --git a/web/messages/de.json b/web/messages/de.json index f89834e2..4b71aba0 100644 --- a/web/messages/de.json +++ b/web/messages/de.json @@ -1121,5 +1121,20 @@ "settings.measurement.metric": "Metrisch", "font.atkinson": "Atkinson Hyperlegible", "font.system-sans": "System Sans", - "font.classic-serif": "Klassische Serifenschrift" + "font.classic-serif": "Klassische Serifenschrift", + "filter.age.label": "Alter", + "filter.age.up_to": "bis zu", + "filter.any_new_users": "Jegliche neue Nutzer", + "filter.label.name": "Suche", + "filter.label.education_levels": "Bildung", + "filter.label.pref_age_max": "Max. Alter", + "filter.label.pref_age_min": "Min. Alter", + "filter.label.drinks": "Getränke", + "filter.label.wants_kids_strength": "Kinder", + "filter.label.pref_relation_styles": "Suche", + "filter.label.pref_gender": "Gesuchtes Geschlecht", + "filter.label.diet": "Ernährung", + "filter.label.political_beliefs": "Politische Ansichten", + "filter.label.mbti": "MBTI", + "filter.drinks.per_month": "pro Monat" } diff --git a/web/messages/fr.json b/web/messages/fr.json index 9c745c5b..ad4077b1 100644 --- a/web/messages/fr.json +++ b/web/messages/fr.json @@ -1121,5 +1121,20 @@ "settings.measurement.metric": "Métrique", "font.atkinson": "Atkinson Hyperlegible", "font.system-sans": "Sans-serif système", - "font.classic-serif": "Serif classique" + "font.classic-serif": "Serif classique", + "filter.age.label": "Âge", + "filter.age.up_to": "jusqu'à", + "filter.any_new_users": "Tout nouvel utilisateur", + "filter.label.name": "Recherche", + "filter.label.education_levels": "Éducation", + "filter.label.pref_age_max": "Âge max", + "filter.label.pref_age_min": "Âge min", + "filter.label.drinks": "Boissons", + "filter.label.wants_kids_strength": "Enfants", + "filter.label.pref_relation_styles": "Recherche", + "filter.label.pref_gender": "Genre recherché", + "filter.label.diet": "Régime", + "filter.label.political_beliefs": "Opinions politiques", + "filter.label.mbti": "MBTI", + "filter.drinks.per_month": "par mois" }