From 4ad8da40837744e33f4e13297eba0e9259cd6585 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Sep 2025 02:49:40 +0000 Subject: [PATCH] Fix JSON parsing error in i18n configuration and API error handling Co-authored-by: lora322 <39804183+lora322@users.noreply.github.com> --- frontend/public/locales/en-US/common.json | 52 +++++++++++++++++++++++ frontend/src/helpers/pexels.ts | 27 ++++++++++-- frontend/src/i18n.ts | 2 + frontend/src/pages/index.tsx | 10 ++++- frontend/src/pages/login.tsx | 5 ++- 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 frontend/public/locales/en-US/common.json diff --git a/frontend/public/locales/en-US/common.json b/frontend/public/locales/en-US/common.json new file mode 100644 index 0000000..2c1a38d --- /dev/null +++ b/frontend/public/locales/en-US/common.json @@ -0,0 +1,52 @@ +{ + "pages": { + "dashboard": { + "pageTitle": "Dashboard", + "overview": "Overview", + "loadingWidgets": "Loading widgets...", + "loading": "Loading..." + }, + "login": { + "pageTitle": "Login", + + "form": { + "loginLabel": "Login", + "loginHelp": "Please enter your login", + "passwordLabel": "Password", + "passwordHelp": "Please enter your password", + "remember": "Remember", + "forgotPassword": "Forgot password?", + "loginButton": "Login", + "loading": "Loading...", + "noAccountYet": "Don’t have an account yet?", + "newAccount": "New Account" + }, + + "pexels": { + "photoCredit": "Photo by {{photographer}} on Pexels", + "videoCredit": "Video by {{name}} on Pexels", + "videoUnsupported": "Your browser does not support the video tag." + }, + + "footer": { + "copyright": "© {{year}} {{title}}. All rights reserved", + "privacy": "Privacy Policy" + } + } + }, + "components": { + "widgetCreator": { + "title": "Create Chart or Widget", + "helpText": "Describe your new widget or chart in natural language. For example: \"Number of admin users\" OR \"red chart with number of closed contracts grouped by month\"", + "settingsTitle": "Widget Creator Settings", + "settingsDescription": "What role are we showing and creating widgets for?", + "doneButton": "Done", + "loading": "Loading..." + }, + "search": { + "placeholder": "Search", + "required": "Required", + "minLength": "Minimum length: {{count}} characters" + } + } +} diff --git a/frontend/src/helpers/pexels.ts b/frontend/src/helpers/pexels.ts index 524a1b2..97dd6ad 100644 --- a/frontend/src/helpers/pexels.ts +++ b/frontend/src/helpers/pexels.ts @@ -6,7 +6,12 @@ export async function getPexelsImage() { return response.data; } catch (error) { console.error('Error fetching image:', error); - return null; + // Return fallback data when backend is not available + return { + src: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZGRkIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPkltYWdlIE5vdCBBdmFpbGFibGU8L3RleHQ+PC9zdmc+', + photographer: 'Placeholder', + photographer_url: '#' + }; } } @@ -16,7 +21,11 @@ export async function getPexelsVideo() { return response.data; } catch (error) { console.error('Error fetching video:', error); - return null; + // Return fallback data when backend is not available + return { + src: '', + name: 'Video Not Available' + }; } } @@ -63,7 +72,19 @@ export async function getMultiplePexelsImages( localStorage.setItem('pexelsImagesCache', JSON.stringify(cachedImages)); } catch (error) { - console.error(error); + console.error('Error fetching multiple images:', error); + // Provide fallback images when backend is not available + missingQueries.forEach((query) => { + const normalizedQuery = normalizeQuery(query); + if (!cachedImages[normalizedQuery]) { + cachedImages[normalizedQuery] = { + src: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZGRkIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPkltYWdlIE5vdCBBdmFpbGFibGU8L3RleHQ+PC9zdmc+', + photographer: 'Placeholder', + photographer_url: '#' + }; + } + }); + localStorage.setItem('pexelsImagesCache', JSON.stringify(cachedImages)); } } diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index f8a7c37..70cd590 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -9,6 +9,8 @@ i18n .use(initReactI18next) .init({ fallbackLng: 'en', + defaultNS: 'common', + ns: ['common'], detection: { order: ['localStorage', 'navigator'], lookupLocalStorage: 'app_lang_33651', diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx index f340802..43c8062 100644 --- a/frontend/src/pages/index.tsx +++ b/frontend/src/pages/index.tsx @@ -12,8 +12,10 @@ import { getPageTitle } from '../config'; import { useAppSelector } from '../stores/hooks'; import CardBoxComponentTitle from '../components/CardBoxComponentTitle'; import { getPexelsImage, getPexelsVideo } from '../helpers/pexels'; +import { useTranslation } from 'react-i18next'; export default function Starter() { + const { t } = useTranslation('common'); const [illustrationImage, setIllustrationImage] = useState({ src: undefined, photographer: undefined, @@ -145,10 +147,14 @@ export default function Starter() {

- © 2025 {title}. All rights reserved + {t('pages.login.footer.copyright', { + year: new Date().getFullYear(), + title: title, + defaultValue: '© {{year}} {{title}}. All rights reserved', + })}

- Privacy Policy + {t('pages.login.footer.privacy', { defaultValue: 'Privacy Policy' })}
diff --git a/frontend/src/pages/login.tsx b/frontend/src/pages/login.tsx index 9b83587..915859f 100644 --- a/frontend/src/pages/login.tsx +++ b/frontend/src/pages/login.tsx @@ -361,9 +361,10 @@ export default function Login() {

- © 2025 {title}.{' '} {t('pages.login.footer.copyright', { - defaultValue: '© All rights reserved', + year: new Date().getFullYear(), + title: title, + defaultValue: '© {{year}} {{title}}. All rights reserved', })}