From 1c307bf06583e7ebc2ba88b8c483a578a25a21dc Mon Sep 17 00:00:00 2001 From: Jonathan Payne Date: Tue, 13 Oct 2026 12:45:39 -0400 Subject: [PATCH] OpenConceptLab/ocl_issues#2902 | Load the Locales catalog from the cached lookup endpoint fetchOclLocales listed /orgs/OCL/sources/Locales/concepts/?limit=500 on every project open: 486 full rows, 421 KB, about 6 s in production. The lookup endpoint returns the same 184 locale/display_name pairs in 56 KB and about 0.3 s, and the API caches it for 24 hours, as fetchMapTypes already uses. closes OpenConceptLab/ocl_issues#2902 Co-Authored-By: Claude Opus 5.5 --- src/components/map-projects/MapProject.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/map-projects/MapProject.jsx b/src/components/map-projects/MapProject.jsx index 34f7be59..7882629e 100644 --- a/src/components/map-projects/MapProject.jsx +++ b/src/components/map-projects/MapProject.jsx @@ -968,14 +968,18 @@ const MapProject = () => { // PR3-H: fetch the canonical locale catalog from /orgs/OCL/sources/Locales/. // ~486 concepts, each mapping a 3-letter ISO 639-3 id to a 2-letter BCP-47 - // `locale` and human-readable `display_name`. Concepts missing a `locale` + // `locale` and human-readable `display_name`. Like fetchMapTypes, this reads + // the lookup endpoint, which returns only those fields and which the API + // caches for 24 hours, instead of listing full concepts on every project + // open (OpenConceptLab/ocl_issues#2902). The lookup has no `retired` field; + // the source has no retired concepts. Concepts missing a `locale` // (e.g. macro-language groupings like "Creoles and pidgins") are filtered // out so the dropdown only offers usable filter values. The list is // sorted alphabetically by display name (English collation) to match the // convention used by browser/OS language pickers. On fetch failure the // state keeps the initial fallback list. - const fetchOclLocales = () => APIService.orgs('OCL').sources('Locales').appendToUrl('concepts/').get(null, null, {limit: 500}).then(response => { - const valid = (response?.data || []).filter(c => c?.locale && !c?.retired) + const fetchOclLocales = () => APIService.orgs('OCL').sources('Locales').appendToUrl('concepts/lookup/').get(null, null, {verbose: true}).then(response => { + const valid = (response?.data || []).filter(c => c?.locale) if (valid.length === 0) return const sorted = valid.map(c => ({id: c.locale, name: c.display_name})) .sort((a, b) => a.name.localeCompare(b.name, 'en'))