Repository navigation
feat(country): retire the translated name columns of t_country (#1939) - #1980
Conversation
- Select co.iso AS iso2 in the projection query: the front end localizes the group label of a projection from iso2 and falls back to en_name, which no longer exists once t_country loses its translated names. - Sort by native country name instead of the French one. - Fix the j_country_crs fixture, which used column names instead of the model attributes and so loaded rows with no country. - Document iso2 and native_name in the swagger, and that Fr_name is always World.
- Drop en_name, fr_name, es_name, de_name, bg_name, it_name, ca_name, nl_name and rs_name from t_country: native_name is the only name the API and the front end read, and the front end localizes country names from the ISO code. - Expose native_name instead of fr_name as country_name in v_data_quality_compute_entrance, the last reader of fr_name: the data-quality endpoints now return and sort on the native name (España instead of Espagne). - Add migration 9_37, one transaction: recreate the view with its four indexes, refresh it, give it back to gc_owner when gc_owner owns the tables, restore its grants, then drop the columns. - Remove the fields from TCountry, from managedCountries in toOrganization and the swagger, from the organization export GROUP BY, from 0_tables.sql, the countries seed and the fixtures.
Paul-AUB
left a comment
There was a problem hiding this comment.
Changes requested for deployment safety.
Given the size of the diff, analysis prioritized the migration, business logic and public API changes. All 250 country seed rows were also checked mechanically: their six retained values are unchanged.
Runtime validation is incomplete: the focused converter test command could not start because Mocha is not installed, and no PostgreSQL container is running. The chained lint command therefore did not run. Database initialization and migration checks reported in the PR were not independently reproduced.
- State in migration 9_37 that the API code which no longer reads the translated country names must be deployed, with no older process left, before the migration runs: the current code declares the columns in TCountry, sorts on fr_name in ConvertService and groups by them in the organization export, so it fails on the migrated schema. - Note that rolling the code back after the migration requires restoring the columns and their data first.
Paul-AUB
left a comment
There was a problem hiding this comment.
The previously requested deployment-order correction is addressed in the migration header and PR description. No further blocking findings identified.
Given the diff size, analysis prioritized migration ownership/grants/indexes, runtime readers and public API changes. Independently checked that all 250 country seed rows preserve their six retained values, the recreated view matches the canonical definition, and the organization converter emits only the intended country fields.
Validation: changed JavaScript passes ESLint when linted with LF-normalized input; the Windows checkout's CRLF endings cause formatting-only errors in a direct lint run. PostgreSQL/Docker and the local API are unavailable here, so the migration and route checks reported in the PR were not independently reproduced. GitHub's build-test check passes.
🤔 What
t_country(en_name,fr_name,es_name,de_name,bg_name,it_name,ca_name,nl_name,rs_name).native_namestays.v_data_quality_compute_entranceexposesco.native_nameascountry_nameinstead ofco.fr_name.sql/9_37_2026_11_06_drop_country_translations.sql. It runs as one transaction and:gc_owner,TCountrymanagedCountriesintoOrganizationand in the swaggerGROUP BYsql/0_tables.sql,sql/91_materialized_views.sqland the countries seedtest/fixtures/tcountry.jsonGET /api/v1/convert(and/api/convert) now returnsiso2, sorts by native country name and documents its fields. The issue missed this reader (see Why).Closes #1939
🤷♂️ Why
native_nameis the only country name the API and the front end use. The front end localizes country names from the ISO code withIntl.DisplayNames. The 9 other columns had no real reader left, apart fromfr_namein the data-quality view.One reader was missing from the issue.
ConvertServicerunsSELECT *overt_crs ⟕ t_countryand sorted onFr_name. With the columns dropped,/api/v1/convertreturned a 500. The front end reads that response too.CRSMenulabels each projection group withgetLocalizedCountryName(p.iso2 || p.country_code, locale, p.en_name). Neitheriso2norcountry_codeexists in the response today, so the label is always theen_namefallback. Withouten_name, every projection would have landed under "World". The query now returnsco.iso AS iso2, so the front end localizes the label from the ISO code with no front-end change needed.Behavior changes
/api/v1/entrances/with-quality/...):country_nameis now the native name (España, notEspagne), and so is thesort=country_nameorder. The front end does not readcountry_name. Documented in the swagger.managedCountries[]only carriesidandnativeName.enName…rsNameare gone from the public response. No front-end consumer is known; external API consumers should be checked before merging.iso2, keepsnative_name, and loses the translated*_namefields.Fr_namewas already alwaysWorld, because Postgres returns the column asfr_name. It is kept and documented as such.🔍 How
gc_ownerinzz_ownership_and_grants.sql. If the migration handed the view togc_ownerunconditionally,99_refresh_views.sqlwould fail withpermission denied for table t_entrance. The migration therefore gives the view togc_owneronly whengc_owneralready ownst_entrance(production). On a fresh volume,zz_ownership_and_grants.sqltransfers it with everything else.gc_ownerorgrottoce, so the migration grantsSELECT, INSERT, UPDATE, DELETEtogc_appandSELECTtogc_readonlyagain. That is exactly the ACL the view had before.search_outbox_enqueue_data_qualityreads the view by name and would fail while it is missing.j_country_crstest fixture used column names (id_country,id_crs) instead of the model's attributes, so its rows loaded with no country. It now usescountry/crs, which the new convert test needs.sql/9_37_2026_11_06_drop_country_translations.sqlby hand, after the deploy:TCountrydeclares them,ConvertServicesorts onfr_name, and the organization export groups by them.country_nameswitches to the native name as soon as it runs.Once the migration has run, rolling back to the previous code requires restoring the columns and their data first. The migration header documents this order too.
🧪 Testing
toOrganizationexposes managed countries withidandnativeNameonly./api/v1/convertreturnsiso2/native_namefor a projection with a country,nullfor a world-wide one, and noen_name/fr_name.npm run lint: clean.npm run test: 5492 passing, 5 failing. The 5 failures also fail ondevelopand are unrelated:Document get-snapshotsChangesrelevance-swap tests in shard 3, which pass in isolationgrottocenter-dbservercontainer from this branch'ssql/.t_countryhas the 6 expected columns.develop'ssql/, then applied the migration by hand.gc_owner, with the same ACL as before (gc_app=arwd,gc_readonly=r).REFRESH ... CONCURRENTLYandsearch_outbox_enqueue_data_quality()succeed.gc_app:GET /api/v1/convertreturns 200 withiso2.GET /api/v1/entrances/with-quality/countries/FR?sort=country_namereturns 200 with native names.GET /api/v1/organizations/1returnsmanagedCountries: [{ id, nativeName }].api/dbSync/entities/organization.jsruns.📸 Previews
No UI change. In the projection menu of the front end, groups are now labelled from
iso2throughIntl.DisplayNamesinstead of theen_namefallback.