From a3cc072bbd80f257f68039b2977a8d4261b69e78 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 31 Aug 2021 12:49:35 +0200 Subject: [PATCH] feat(i18n): translate countries selector --- Gemfile | 1 + Gemfile.lock | 2 + app/controllers/api/pays_controller.rb | 20 + app/javascript/components/ComboPaysSearch.jsx | 2 +- app/javascript/components/ComboSearch.jsx | 21 +- .../components/shared/queryClient.js | 4 +- app/models/champs/pays_champ.rb | 15 + .../dossiers/editable_champs/_pays.html.haml | 3 +- config/routes.rb | 2 + public/pays.json | 848 ------------------ spec/features/users/brouillon_spec.rb | 6 +- 11 files changed, 61 insertions(+), 863 deletions(-) create mode 100644 app/controllers/api/pays_controller.rb delete mode 100644 public/pays.json diff --git a/Gemfile b/Gemfile index 8a7d7b6f5..6bef72e7d 100644 --- a/Gemfile +++ b/Gemfile @@ -42,6 +42,7 @@ gem 'groupdate' gem 'haml-rails' gem 'hashie' gem 'http_accept_language' +gem 'i18n_data' gem 'i18n-tasks', require: false gem 'iban-tools' gem 'image_processing' diff --git a/Gemfile.lock b/Gemfile.lock index d5b56654c..d5a3dac03 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -360,6 +360,7 @@ GEM rails-i18n rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) + i18n_data (0.13.0) iban-tools (1.1.0) ice_nine (0.11.2) image_processing (1.12.1) @@ -837,6 +838,7 @@ DEPENDENCIES hashie http_accept_language i18n-tasks + i18n_data iban-tools image_processing json_schemer diff --git a/app/controllers/api/pays_controller.rb b/app/controllers/api/pays_controller.rb new file mode 100644 index 000000000..b64359281 --- /dev/null +++ b/app/controllers/api/pays_controller.rb @@ -0,0 +1,20 @@ +class API::PaysController < ApplicationController + before_action :authenticate_logged_user! + + def index + countries = I18nData.countries('FR').zip(I18nData.countries(I18n.locale)) + countries = countries.map do |(code, value_fr), (localized_code, localized_value)| + if code != localized_code + raise "Countries lists mismatch. It means i18n_data gem has some internal inconsistencies." + end + + { + code: code, + value: value_fr, + label: localized_value + } + end + + render json: countries + end +end diff --git a/app/javascript/components/ComboPaysSearch.jsx b/app/javascript/components/ComboPaysSearch.jsx index 7bddae9f9..22b1cdcd6 100644 --- a/app/javascript/components/ComboPaysSearch.jsx +++ b/app/javascript/components/ComboPaysSearch.jsx @@ -12,7 +12,7 @@ function ComboPaysSearch(params) { hiddenFieldId={params.hiddenFieldId} scope="pays" minimumInputLength={0} - transformResult={({ nom }) => [nom, nom]} + transformResult={({ code, value, label }) => [code, value, label]} /> ); diff --git a/app/javascript/components/ComboSearch.jsx b/app/javascript/components/ComboSearch.jsx index a257181a4..5bcf4d559 100644 --- a/app/javascript/components/ComboSearch.jsx +++ b/app/javascript/components/ComboSearch.jsx @@ -47,6 +47,10 @@ function ComboSearch({ const [debouncedSearchTerm] = useDebounce(searchTerm, 300); const [value, setValue] = useState(initialValue); const resultsMap = useRef({}); + const getLabel = (result) => { + const [, value, label] = transformResult(result); + return label ?? value; + }; const setExternalValue = useCallback( (value) => { if (hiddenValueField) { @@ -64,8 +68,8 @@ function ComboSearch({ }, [hiddenIdField] ); - const setExternalValueAndId = useCallback((value) => { - const [key, result] = resultsMap.current[value]; + const setExternalValueAndId = useCallback((label) => { + const { key, value, result } = resultsMap.current[label]; setExternalId(key); setExternalValue(value); if (onChange) { @@ -107,9 +111,9 @@ function ComboSearch({ const onBlur = useCallback(() => { if (!allowInputValues && isSuccess && results[0]) { - const [, value] = transformResult(results[0]); + const label = getLabel(results[0]); awaitFormSubmit(() => { - handleOnSelect(value); + handleOnSelect(label); }); } }, [data]); @@ -129,13 +133,14 @@ function ComboSearch({ {results.length > 0 ? ( {results.map((result, index) => { - const [key, str] = transformResult(result); - resultsMap.current[str] = [key, result]; + const label = getLabel(result); + const [key, value] = transformResult(result); + resultsMap.current[label] = { key, value, result }; return ( ); })} diff --git a/app/javascript/components/shared/queryClient.js b/app/javascript/components/shared/queryClient.js index 5971b99c2..9ec274d87 100644 --- a/app/javascript/components/shared/queryClient.js +++ b/app/javascript/components/shared/queryClient.js @@ -55,7 +55,7 @@ function buildOptions() { async function defaultQueryFn({ queryKey: [scope, term] }) { if (scope == 'pays') { - return matchSorter(await getPays(), term, { keys: ['nom'] }); + return matchSorter(await getPays(), term, { keys: ['label'] }); } const url = buildURL(scope, term); @@ -73,7 +73,7 @@ async function defaultQueryFn({ queryKey: [scope, term] }) { let paysCache; async function getPays() { if (!paysCache) { - paysCache = await fetch('/pays.json').then((response) => response.json()); + paysCache = await fetch('/api/pays').then((response) => response.json()); } return paysCache; } diff --git a/app/models/champs/pays_champ.rb b/app/models/champs/pays_champ.rb index ba56eb3ee..04110d82f 100644 --- a/app/models/champs/pays_champ.rb +++ b/app/models/champs/pays_champ.rb @@ -18,4 +18,19 @@ # type_de_champ_id :integer # class Champs::PaysChamp < Champs::TextChamp + def localized_value + if external_id + I18nData.countries(I18n.locale)[external_id] + else + value.present? ? value.to_s : '' + end + end + + def to_s + localized_value + end + + def for_tag + localized_value + end end diff --git a/app/views/shared/dossiers/editable_champs/_pays.html.haml b/app/views/shared/dossiers/editable_champs/_pays.html.haml index 5a9ca2523..241049b46 100644 --- a/app/views/shared/dossiers/editable_champs/_pays.html.haml +++ b/app/views/shared/dossiers/editable_champs/_pays.html.haml @@ -1,3 +1,4 @@ - hidden_field_id = SecureRandom.uuid -= form.hidden_field :value, { data: { uuid: hidden_field_id } } += form.hidden_field :value, { value: champ.localized_value, data: { uuid: hidden_field_id } } += form.hidden_field :external_id, { data: { reference: true } } = react_component("ComboPaysSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id) diff --git a/config/routes.rb b/config/routes.rb index 6fbfb9841..52f57517a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -242,6 +242,8 @@ Rails.application.routes.draw do get 'dossiers/pdf/:id', format: :pdf, to: "dossiers#pdf", as: :dossier_pdf get 'dossiers/geojson/:id', to: "dossiers#geojson", as: :dossier_geojson end + + resources :pays, only: :index end # diff --git a/public/pays.json b/public/pays.json deleted file mode 100644 index a56e16923..000000000 --- a/public/pays.json +++ /dev/null @@ -1,848 +0,0 @@ -[ - { - "nom": "FRANCE" - }, - { - "nom": "ACORES, MADERE" - }, - { - "nom": "AFGHANISTAN" - }, - { - "nom": "AFRIQUE DU SUD" - }, - { - "nom": "ALASKA" - }, - { - "nom": "ALBANIE" - }, - { - "nom": "ALGERIE" - }, - { - "nom": "ALLEMAGNE" - }, - { - "nom": "ANDORRE" - }, - { - "nom": "ANGOLA" - }, - { - "nom": "ANGUILLA" - }, - { - "nom": "ANTIGUA-ET-BARBUDA" - }, - { - "nom": "ANTILLES NEERLANDAISES" - }, - { - "nom": "ARABIE SAOUDITE" - }, - { - "nom": "ARGENTINE" - }, - { - "nom": "ARMENIE" - }, - { - "nom": "ARUBA" - }, - { - "nom": "AUSTRALIE" - }, - { - "nom": "AUTRICHE" - }, - { - "nom": "AZERBAIDJAN" - }, - { - "nom": "BAHAMAS" - }, - { - "nom": "BAHREIN" - }, - { - "nom": "BANGLADESH" - }, - { - "nom": "BARBADE" - }, - { - "nom": "BELGIQUE" - }, - { - "nom": "BELIZE" - }, - { - "nom": "BENIN" - }, - { - "nom": "BERMUDES" - }, - { - "nom": "BHOUTAN" - }, - { - "nom": "BIELORUSSIE" - }, - { - "nom": "BIRMANIE" - }, - { - "nom": "BOLIVIE" - }, - { - "nom": "BONAIRE, SAINT EUSTACHE ET SABA" - }, - { - "nom": "BOSNIE-HERZEGOVINE" - }, - { - "nom": "BOTSWANA" - }, - { - "nom": "BOUVET (ILE)" - }, - { - "nom": "BRESIL" - }, - { - "nom": "BRUNEI" - }, - { - "nom": "BULGARIE" - }, - { - "nom": "BURKINA" - }, - { - "nom": "BURUNDI" - }, - { - "nom": "CAIMANES (ILES)" - }, - { - "nom": "CAMBODGE" - }, - { - "nom": "CAMEROUN" - }, - { - "nom": "CAMEROUN ET TOGO" - }, - { - "nom": "CANADA" - }, - { - "nom": "CANARIES (ILES)" - }, - { - "nom": "CAP-VERT" - }, - { - "nom": "CENTRAFRICAINE (REPUBLIQUE)" - }, - { - "nom": "CHILI" - }, - { - "nom": "CHINE" - }, - { - "nom": "CHRISTMAS (ILE)" - }, - { - "nom": "CHYPRE" - }, - { - "nom": "CLIPPERTON (ILE)" - }, - { - "nom": "COCOS ou KEELING (ILES)" - }, - { - "nom": "COLOMBIE" - }, - { - "nom": "COMORES" - }, - { - "nom": "CONGO" - }, - { - "nom": "CONGO (REPUBLIQUE DEMOCRATIQUE)" - }, - { - "nom": "COOK (ILES)" - }, - { - "nom": "COREE" - }, - { - "nom": "COREE (REPUBLIQUE DE)" - }, - { - "nom": "COREE (REPUBLIQUE POPULAIRE DEMOCRATIQUE DE)" - }, - { - "nom": "COSTA RICA" - }, - { - "nom": "COTE D'IVOIRE" - }, - { - "nom": "CROATIE" - }, - { - "nom": "CUBA" - }, - { - "nom": "CURAÇAO" - }, - { - "nom": "DANEMARK" - }, - { - "nom": "DJIBOUTI" - }, - { - "nom": "DOMINICAINE (REPUBLIQUE)" - }, - { - "nom": "DOMINIQUE" - }, - { - "nom": "EGYPTE" - }, - { - "nom": "EL SALVADOR" - }, - { - "nom": "EMIRATS ARABES UNIS" - }, - { - "nom": "EQUATEUR" - }, - { - "nom": "ERYTHREE" - }, - { - "nom": "ESPAGNE" - }, - { - "nom": "ESTONIE" - }, - { - "nom": "ETATS MALAIS NON FEDERES" - }, - { - "nom": "ETATS-UNIS" - }, - { - "nom": "ETHIOPIE" - }, - { - "nom": "FEROE (ILES)" - }, - { - "nom": "FIDJI" - }, - { - "nom": "FINLANDE" - }, - { - "nom": "GABON" - }, - { - "nom": "GAMBIE" - }, - { - "nom": "GEORGIE" - }, - { - "nom": "GEORGIE DU SUD ET LES ILES SANDWICH DU SUD" - }, - { - "nom": "GHANA" - }, - { - "nom": "GIBRALTAR" - }, - { - "nom": "GOA" - }, - { - "nom": "GRECE" - }, - { - "nom": "GRENADE" - }, - { - "nom": "GROENLAND" - }, - { - "nom": "GUADELOUPE" - }, - { - "nom": "GUAM" - }, - { - "nom": "GUATEMALA" - }, - { - "nom": "GUERNESEY" - }, - { - "nom": "GUINEE" - }, - { - "nom": "GUINEE EQUATORIALE" - }, - { - "nom": "GUINEE-BISSAU" - }, - { - "nom": "GUYANA" - }, - { - "nom": "GUYANE" - }, - { - "nom": "HAITI" - }, - { - "nom": "HAWAII (ILES)" - }, - { - "nom": "HEARD ET MACDONALD (ILES)" - }, - { - "nom": "HONDURAS" - }, - { - "nom": "HONG-KONG" - }, - { - "nom": "HONGRIE" - }, - { - "nom": "ILES PORTUGAISES DE L'OCEAN INDIEN" - }, - { - "nom": "INDE" - }, - { - "nom": "INDONESIE" - }, - { - "nom": "IRAN" - }, - { - "nom": "IRAQ" - }, - { - "nom": "IRLANDE, ou EIRE" - }, - { - "nom": "ISLANDE" - }, - { - "nom": "ISRAEL" - }, - { - "nom": "ITALIE" - }, - { - "nom": "JAMAIQUE" - }, - { - "nom": "JAPON" - }, - { - "nom": "JERSEY" - }, - { - "nom": "JORDANIE" - }, - { - "nom": "KAMTCHATKA" - }, - { - "nom": "KAZAKHSTAN" - }, - { - "nom": "KENYA" - }, - { - "nom": "KIRGHIZISTAN" - }, - { - "nom": "KIRIBATI" - }, - { - "nom": "KOSOVO" - }, - { - "nom": "KOWEIT" - }, - { - "nom": "LA REUNION" - }, - { - "nom": "LABRADOR" - }, - { - "nom": "LAOS" - }, - { - "nom": "LESOTHO" - }, - { - "nom": "LETTONIE" - }, - { - "nom": "LIBAN" - }, - { - "nom": "LIBERIA" - }, - { - "nom": "LIBYE" - }, - { - "nom": "LIECHTENSTEIN" - }, - { - "nom": "LITUANIE" - }, - { - "nom": "LUXEMBOURG" - }, - { - "nom": "MACAO" - }, - { - "nom": "MACEDOINE DU NORD (REPUBLIQUE DE)" - }, - { - "nom": "MADAGASCAR" - }, - { - "nom": "MALAISIE" - }, - { - "nom": "MALAWI" - }, - { - "nom": "MALDIVES" - }, - { - "nom": "MALI" - }, - { - "nom": "MALOUINES, OU FALKLAND (ILES)" - }, - { - "nom": "MALTE" - }, - { - "nom": "MAN (ILE)" - }, - { - "nom": "MANDCHOURIE" - }, - { - "nom": "MARIANNES DU NORD (ILES)" - }, - { - "nom": "MAROC" - }, - { - "nom": "MARSHALL (ILES)" - }, - { - "nom": "MARTINIQUE" - }, - { - "nom": "MAURICE" - }, - { - "nom": "MAURITANIE" - }, - { - "nom": "MAYOTTE" - }, - { - "nom": "MEXIQUE" - }, - { - "nom": "MICRONESIE (ETATS FEDERES DE)" - }, - { - "nom": "MOLDAVIE" - }, - { - "nom": "MONACO" - }, - { - "nom": "MONGOLIE" - }, - { - "nom": "MONTENEGRO" - }, - { - "nom": "MONTSERRAT" - }, - { - "nom": "MOZAMBIQUE" - }, - { - "nom": "NAMIBIE" - }, - { - "nom": "NAURU" - }, - { - "nom": "NEPAL" - }, - { - "nom": "NICARAGUA" - }, - { - "nom": "NIGER" - }, - { - "nom": "NIGERIA" - }, - { - "nom": "NIUE" - }, - { - "nom": "NORFOLK (ILE)" - }, - { - "nom": "NORVEGE" - }, - { - "nom": "NOUVELLE-CALEDONIE" - }, - { - "nom": "NOUVELLE-ZELANDE" - }, - { - "nom": "OCEAN INDIEN (TERRITOIRE BRITANNIQUE DE L')" - }, - { - "nom": "OMAN" - }, - { - "nom": "OUGANDA" - }, - { - "nom": "OUZBEKISTAN" - }, - { - "nom": "PAKISTAN" - }, - { - "nom": "PALAOS (ILES)" - }, - { - "nom": "PALESTINE (Etat de)" - }, - { - "nom": "PANAMA" - }, - { - "nom": "PAPOUASIE-NOUVELLE-GUINEE" - }, - { - "nom": "PARAGUAY" - }, - { - "nom": "PAYS-BAS" - }, - { - "nom": "PEROU" - }, - { - "nom": "PHILIPPINES" - }, - { - "nom": "PITCAIRN (ILE)" - }, - { - "nom": "POLOGNE" - }, - { - "nom": "POLYNESIE FRANCAISE" - }, - { - "nom": "PORTO RICO" - }, - { - "nom": "PORTUGAL" - }, - { - "nom": "POSSESSIONS BRITANNIQUES AU PROCHE-ORIENT" - }, - { - "nom": "PRESIDES" - }, - { - "nom": "PROVINCES ESPAGNOLES D'AFRIQUE" - }, - { - "nom": "QATAR" - }, - { - "nom": "REPUBLIQUE DEMOCRATIQUE ALLEMANDE" - }, - { - "nom": "REPUBLIQUE FEDERALE D'ALLEMAGNE" - }, - { - "nom": "ROUMANIE" - }, - { - "nom": "ROYAUME-UNI" - }, - { - "nom": "RUSSIE" - }, - { - "nom": "RWANDA" - }, - { - "nom": "SAHARA OCCIDENTAL" - }, - { - "nom": "SAINT-BARTHELEMY" - }, - { - "nom": "SAINT-CHRISTOPHE-ET-NIEVES" - }, - { - "nom": "SAINT-MARIN" - }, - { - "nom": "SAINT-MARTIN" - }, - { - "nom": "SAINT-MARTIN (PARTIE NEERLANDAISE)" - }, - { - "nom": "SAINT-PIERRE-ET-MIQUELON" - }, - { - "nom": "SAINT-VINCENT-ET-LES GRENADINES" - }, - { - "nom": "SAINTE HELENE, ASCENSION ET TRISTAN DA CUNHA" - }, - { - "nom": "SAINTE-LUCIE" - }, - { - "nom": "SALOMON (ILES)" - }, - { - "nom": "SAMOA AMERICAINES" - }, - { - "nom": "SAMOA OCCIDENTALES" - }, - { - "nom": "SAO TOME-ET-PRINCIPE" - }, - { - "nom": "SENEGAL" - }, - { - "nom": "SERBIE" - }, - { - "nom": "SEYCHELLES" - }, - { - "nom": "SIBERIE" - }, - { - "nom": "SIERRA LEONE" - }, - { - "nom": "SINGAPOUR" - }, - { - "nom": "SLOVAQUIE" - }, - { - "nom": "SLOVENIE" - }, - { - "nom": "SOMALIE" - }, - { - "nom": "SOUDAN" - }, - { - "nom": "SOUDAN ANGLO-EGYPTIEN, KENYA, OUGANDA" - }, - { - "nom": "SOUDAN DU SUD" - }, - { - "nom": "SRI LANKA" - }, - { - "nom": "SUEDE" - }, - { - "nom": "SUISSE" - }, - { - "nom": "SURINAME" - }, - { - "nom": "SVALBARD et ILE JAN MAYEN" - }, - { - "nom": "SWAZILAND" - }, - { - "nom": "SYRIE" - }, - { - "nom": "TADJIKISTAN" - }, - { - "nom": "TAIWAN" - }, - { - "nom": "TANGER" - }, - { - "nom": "TANZANIE" - }, - { - "nom": "TCHAD" - }, - { - "nom": "TCHECOSLOVAQUIE" - }, - { - "nom": "TCHEQUE (REPUBLIQUE)" - }, - { - "nom": "TERR. DES ETATS-UNIS D'AMERIQUE EN AMERIQUE" - }, - { - "nom": "TERR. DES ETATS-UNIS D'AMERIQUE EN OCEANIE" - }, - { - "nom": "TERR. DU ROYAUME-UNI DANS L'ATLANTIQUE SUD" - }, - { - "nom": "TERRE-NEUVE" - }, - { - "nom": "TERRES AUSTRALES FRANCAISES" - }, - { - "nom": "TERRITOIRES DU ROYAUME-UNI AUX ANTILLES" - }, - { - "nom": "THAILANDE" - }, - { - "nom": "TIMOR ORIENTAL" - }, - { - "nom": "TOGO" - }, - { - "nom": "TOKELAU" - }, - { - "nom": "TONGA" - }, - { - "nom": "TRINITE-ET-TOBAGO" - }, - { - "nom": "TUNISIE" - }, - { - "nom": "TURKESTAN RUSSE" - }, - { - "nom": "TURKMENISTAN" - }, - { - "nom": "TURKS ET CAIQUES (ILES)" - }, - { - "nom": "TURQUIE" - }, - { - "nom": "TURQUIE D'EUROPE" - }, - { - "nom": "TUVALU" - }, - { - "nom": "UKRAINE" - }, - { - "nom": "URUGUAY" - }, - { - "nom": "VANUATU" - }, - { - "nom": "VATICAN, ou SAINT-SIEGE" - }, - { - "nom": "VENEZUELA" - }, - { - "nom": "VIERGES BRITANNIQUES (ILES)" - }, - { - "nom": "VIERGES DES ETATS-UNIS (ILES)" - }, - { - "nom": "VIET NAM" - }, - { - "nom": "VIET NAM DU NORD" - }, - { - "nom": "VIET NAM DU SUD" - }, - { - "nom": "WALLIS-ET-FUTUNA" - }, - { - "nom": "YEMEN" - }, - { - "nom": "YEMEN (REPUBLIQUE ARABE DU)" - }, - { - "nom": "YEMEN DEMOCRATIQUE" - }, - { - "nom": "ZAMBIE" - }, - { - "nom": "ZANZIBAR" - }, - { - "nom": "ZIMBABWE" - } -] diff --git a/spec/features/users/brouillon_spec.rb b/spec/features/users/brouillon_spec.rb index 30c127051..0b460aecc 100644 --- a/spec/features/users/brouillon_spec.rb +++ b/spec/features/users/brouillon_spec.rb @@ -28,7 +28,7 @@ feature 'The user' do select_multi_combobox('multiple_choice_drop_down_list_long', 'alp', 'alpha') select_multi_combobox('multiple_choice_drop_down_list_long', 'cha', 'charly') - select_combobox('pays', 'aust', 'AUSTRALIE') + select_combobox('pays', 'aust', 'Australie') select_combobox('regions', 'Ma', 'Martinique') select_combobox('departements', 'Ai', '02 - Aisne') select_combobox('communes', 'Ambl', 'Ambléon (01300)') @@ -57,7 +57,7 @@ feature 'The user' do expect(champ_value_for('simple_choice_drop_down_list_long')).to eq('bravo') expect(JSON.parse(champ_value_for('multiple_choice_drop_down_list_long'))).to match(['alpha', 'charly']) expect(JSON.parse(champ_value_for('multiple_drop_down_list'))).to match(['val1', 'val3']) - expect(champ_value_for('pays')).to eq('AUSTRALIE') + expect(champ_value_for('pays')).to eq('Australie') expect(champ_value_for('regions')).to eq('Martinique') expect(champ_value_for('departements')).to eq('02 - Aisne') expect(champ_value_for('communes')).to eq('Ambléon (01300)') @@ -82,7 +82,7 @@ feature 'The user' do expect(page).to have_checked_field('val3') expect(page).to have_selected_value('simple_choice_drop_down_list_long', selected: 'bravo') check_selected_values('multiple_choice_drop_down_list_long', ['alpha', 'charly']) - expect(page).to have_hidden_field('pays', with: 'AUSTRALIE') + expect(page).to have_hidden_field('pays', with: 'Australie') expect(page).to have_hidden_field('regions', with: 'Martinique') expect(page).to have_hidden_field('departements', with: '02 - Aisne') expect(page).to have_hidden_field('communes', with: 'Ambléon (01300)')