taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit eeb3906f4f827860650ba02f1d73f979a4caec89
parent e31f18b8f129adb9cbe33158297a9cff56a7143e
Author: Florian Dold <florian@dold.me>
Date:   Tue, 12 Dec 2023 16:30:04 +0100

wallet-core: i18n-ized terms

Diffstat:
Mpackages/taler-util/src/wallet-types.ts | 9+++++++++
Mpackages/taler-wallet-core/src/operations/exchanges.ts | 28++++++++++++++++++++++------
Mpackages/taler-wallet-core/src/wallet.ts | 20++++++++++++++------
3 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts @@ -1576,6 +1576,13 @@ export interface GetExchangeTosResult { */ contentType: string; + /** + * Language of the returned content. + * + * If missing, language is unknown. + */ + contentLanguage: string | undefined; + tosStatus: ExchangeTosStatus; } @@ -1674,12 +1681,14 @@ export const codecForForceExchangeUpdateRequest = export interface GetExchangeTosRequest { exchangeBaseUrl: string; acceptedFormat?: string[]; + acceptLanguage?: string; } export const codecForGetExchangeTosRequest = (): Codec<GetExchangeTosRequest> => buildCodecForObject<GetExchangeTosRequest>() .property("exchangeBaseUrl", codecForString()) .property("acceptedFormat", codecOptional(codecForList(codecForString()))) + .property("acceptLanguage", codecOptional(codecForString())) .build("GetExchangeTosRequest"); export interface AcceptManualWithdrawalRequest { diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -122,29 +122,39 @@ interface ExchangeTosDownloadResult { tosText: string; tosEtag: string; tosContentType: string; + tosContentLanguage: string | undefined; } async function downloadExchangeWithTermsOfService( exchangeBaseUrl: string, http: HttpRequestLibrary, timeout: Duration, - contentType: string, + acceptFormat: string, + acceptLanguage: string | undefined, ): Promise<ExchangeTosDownloadResult> { - logger.trace(`downloading exchange tos (type ${contentType})`); + logger.trace(`downloading exchange tos (type ${acceptFormat})`); const reqUrl = new URL("terms", exchangeBaseUrl); - const headers = { - Accept: contentType, + const headers: { + Accept: string; + "Accept-Language"?: string; + } = { + Accept: acceptFormat, }; + if (acceptLanguage) { + headers["Accept-Language"] = acceptLanguage; + } + const resp = await http.fetch(reqUrl.href, { headers, timeout, }); const tosText = await readSuccessResponseTextOrThrow(resp); const tosEtag = resp.headers.get("etag") || "unknown"; + const tosContentLanguage = resp.headers.get("content-language") || undefined; const tosContentType = resp.headers.get("content-type") || "text/plain"; - return { tosText, tosEtag, tosContentType }; + return { tosText, tosEtag, tosContentType, tosContentLanguage }; } /** @@ -572,9 +582,10 @@ async function downloadTosFromAcceptedFormat( baseUrl: string, timeout: Duration, acceptedFormat?: string[], + acceptLanguage?: string, ): Promise<ExchangeTosDownloadResult> { let tosFound: ExchangeTosDownloadResult | undefined; - //Remove this when exchange supports multiple content-type in accept header + // Remove this when exchange supports multiple content-type in accept header if (acceptedFormat) for (const format of acceptedFormat) { const resp = await downloadExchangeWithTermsOfService( @@ -582,6 +593,7 @@ async function downloadTosFromAcceptedFormat( ws.http, timeout, format, + acceptLanguage, ); if (resp.tosContentType === format) { tosFound = resp; @@ -597,6 +609,7 @@ async function downloadTosFromAcceptedFormat( ws.http, timeout, "text/plain", + acceptLanguage, ); } @@ -1144,6 +1157,7 @@ export async function getExchangeTos( ws: InternalWalletState, exchangeBaseUrl: string, acceptedFormat?: string[], + acceptLanguage?: string, ): Promise<GetExchangeTosResult> { // FIXME: download ToS in acceptable format if passed! const { exchange, exchangeDetails } = await fetchFreshExchange( @@ -1156,6 +1170,7 @@ export async function getExchangeTos( exchangeBaseUrl, getExchangeRequestTimeout(), acceptedFormat, + acceptLanguage, ); await ws.db @@ -1173,6 +1188,7 @@ export async function getExchangeTos( currentEtag: tosDownload.tosEtag, content: tosDownload.tosText, contentType: tosDownload.tosContentType, + contentLanguage: tosDownload.tosContentLanguage, tosStatus: getExchangeTosStatusFromRecord(exchange), }; } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -187,6 +187,7 @@ import { getBalanceDetail, getBalances } from "./operations/balance.js"; import { TaskIdentifiers, TaskRunResult, + TaskRunResultType, makeExchangeListItem, runTaskWithErrorReporting, } from "./operations/common.js"; @@ -511,11 +512,13 @@ async function runTaskLoop( const res = await runTaskWithErrorReporting(ws, p.id, async () => { return await callOperationHandler(ws, p); }); - ws.notify({ - type: NotificationType.PendingOperationProcessed, - id: p.id, - taskResultType: res.type, - }); + if (!(ws.stopped && res.type === TaskRunResultType.Error)) { + ws.notify({ + type: NotificationType.PendingOperationProcessed, + id: p.id, + taskResultType: res.type, + }); + } if (ws.stopped) { ws.isTaskLoopRunning = false; return { @@ -1106,7 +1109,12 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( } case WalletApiOperation.GetExchangeTos: { const req = codecForGetExchangeTosRequest().decode(payload); - return getExchangeTos(ws, req.exchangeBaseUrl, req.acceptedFormat); + return getExchangeTos( + ws, + req.exchangeBaseUrl, + req.acceptedFormat, + req.acceptLanguage, + ); } case WalletApiOperation.GetContractTermsDetails: { const req = codecForGetContractTermsDetails().decode(payload);