Skip to content

Commit b95c94c

Browse files
authored
fix(project): use display fallback (#1129)
* fix(api): include source language targets Treat the conversation or project source display language as part of the configured content translation target set when scheduling eager translation work. This makes eager scheduling match on-demand translation availability and queues translations such as Russian/Kyrgyz seed opinions into English when English is the conversation display language. Apply the same target-set rule in the import worker because imported conversations create content translation work directly instead of going through the API scheduler. Deploy: api, import-worker * fix(agora): preserve inherited languages Edit conversations that inherit project language settings now load and save with the same inherited/override model used during conversation creation. Changes: - Return language settings source and listed project language metadata from the edit endpoint - Reuse the project language settings control on the edit page when project metadata is available - Preserve project_inherited on save unless the user switches to a conversation override - Keep update request and generated API contract/client types in sync Deploy: agora, api * fix(math-updater): compare language enums safely Avoid comparing display_language_code and spoken_language_code columns directly in AI description translation work queries. PostgreSQL does not define equality between distinct enum types, which caused expired translation work recovery and first-pass resume paths to fail. Build matching display/spoken enum pairs instead, so each SQL predicate compares an enum column with a value of the same enum type. Add a regression test covering the supported eager translation pair mapping. Deploy: math-updater * feat(project): add machine translation Add project pages to the existing content translation flow so listed projects can lazily request and display machine translations when dynamic translation is enabled and the target language is configured. Product behavior: - Manual project localizations remain native-quality content and do not show the translation toggle. - Machine translations expose original and translated variants, defaulting based on whether the viewer understands the source language. - Missing or failed machine translations can be retried from the project page with Show translation. - Completed project translation events update the relevant cached project content without refetching the whole project page. Implementation details: - Add project as a content translation subject with project localized content DTOs and OpenAPI output. - Return project body as sanitized-rendered HTML via bodyHtml plus originalContent and optional machineTranslation metadata. - Queue project content translation work through the existing content translation service and availability checks. - Add shared SSE topic builders and a project translation topic for realtime updates. - Use generated content translation client calls from the frontend and patch project page cache on retry or SSE completion. - Update dev project page fixtures and translation preview subject handling for project subjects. Verification: - cd services/agora && pnpm exec vue-tsc --noEmit - cd services/agora && pnpm lint - cd services/api && pnpm typecheck Deploy: agora, api * fix(project): use display fallback Resolve project and conversation dynamic content using the user's display-language fallback chain on the backend. Changes: - add a shared display-language fallback chain and generic preferred-content resolver - remove project-specific display-language persistence and API state - make the project language selector update the global display language while showing all display languages with project-supported options first - resolve project activity card translations per conversation instead of with a project-level language - regenerate shared DTOs, OpenAPI clients, and the table-drop migration Deploy: agora, api
1 parent 13d590e commit b95c94c

100 files changed

Lines changed: 19210 additions & 1491 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

services/agora/src/App.vue

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ import { isNetworkOffline } from "./composables/useNetworkStatus";
3131
import { useRealtimeSSE } from "./composables/useRealtimeSSE";
3232
import { useZupassVerification } from "./composables/zupass/useZupassVerification";
3333
import PersistentLayout from "./layouts/PersistentLayout.vue";
34+
import { ZodSupportedDisplayLanguageCodes } from "./shared/languages";
35+
import {
36+
buildContentTranslationTopic,
37+
buildProjectContentTranslationTopic,
38+
} from "./shared/types/dto";
3439
import { useLanguageStore } from "./stores/language";
3540
import { useBackendAuthApi } from "./utils/api/auth";
3641
import { useHtmlNodeCssPatch } from "./utils/css/htmlNodeCssPatch";
@@ -63,14 +68,42 @@ const realtimeConversationSlugId = computed(() => {
6368
6469
return getSingleRouteParam(route.params.postSlugId) || undefined;
6570
});
71+
const realtimeProjectSlug = computed(() => {
72+
if (String(route.name ?? "") !== "/project/[projectSlug]") {
73+
return undefined;
74+
}
75+
76+
if (!("projectSlug" in route.params)) {
77+
return undefined;
78+
}
79+
80+
return getSingleRouteParam(route.params.projectSlug) || undefined;
81+
});
6682
const realtimeTopics = computed(() => {
67-
if (realtimeConversationSlugId.value === undefined) {
68-
return [];
83+
const topics: string[] = [];
84+
if (realtimeConversationSlugId.value !== undefined) {
85+
topics.push(
86+
buildContentTranslationTopic({
87+
conversationSlugId: realtimeConversationSlugId.value,
88+
targetLanguageCode: languageStore.displayLanguage,
89+
})
90+
);
91+
}
92+
93+
const projectSlug = realtimeProjectSlug.value;
94+
if (projectSlug !== undefined) {
95+
topics.push(
96+
...ZodSupportedDisplayLanguageCodes.options.map(
97+
(languageCode) =>
98+
buildProjectContentTranslationTopic({
99+
projectSlug,
100+
targetLanguageCode: languageCode,
101+
})
102+
)
103+
);
69104
}
70105
71-
return [
72-
`translation:conversation:${realtimeConversationSlugId.value}:target:${languageStore.displayLanguage}`,
73-
];
106+
return topics;
74107
});
75108
76109
// Initialize SSE for real-time events after auth initialization.

services/agora/src/api/.openapi-generator/FILES

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,15 @@ docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf2ContentAnyOf2.md
111111
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf2ContentAnyOf2Variants.md
112112
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf2ContentAnyOfVariants.md
113113
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3.md
114+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3Content.md
115+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3ContentAnyOf.md
116+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3ContentAnyOf1.md
117+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3ContentAnyOf1Variants.md
118+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3ContentAnyOf2.md
119+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3ContentAnyOf2Variants.md
120+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf3ContentAnyOfVariants.md
114121
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf4.md
122+
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOf5.md
115123
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOfContent.md
116124
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOfContentAnyOf.md
117125
docs/ApiV1ContentTranslationRequestPost200ResponseAnyOfContentAnyOf1.md
@@ -130,6 +138,7 @@ docs/ApiV1ContentTranslationRequestPostRequestSubject.md
130138
docs/ApiV1ContentTranslationRequestPostRequestSubjectOneOf.md
131139
docs/ApiV1ContentTranslationRequestPostRequestSubjectOneOf1.md
132140
docs/ApiV1ContentTranslationRequestPostRequestSubjectOneOf2.md
141+
docs/ApiV1ContentTranslationRequestPostRequestSubjectOneOf3.md
133142
docs/ApiV1ConversationClosePost200Response.md
134143
docs/ApiV1ConversationClosePost200ResponseOneOf.md
135144
docs/ApiV1ConversationClosePost200ResponseOneOf1.md
@@ -314,9 +323,6 @@ docs/ApiV1ProjectCreateOptionsListPost200ResponseOneOfProjectListInner.md
314323
docs/ApiV1ProjectCreateOptionsListPost200ResponseOneOfProjectListInnerLanguageSettings.md
315324
docs/ApiV1ProjectCreateOptionsListPostRequest.md
316325
docs/ApiV1ProjectPageActivitiesFetchPost200Response.md
317-
docs/ApiV1ProjectPageActivitiesFetchPostRequest.md
318-
docs/ApiV1ProjectPageDisplayLanguageUpdatePost200Response.md
319-
docs/ApiV1ProjectPageDisplayLanguageUpdatePostRequest.md
320326
docs/ApiV1ProjectPageFetchPost200Response.md
321327
docs/ApiV1ProjectPageFetchPost200ResponseActivitiesInner.md
322328
docs/ApiV1ProjectPageFetchPost200ResponseActivitiesInnerStats.md
@@ -325,6 +331,8 @@ docs/ApiV1ProjectPageFetchPost200ResponseNextActivityCursor.md
325331
docs/ApiV1ProjectPageFetchPost200ResponseProject.md
326332
docs/ApiV1ProjectPageFetchPost200ResponseProjectAttributionsInner.md
327333
docs/ApiV1ProjectPageFetchPost200ResponseProjectContact.md
334+
docs/ApiV1ProjectPageFetchPost200ResponseProjectMachineTranslation.md
335+
docs/ApiV1ProjectPageFetchPost200ResponseProjectOriginalContent.md
328336
docs/ApiV1ProjectPageFetchPostRequest.md
329337
docs/ApiV1ProjectPageFetchPostRequestActivityCursor.md
330338
docs/ApiV1ReportConversationCreatePostRequest.md

0 commit comments

Comments
 (0)