Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
459 changes: 91 additions & 368 deletions package-lock.json

Large diffs are not rendered by default.

83 changes: 61 additions & 22 deletions src/app/core/http/error-handler.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Injectable, inject } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';

/** rxjs Imports */
import { EMPTY, Observable } from 'rxjs';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';

/** Environment Configuration */
Expand All @@ -20,13 +20,14 @@ import { environment } from '../../../environments/environment';
/** Custom Services */
import { Logger } from '../logger/logger.service';
import { AlertService } from '../alert/alert.service';
import { TranslateService } from '@ngx-translate/core'; // Added import for TranslateService
import { TranslateService } from '@ngx-translate/core';

/** Initialize Logger */
const log = new Logger('ErrorHandlerInterceptor');

/**
* Http Request interceptor to add a default error handler to requests.
* Supports localisation of error messages using Fineract's userMessageGlobalisationCode.
*/
@Injectable()
export class ErrorHandlerInterceptor implements HttpInterceptor {
Expand All @@ -42,60 +43,98 @@ export class ErrorHandlerInterceptor implements HttpInterceptor {

/**
* Error handler.
* Uses userMessageGlobalisationCode from Fineract error response to localise error messages.
*/
private handleError(response: HttpErrorResponse, request: HttpRequest<any>): Observable<HttpEvent<any>> {
const status = response.status;
let errorMessage = response.error.developerMessage || response.message;
if (response.error.errors) {
let errorMessage = response.error?.developerMessage || response.message;
let globalisationCode: string | null = null;

// Extract globalisation code and message from Fineract error response
if (response.error?.errors) {
if (response.error.errors[0]) {
globalisationCode = response.error.errors[0].userMessageGlobalisationCode || null;
errorMessage = response.error.errors[0].defaultUserMessage || response.error.errors[0].developerMessage;
}
}

// Also check top-level userMessageGlobalisationCode
if (response.error?.userMessageGlobalisationCode) {
globalisationCode = response.error.userMessageGlobalisationCode;
}
Comment on lines +50 to +64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't let the top-level error overwrite the nested/user-facing one.

response.error.userMessageGlobalisationCode currently replaces errors[0].userMessageGlobalisationCode, and the initial fallback starts from developerMessage. When both shapes are present, the interceptor can discard the more specific nested translation and fall back to technical English text.

🔧 Suggested fix
-    let errorMessage = response.error?.developerMessage || response.message;
+    let errorMessage =
+      response.error?.defaultUserMessage || response.error?.developerMessage || response.message;
     let globalisationCode: string | null = null;
@@
-    if (response.error?.userMessageGlobalisationCode) {
+    if (!globalisationCode && response.error?.userMessageGlobalisationCode) {
       globalisationCode = response.error.userMessageGlobalisationCode;
+      errorMessage = response.error?.defaultUserMessage || errorMessage;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 50 - 64, The
interceptor currently lets response.error.userMessageGlobalisationCode overwrite
a more-specific nested code and may have initialized errorMessage from
developerMessage before checking nested errors; update the logic in
error-handler.interceptor.ts so that you first prefer and assign nested values
(response.error.errors[0].userMessageGlobalisationCode and
.defaultUserMessage/.developerMessage) to globalisationCode and errorMessage,
and only set globalisationCode from response.error.userMessageGlobalisationCode
if globalisationCode is still null/undefined; ensure errorMessage is not
overwritten by a top-level developerMessage once a nested defaultUserMessage was
chosen.


// If we have a globalisation code, try to translate it with variable substitution
if (globalisationCode) {
const translated = this.translate.instant(globalisationCode, response.error?.errors?.[0] || response.error || {});
// Only use translation if the key actually exists (translate returns the key itself if not found)
if (translated !== globalisationCode) {
errorMessage = translated;
}
Comment on lines +67 to +72
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
# Check whether the app customizes ngx-translate parsing and how existing error keys are referenced.
rg -n -C 3 "TranslateModule\.forRoot|TranslateParser|MissingTranslationHandler|TranslateLoader" src
rg -n -C 1 "errors\.[A-Za-z0-9_.-]+" src/app

Repository: openMF/web-app

Length of output: 10304


🏁 Script executed:

cat -n src/app/core/http/error-handler.interceptor.ts | head -140

Repository: openMF/web-app

Length of output: 6766


🏁 Script executed:

fd -e json src/assets/translations | head -10

Repository: openMF/web-app

Length of output: 455


🏁 Script executed:

head -100 src/assets/translations/lt-LT.json

Repository: openMF/web-app

Length of output: 11943


🏁 Script executed:

rg -n "instant\('error\." src/app --type ts -A 1 | head -40

Repository: openMF/web-app

Length of output: 2854


🏁 Script executed:

rg -n "instant\('errors\." src/app --type ts -A 1 | head -40

Repository: openMF/web-app

Length of output: 1099


🏁 Script executed:

grep -r "error\.auth\|errors\.error\.auth" src/assets/translations/

Repository: openMF/web-app

Length of output: 2599


🏁 Script executed:

cat src/assets/translations/lt-LT.json | head -20 && cat src/assets/translations/lt-LT.json | tail -5

Repository: openMF/web-app

Length of output: 1155


🏁 Script executed:

python3 << 'EOF'
import json

with open('src/assets/translations/lt-LT.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

# Check the structure of "errors" top-level keys
errors = data.get('errors', {})
print("Keys under 'errors' object:")
for key in list(errors.keys())[:15]:
    print(f"  {key}")
    if isinstance(errors[key], dict):
        for subkey in errors[key].keys():
            print(f"    {subkey}")

print("\nTotal keys in errors:", len(errors))
EOF

Repository: openMF/web-app

Length of output: 556


🏁 Script executed:

cat -n src/app/app.module.ts | sed -n '72,76p'

Repository: openMF/web-app

Length of output: 369


🏁 Script executed:

rg -n "getTranslation|onTranslationNotFound" src/app --type ts -B 2 -A 5

Repository: openMF/web-app

Length of output: 40


Fix translation key paths in error-handler interceptor.

The hardcoded error keys on lines 84–137 are missing the errors. prefix required to match the nested structure in translation files. For example, 'error.auth.type' should be 'errors.error.auth.type', and similarly for all other hardcoded error keys (error.token.invalid.*, error.bad.request.*, error.unauthorized.*, error.resource.not.found.*, error.server.internal.*, error.resource.notImplemented.*, error.unknown.*). Without this prefix, translate.instant() will fail to resolve the keys and fall back to displaying the key name instead of the translated message. This is inconsistent with other parts of the codebase that correctly use the errors. prefix (e.g., 'errors.validationSaveError', 'errors.accountingRule.duplicateName').

The same approach used on lines 67–72 (verifying that the translation key exists before using it) should also be applied to all hardcoded error keys, or the keys should be prefixed consistently.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 67 - 72, In
src/app/core/http/error-handler.interceptor.ts the hardcoded translation keys
(e.g., 'error.auth.type', 'error.token.invalid.*', 'error.bad.request.*', etc.)
lack the required "errors." prefix and therefore fail to resolve; update all
those hardcoded keys to include the "errors." prefix (for example
'error.auth.type' -> 'errors.error.auth.type') and mirror the existing pattern
used around globalisationCode: use translate.instant(...) then verify the
returned value !== key before assigning to errorMessage (referencing
globalisationCode, translate.instant and errorMessage in the interceptor) so
only valid translations replace the fallback.

}

const isClientImage404 = status === 404 && request.url.includes('/clients/') && request.url.includes('/images');

if (!environment.production && !isClientImage404) {
log.error(`Request Error: ${errorMessage}`);
}

if (status === 401 || (environment.oauth.enabled && status === 400)) {
this.alertService.alert({ type: 'Authentication Error', message: 'Invalid User Details. Please try again!' });
} else if (status === 403 && errorMessage === 'The provided one time token is invalid') {
this.alertService.alert({ type: 'Invalid Token', message: 'Invalid Token. Please try again!' });
// Check specific 403 error (invalid token) BEFORE generic 403 (higher priority)
if (status === 403 && globalisationCode === 'error.token.invalid') {
this.alertService.alert({
type: this.translate.instant('error.token.invalid.type'),
message: this.translate.instant('error.token.invalid.message')
});
} else if (status === 401) {
// Allow Fineract translations for 401 errors
this.alertService.alert({
type: this.translate.instant('error.auth.type'),
message: errorMessage || this.translate.instant('error.auth.message')
});
} else if (environment.oauth.enabled && status === 400) {
this.alertService.alert({
type: this.translate.instant('error.auth.type'),
message: this.translate.instant('error.auth.message')
});
} else if (status === 400) {
this.alertService.alert({
type: 'Bad Request',
message: errorMessage || 'Invalid parameters were passed in the request!'
type: this.translate.instant('error.bad.request.type'),
message: errorMessage || this.translate.instant('error.bad.request.message')
});
} else if (status === 403) {
this.alertService.alert({
type: 'Unauthorized Request',
message: errorMessage || 'You are not authorized for this request!'
type: this.translate.instant('error.unauthorized.type'),
message: errorMessage || this.translate.instant('error.unauthorized.message')
});
} else if (status === 404) {
// Check if this is an image request that should be silently handled (client profile image)
if (isClientImage404) {
// Don't show alerts for missing client images
// This is an expected condition, not an error
return EMPTY;
// Return observable of null for missing client images so imaging service can handle gracefully
return new Observable((observer) => {
observer.next(null);
observer.complete();
});
Comment on lines 109 to +114
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Angular HttpInterceptor, if the goal is to let downstream request handlers process a 404, should the interceptor rethrow with throwError(() => response)instead of emittingnullfromintercept()?

💡 Result:

Yes, if the goal is to let downstream request handlers (services, components) process the 404 error via their error callbacks, the interceptor should rethrow using throwError( => response) (or throwError(response) in older RxJS) from within catchError, rather than emitting null (e.g., via of(null)) from intercept. Emitting null or any value completes the observable successfully, so subscribers receive it in the next handler and the error callback is never triggered. Rethrowing propagates the original HttpErrorResponse, triggering error callbacks downstream. Example in interceptor: return next.handle(req).pipe( catchError((error: HttpErrorResponse) => { // Optional: log or handle 404 specifically without consuming if (error.status === 404) { console.log('404 intercepted but propagating'); } return throwError( => error); }) ); This pattern is standard for error-passing interceptors, as shown in official Angular docs and RxJS error handling guides.

Citations:


🏁 Script executed:

#!/bin/bash
# Find and examine the error-handler.interceptor.ts file
fd "error-handler.interceptor.ts" src/

Repository: openMF/web-app

Length of output: 104


🏁 Script executed:

#!/bin/bash
# Read the error-handler.interceptor.ts file to see the context around lines 109-114
if [ -f "src/app/core/http/error-handler.interceptor.ts" ]; then
  wc -l "src/app/core/http/error-handler.interceptor.ts"
fi

Repository: openMF/web-app

Length of output: 108


🏁 Script executed:

#!/bin/bash
# Get context around lines 109-114, including imports and broader error handling
cat -n "src/app/core/http/error-handler.interceptor.ts" | head -150

Repository: openMF/web-app

Length of output: 6786


Rethrow the 404 instead of emitting null to let the image service handle the error.

Returning a successful observable with null swallows the error and prevents downstream error handlers from seeing the 404. To allow the image service to decide how to handle missing client images, rethrow the error using throwError().

🔧 Suggested fix
-import { Observable } from 'rxjs';
+import { Observable, throwError } from 'rxjs';
@@
-        return new Observable((observer) => {
-          observer.next(null);
-          observer.complete();
-        });
+        return throwError(() => response);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 109 - 114, The
current branch where isClientImage404 returns a successful Observable with null
swallows the original 404; instead rethrow the original error so downstream
image service can handle it. Replace the return new Observable(...) in the
isClientImage404 branch with a rethrow using throwError(() => err) (or
throwError(() => originalError)) so the interceptor emits the error rather than
a null value; keep the isClientImage404 condition and use the same err reference
available in the interceptor's catch block.

} else {
this.alertService.alert({
type: this.translate.instant('error.resource.not.found'),
message: errorMessage || 'Resource does not exist!'
type: this.translate.instant('error.resource.not.found.type'),
message: errorMessage || this.translate.instant('error.resource.not.found.message')
});
}
} else if (status === 500) {
// Allow Fineract translations for 500 errors
this.alertService.alert({
type: 'Internal Server Error',
message: 'Internal Server Error. Please try again later.'
type: this.translate.instant('error.server.internal.type'),
message: errorMessage || this.translate.instant('error.server.internal.message')
});
} else if (status === 501) {
// Allow Fineract translations for 501 errors
this.alertService.alert({
type: this.translate.instant('error.resource.notImplemented.type'),
message: this.translate.instant('error.resource.notImplemented.message')
message: errorMessage || this.translate.instant('error.resource.notImplemented.message')
});
} else {
this.alertService.alert({ type: 'Unknown Error', message: 'Unknown Error. Please try again later.' });
this.alertService.alert({
type: this.translate.instant('error.unknown.type'),
message: this.translate.instant('error.unknown.message')
Comment on lines 133 to +136
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep the resolved backend message in the catch-all branch.

The else branch always shows the generic unknown message, so any localized defaultUserMessage / translated userMessageGlobalisationCode is thrown away for statuses like 409, 422, or 503.

🔧 Suggested fix
     } else {
       this.alertService.alert({
         type: this.translate.instant('error.unknown.type'),
-        message: this.translate.instant('error.unknown.message')
+        message: errorMessage || this.translate.instant('error.unknown.message')
       });
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else {
this.alertService.alert({ type: 'Unknown Error', message: 'Unknown Error. Please try again later.' });
this.alertService.alert({
type: this.translate.instant('error.unknown.type'),
message: this.translate.instant('error.unknown.message')
} else {
this.alertService.alert({
type: this.translate.instant('error.unknown.type'),
message: errorMessage || this.translate.instant('error.unknown.message')
});
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 133 - 136, The
catch-all else branch currently discards any resolved backend message and always
uses the generic unknown message; update the else branch in the error-handling
flow (the code that calls alertService.alert and translate.instant) to prefer
the resolved backend message (e.g. the previously-derived defaultUserMessage or
the translated userMessageGlobalisationCode) when present, and only fall back to
translate.instant('error.unknown.message') if no backend message exists; ensure
you use the same translation helper (translate.instant) for the globalization
code path and pass that resolved string into alertService.alert's message field.

});
}

throw response;
Expand Down
14 changes: 14 additions & 0 deletions src/assets/translations/cs-CS.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
"Remember me": "Zapamatuj si mě",
"error.resource.notImplemented.type": "Nenaimplementovaná chyba",
"error.resource.notImplemented.message": "Funkce není implementována!",
"error.auth.type": "Chyba ověřování",
"error.auth.message": "Neplatné údaje o uživateli. Zkuste prosím znovu!",
"error.token.invalid.type": "Neplatný token",
"error.token.invalid.message": "Neplatný token. Zkuste prosím znovu!",
"error.bad.request.type": "Špatný požadavek",
"error.bad.request.message": "V požadavku byly předány neplatné parametry!",
"error.unauthorized.type": "Neautorizovaný požadavek",
"error.unauthorized.message": "Nemáte oprávnění pro tento požadavek!",
"error.resource.not.found.type": "Zdroj nenalezen",
"error.resource.not.found.message": "Zdroj neexistuje!",
"error.server.internal.type": "Interní chyba serveru",
"error.server.internal.message": "Interní chyba serveru. Zkuste prosím později.",
"error.unknown.type": "Neznámá chyba",
"error.unknown.message": "Neznámá chyba. Zkuste prosím později.",
"errors": {
"accountingRule": {
"duplicateName": "Omlouváme se, ale účetní pravidlo s tímto názvem již existuje."
Expand Down
14 changes: 14 additions & 0 deletions src/assets/translations/de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
"Remember me": "Erinnere dich an mich",
"error.resource.notImplemented.type": "Nicht implementierter Fehler",
"error.resource.notImplemented.message": "Nicht implementierte Funktion!",
"error.auth.type": "Authentifizierungsfehler",
"error.auth.message": "Ungültige Benutzerdetails. Bitte versuchen Sie es erneut!",
"error.token.invalid.type": "Ungültiger Token",
"error.token.invalid.message": "Ungültiger Token. Bitte versuchen Sie es erneut!",
"error.bad.request.type": "Ungültige Anfrage",
"error.bad.request.message": "Ungültige Parameter wurden in der Anfrage übergeben!",
"error.unauthorized.type": "Unbefugte Anfrage",
"error.unauthorized.message": "Sie sind nicht berechtigt für diese Anfrage!",
"error.resource.not.found.type": "Ressource nicht gefunden",
"error.resource.not.found.message": "Die Ressource existiert nicht!",
"error.server.internal.type": "Interner Serverfehler",
"error.server.internal.message": "Interner Serverfehler. Bitte versuchen Sie es später erneut.",
"error.unknown.type": "Unbekannter Fehler",
"error.unknown.message": "Unbekannter Fehler. Bitte versuchen Sie es später erneut.",
"errors": {
"accountingRule": {
"duplicateName": "Entschuldigung, aber eine Buchungsregel mit diesem Namen existiert bereits."
Expand Down
14 changes: 14 additions & 0 deletions src/assets/translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
"Remember me": "Remember me",
"error.resource.notImplemented.type": "Not Implemented Error",
"error.resource.notImplemented.message": "Not implemented functionality!",
"error.auth.type": "Authentication Error",
"error.auth.message": "Invalid User Details. Please try again!",
"error.token.invalid.type": "Invalid Token",
"error.token.invalid.message": "Invalid Token. Please try again!",
"error.bad.request.type": "Bad Request",
"error.bad.request.message": "Invalid parameters were passed in the request!",
"error.unauthorized.type": "Unauthorized Request",
"error.unauthorized.message": "You are not authorized for this request!",
"error.resource.not.found.type": "Resource Not Found",
"error.resource.not.found.message": "Resource does not exist!",
"error.server.internal.type": "Internal Server Error",
"error.server.internal.message": "Internal Server Error. Please try again later.",
"error.unknown.type": "Unknown Error",
"error.unknown.message": "Unknown Error. Please try again later.",
"errors": {
"accountingRule": {
"duplicateName": "Sorry, but an Accounting Rule with this Name exists already."
Expand Down
14 changes: 14 additions & 0 deletions src/assets/translations/es-CL.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
},
"error.resource.notImplemented.type": "Error no implementado",
"error.resource.notImplemented.message": "¡Funcionalidad no implementada!",
"error.auth.type": "Error de autenticación",
"error.auth.message": "Datos de usuario inválidos. ¡Por favor, inténtelo de nuevo!",
"error.token.invalid.type": "Token inválido",
"error.token.invalid.message": "Token inválido. ¡Por favor, inténtelo de nuevo!",
"error.bad.request.type": "Solicitud incorrecta",
"error.bad.request.message": "Se enviaron parámetros no válidos en la solicitud.",
"error.unauthorized.type": "Solicitud no autorizada",
"error.unauthorized.message": "No está autorizado para esta solicitud.",
"error.resource.not.found.type": "Recurso no encontrado",
"error.resource.not.found.message": "¡El recurso no existe!",
"error.server.internal.type": "Error interno del servidor",
"error.server.internal.message": "Error interno del servidor. Por favor, inténtelo más tarde.",
"error.unknown.type": "Error desconocido",
"error.unknown.message": "Error desconocido. Por favor, inténtelo más tarde.",
"linkedSavingsAccountOwnership": "La cuenta de ahorro vinculada no pertenece al cliente seleccionado.",
"clientNotInGSIM": "El cliente con ID {{id}} no está presente en GSIM.",
"Capitalized Income amount adjusted already adjusted": "Monto de Ingreso Capitalizado ajustado ya ajustado",
Expand Down
14 changes: 14 additions & 0 deletions src/assets/translations/es-MX.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
},
"error.resource.notImplemented.type": "Error no implementado",
"error.resource.notImplemented.message": "¡Funcionalidad no implementada!",
"error.auth.type": "Error de autenticación",
"error.auth.message": "Datos de usuario inválidos. ¡Por favor, inténtelo de nuevo!",
"error.token.invalid.type": "Token inválido",
"error.token.invalid.message": "Token inválido. ¡Por favor, inténtelo de nuevo!",
"error.bad.request.type": "Solicitud incorrecta",
"error.bad.request.message": "Se enviaron parámetros no válidos en la solicitud.",
"error.unauthorized.type": "Solicitud no autorizada",
"error.unauthorized.message": "No está autorizado para esta solicitud.",
"error.resource.not.found.type": "Recurso no encontrado",
"error.resource.not.found.message": "¡El recurso no existe!",
"error.server.internal.type": "Error interno del servidor",
"error.server.internal.message": "Error interno del servidor. Por favor, inténtelo más tarde.",
"error.unknown.type": "Error desconocido",
"error.unknown.message": "Error desconocido. Por favor, inténtelo más tarde.",
"linkedSavingsAccountOwnership": "La cuenta de ahorro vinculada no pertenece al cliente seleccionado.",
"clientNotInGSIM": "El cliente con ID {{id}} no está presente en GSIM.",
"Capitalized Income amount adjusted already adjusted": "Monto de Ingreso Capitalizado ajustado ya ajustado",
Expand Down
15 changes: 14 additions & 1 deletion src/assets/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@
},
"error.resource.notImplemented.type": "Erreur non implémentée",
"error.resource.notImplemented.message": "Fonctionnalité non implémentée !",
"linkedSavingsAccountOwnership": "Le compte d'épargne lié n'appartient pas au client sélectionné.",
"error.auth.type": "Erreur d'authentification",
"error.auth.message": "Détails utilisateur invalides. Veuillez réessayer!",
"error.token.invalid.type": "Token invalide",
"error.token.invalid.message": "Token invalide. Veuillez réessayer!",
"error.bad.request.type": "Mauvaise demande",
"error.bad.request.message": "Des paramètres invalides ont été transmis dans la demande!",
"error.unauthorized.type": "Demande non autorisée",
"error.unauthorized.message": "Vous n'êtes pas autorisé pour cette demande!",
"error.resource.not.found.type": "Ressource non trouvée",
"error.resource.not.found.message": "La ressource n'existe pas!",
"error.server.internal.type": "Erreur interne du serveur",
"error.server.internal.message": "Erreur interne du serveur. Veuillez réessayer plus tard.",
"error.unknown.type": "Erreur inconnue",
"error.unknown.message": "Erreur inconnue. Veuillez réessayer plus tard.",
"clientNotInGSIM": "Le client avec l'ID {{id}} n'est pas membre du GSIM.",
"Capitalized Income amount adjusted already adjusted": "Montant du revenu capitalisé ajusté déjà ajusté",
"Capitalized Income Adjustment amount must be lower or equal to": "Le montant de l'ajustement du revenu capitalisé doit être inférieur ou égal à",
Expand Down
15 changes: 14 additions & 1 deletion src/assets/translations/it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@
},
"error.resource.notImplemented.type": "Errore non implementato",
"error.resource.notImplemented.message": "Funzionalità non implementata!",
"linkedSavingsAccountOwnership": "Il conto di risparmio collegato non appartiene al cliente selezionato.",
"error.auth.type": "Errore di autenticazione",
"error.auth.message": "Dettagli utente non validi. Per favore riprova!",
"error.token.invalid.type": "Token non valido",
"error.token.invalid.message": "Token non valido. Per favore riprova!",
"error.bad.request.type": "Richiesta non valida",
"error.bad.request.message": "Parametri non validi sono stati trasmessi nella richiesta!",
"error.unauthorized.type": "Richiesta non autorizzata",
"error.unauthorized.message": "Non sei autorizzato per questa richiesta!",
"error.resource.not.found.type": "Risorsa non trovata",
"error.resource.not.found.message": "La risorsa non esiste!",
"error.server.internal.type": "Errore interno del server",
"error.server.internal.message": "Errore interno del server. Per favore riprova più tardi.",
"error.unknown.type": "Errore sconosciuto",
"error.unknown.message": "Errore sconosciuto. Per favore riprova più tardi.",
"clientNotInGSIM": "Il cliente con ID {{id}} non è presente in GSIM.",
"Capitalized Income amount adjusted already adjusted": "Importo del reddito capitalizzato rettificato già rettificato",
"Capitalized Income Adjustment amount must be lower or equal to": "L'importo dell'adeguamento del reddito capitalizzato deve essere inferiore o uguale a",
Expand Down
15 changes: 14 additions & 1 deletion src/assets/translations/ko-KO.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@
},
"error.resource.notImplemented.type": "구현되지 않은 오류",
"error.resource.notImplemented.message": "구현되지 않은 기능입니다!",
"linkedSavingsAccountOwnership": "연결된 저축 계좌가 선택한 클라이언트에 속하지 않습니다.",
"error.auth.type": "인증 오류",
"error.auth.message": "잘못된 사용자 세부정보입니다. 다시 시도해주세요!",
"error.token.invalid.type": "유효하지 않은 토큰",
"error.token.invalid.message": "유효하지 않은 토큰입니다. 다시 시도해주세요!",
"error.bad.request.type": "잘못된 요청",
"error.bad.request.message": "요청에 잘못된 매개변수가 전달되었습니다!",
"error.unauthorized.type": "승인되지 않은 요청",
"error.unauthorized.message": "이 요청에 대해 권한이 없습니다!",
"error.resource.not.found.type": "리소스를 찾을 수 없음",
"error.resource.not.found.message": "리소스가 존재하지 않습니다!",
"error.server.internal.type": "내부 서버 오류",
"error.server.internal.message": "내부 서버 오류입니다. 나중에 다시 시도해주세요.",
"error.unknown.type": "알 수 없는 오류",
"error.unknown.message": "알 수 없는 오류입니다. 나중에 다시 시도해주세요.",
"clientNotInGSIM": "ID가 {{id}}인 클라이언트가 GSIM에 없습니다.",
"Capitalized Income amount adjusted already adjusted": "자본화된 소득 금액은 이미 조정되었습니다.",
"Capitalized Income Adjustment amount must be lower or equal to": "자본화된 소득 조정 금액은 다음보다 낮거나 같아야 합니다.",
Expand Down
15 changes: 14 additions & 1 deletion src/assets/translations/lt-LT.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@
},
"error.resource.notImplemented.type": "Neįdiegta klaida",
"error.resource.notImplemented.message": "Funkcionalumas neįdiegtas!",
"linkedSavingsAccountOwnership": "Susieta taupomoji sąskaita nepriklauso pasirinktam klientui.",
"error.auth.type": "Autentifikavimo klaida",
"error.auth.message": "Neteisingi vartotojo duomenys. Bandykite dar kartą!",
"error.token.invalid.type": "Nevalidus žeton",
"error.token.invalid.message": "Nevalidus žeton. Bandykite dar kartą!",
"error.bad.request.type": "Bloga užklausa",
"error.bad.request.message": "Užklausoje buvo perduoti neteisingi parametrai!",
"error.unauthorized.type": "Neleistina užklausa",
"error.unauthorized.message": "Jūs neturite leidimo šiai užklausai!",
"error.resource.not.found.type": "Išteklius nerastas",
"error.resource.not.found.message": "Išteklius neegzistuoja!",
"error.server.internal.type": "Vidinė serverio klaida",
"error.server.internal.message": "Vidinė serverio klaida. Bandykite dar kartą vėliau.",
"error.unknown.type": "Nežinoma klaida",
"error.unknown.message": "Nežinoma klaida. Bandykite dar kartą vėliau.",
"clientNotInGSIM": "Klientas su ID {{id}} nėra GSIM sistemoje.",
"Capitalized Income amount adjusted already adjusted": "Kapitalizuotų pajamų suma pakoreguota jau pakoreguota",
"Capitalized Income Adjustment amount must be lower or equal to": "Kapitalizuotų pajamų koregavimo suma turi būti mažesnė arba lygi",
Expand Down
Loading
Loading