What's changed
Features (10)
-
accountSettings: add UI for token regeneration (#7125)
Allow regenerating the API Key (token) in the "Security" section of the
"Account Settings" UI. -
asset: add created by to API (#7094)
Add
created_byto the asset API responses.Update the asset list and detail endpoints with a new
created_byfield
containing the username of the asset's creator. -
auth: environment internal endpoint openapi docs (#6978)
Added
/environmentendpoint to the OpenAPI docsCreated EnvironmentResponseSerializer (along with SocialAppSerializer
and MetadataFieldSerializer) to explicitly type out all configuration
properties. Added markdown documentation describing what the endpoint
provides. The view get() method was then decorated with @extend_schema
to formally document the endpoint using Kobo's standardized
open_api_200_ok_response format, and added APIV2Versioning so the V2
schema generator picks it up. -
bulkProcessing: mark in progress cells (#7055)
Marks Project → Data → Table cells as in progress when a bulk action is
undergoing. This change is hidden behind a feature flag. -
bulkProcessing: dismissible info banner (#7092)
On the Data Table, we show a dismissible info banner when bulk
processing is actively running and at least one active job was started
by a different user, so data changes are easier to anticipate. This is
hidden behind feature flag. -
dataTable: add processing columns (#7065)
Display transcription/translation columns even if there is no data, but
bulk processes are in progress. This change is part of incomplete
feature, thus it is hidden behind a feature flag. -
formSummary: always display extra metadata fields in summary (#7070)
Summary now displays extra metadata fields even with the value is null
or empty -
frontend: create a reflux to react-query (orval) bridge (#7040)
-
nlp: implement Google API US/EU region routing for Speech-to-Text and Translation (#7128)
This PR implements the server-wide Google ASR/MT location setting to
enforce strict EU data residency or utilize global US infrastructure for
Speech-to-Text (v2) and Translation (v3) APIs.Following the parallel switch to Google Cloud Speech-to-Text v2 and
Translation v3, the previous ASR/MT region control setting (from
) was no longer functional. This PR re-establishes the
server-wide US/EU location toggle and ensures requests are routed to the
correct regional or global endpoints based on that configuration.Speech-to-Text (ASR) Updates:
- The Google location is dynamically set to
usoreudepending on
the server-wideASR_MT_GOOGLE_REGIONsetting.
Translation (MT) Updates:
- EU traffic is explicitly routed through the dedicated
translate-eu.googleapis.commulti-regional gateway and processed in
europe-west1. This guarantees that TLS termination, processing, and
data-in-transit remain entirely within European borders. - US traffic is routed through
translate-us.googleapis.com+
us-west1.
Constance setting:
- Consolidated the legacy
ASR_MT_GOOGLE_TRANSLATION_LOCATIONsetting
(which tracked granular locations likeus-central1oreurope-west1)
into a newASR_MT_GOOGLE_REGIONConstance setting that provides a
straightforward US or EU toggle.
Region code fallback fix (pre-existing bug):
TranscriptionService.get_language_code()andget_configuration()
previously raisedLanguageNotSupportedfor any region code not
explicitly listed in the database (e.g.fr-BE,de-AT). The check
language_set.filter(code='fr-BE')always returned false because
fr-BEis a region code, not a language code.- Fixed: both methods now extract the parent language code (
frfrom
fr-BE) as a fallback. If the parent language is supported, the
original region code is passed through to Google STT unchanged, allowing
it to apply the best available model for that regional variant.
- The Google location is dynamically set to
-
nlp: ensure maximum language support with per-language STT routing and GLOBAL/EU toggle (#7154)
Extends the Google ASR/MT location handling from
kpi#7128 to support
every language Google offers. Instead of a fixedus/euendpoint for
all languages, the code now routes each language to whichever Google
endpoint hosts its best available model. A newGLOBAL/EUConstance
toggle replaces the oldUS/EUtoggle:GLOBAL(default) uses
per-language routing for maximum coverage;EUrestricts all processing
to EU-hosted endpoints for data residency compliance.kpi#7128 re-implemented
the server-wide Google ASR/MT region setting (ASR_MT_GOOGLE_REGION)
and simplified routing to use a single fixed location:usfor all
languages on non-EU servers andeuon EU servers.However, this caused 24 languages to lose ASR support, languages like
Irish, Belarusian, Bosnian, and Somali that only havechirp_2model
support in specific Google sub-regions (us-central1,europe-west4)
and no model at all in theus/eumulti-region endpoints.Because we cannot lose support for these 24 languages, we decided to
implement the following approach instead:- Global mode (default): Support every language that Google supports by
routing each language to the endpoint that provides the best available
model. - EU mode: Use the best available model within EU-hosted endpoints
only. Languages that are not available in any EU endpoint are considered
unsupported on EU servers.
In
GLOBALmode, the code readslocation_codeper language from the
database (populated by the language spreadsheet, which stores the
correct global location for each model). In EU mode, the code overrides
the DB location at runtime using the table above via
EU_LOCATION_BY_MODELinlocations.py. - Global mode (default): Support every language that Google supports by
Bug Fixes (4)
-
assets: fix deletion of projects with long names (#7147)
Fixes a bug that was causing errors when users tried to delete a project
with a particularly long name. -
frontend: ensure proper hash navigation in few components (#6999)
Clicking the app logo, the "Back to REST Services" button, or the "See
plans" link no longer reloads the whole page. -
languages: correct Orval-generated types for language services fields and LanguagesListParams (#7067)
This PR corrects two OpenAPI schema inaccuracies in the language
endpoints that caused incorrect Orval-generated TypeScript types for the
frontend.This PR addresses two schema issues reported by the frontend against the
language API endpoints.Issue 1: Incorrect schema for
transcription_services/
translation_serviceson the retrieve endpointThe list (
/api/v2/languages/) and retrieve
(/api/v2/languages/{code}/) endpoints return different shapes for the
services fields, but both serializers were annotated with the same
@extend_schema_field(ServicesField), causing drf-spectacular to emit
one schema for both, which matched only the list endpoint. This led
Orval to generate an incorrect array type for the retrieve endpoint's
response.This is resolved by introducing a dedicated
ServicesDetailFieldmarker
class and a correspondingServicesDetailFieldExtensionthat emits the
correct nested-object schema ({ [serviceCode]: { [regionCode]: string } }).LanguageSerializer(retrieve) is updated to useServicesDetailField,
whileLanguageListSerializer(list) continues to use the existing
ServicesField.Issue 2: Missing
qquery parameter inLanguagesListParamsThe
LanguageViewSetrelied onBaseViewSet'sSearchFilterbackend
to handle theqparameter at runtime, but drf-spectacular requires
explicitOpenApiParameterdeclarations to include query params in the
schema. As a result,qwas absent from the generated
LanguagesListParamstype, forcing the frontend to cast hook calls with
as any. This is resolved by adding an explicit
OpenApiParameter(name='q', ...)declaration to thelistaction
schema, consistent with the pattern already used in
TranscriptionServiceViewSet. -
qual: export qual questions correctly (#7124)
Fixes the qualitative manual multiple select data export
The one hot data export for manual qualitative multiple select data was
fixed on formpack.
Inimport_export_task.py, the
SubmissionExportTaskBase.get_export_objectwe pass for_output=True
down toget_submissionsin order to resolve the choice UUIDs into
their corresponding human-readable labels. We have also added_uuid
andmeta/rootUuidto the additional_fields list in
_get_fields_and_groups()to retrieve the qualitative payload
correctly.
Documentation (1)
- Add DPG Badge to README (#7071)
This PR includes the new DPG badge in the README file, following the
guide,
and links to KoboToolbox's new profile page on the DPG
Registry.
Continous Integration (1)
- openapi: fail CI job on drf-spectacular error (#7097)
Refactor (10)
-
formLanguagesManager: improve flaky tests (#7091)
Improve form language manager Storybook tests
-
frontend: drop react-debounced-input in favor of mantine based component (#7019)
-
frontend: migrate Languages/Translations modal to Mantine and react-query (#7042)
Migrates the project languages and translations modal interface to Mantine components and react-query
-
frontend: remove react-tagsinput in favor of Mantine-powered in-house component (#7089)
Project and library tag inputs now use Kobo’s Mantine-based
TagsInput,
which keeps tag editing working while removing the legacy
react-tagsinputdependency. -
languageSelector: update and replace old language selector (#7039)
Update old language selector into a new component
-
library: mantineify upload modal (#7101)
-
libraryAssetForm: remove mixins (#7068)
-
libraryAssetForm: migrate to TypeScript (#7069)
-
libraryAssetForm: change component to functional and use proper metadata (#7072)
Library asset create and edit forms now fully honor instance-configured
project metadata fields, and the select controls used in that form were
modernized and stabilized (new shared Select and MultiSelect wrappers,
Mantine input migration, shared theme base styles, and UI parity fixes).Until now, the create/edit form for library templates and collections
rendered a fixed set of metadata fields (description, sector, country)
regardless of what the instance had configured. If an admin disabled one
of those, it still showed up; if they enabledoperational_purpose,
collects_pii, or any custom extra metadata field, it was nowhere to be
found. The form now behaves the same way Project Settings already does
and renders exactly the fields the environment exposes. -
regionSelector: update and replace old region selector (#7073)
Updates the region selector UI in the automated
transcription/translation step
Chores (4)
-
api: [breaking] remove all legacy v1 API endpoints (#7098)
The legacy
/api/v1/API has been fully removed. Requests to removed
endpoints now receive an HTTP 410 Gone response with a link to the
migration guide.All remaining
/api/v1/endpoints have been removed:/api/v1/user,/api/v1/users/api/v1/notes/api/v1/forms,/api/v1/formlist/api/v1/data(submissions, metadata, media)/api/v1/briefcase- KPI v1 endpoints
Any request to a removed endpoint returns HTTP 410 Gone (HTML, JSON,
XML depending onAcceptheader) with a link to the migration article:
https://support.kobotoolbox.org/migrating_api.html -
deps: remove temporary Python pins (#6829)
-
github: update PR checklist (#7100)
-
security: add vulnerability reporting policy (#7082)
Add
SECURITY.mdfile with link to KoboToolbox Vulnerability Reporting
Policy.
Full Changelog: https://github.com/kobotoolbox/kpi/compare/2.026.21c..2.026.23