Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DESENG-611: Splitting translations based on language and common #2525

Merged
merged 6 commits into from
May 27, 2024
Merged
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
8 changes: 8 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## May 27, 2024

- **Feature** MET translation file keys used on pages needing translation [🎟️ DESENG-611](https://apps.itsm.gov.bc.ca/jira/browse/DESENG-611)
- Removed Tenant based translations from langauge files
- Set TODO statements to replace tenant related values from backend
- Splitting translations based on language files and added a common translation file for items common across all languages


## May 23, 2024

- **Feature** Finish tenant management UX [🎟️ DESENG-605](https://apps.itsm.gov.bc.ca/jira/browse/DESENG-605), [🎟️ DESENG-606](https://apps.itsm.gov.bc.ca/jira/browse/DESENG-606)
Expand Down
23 changes: 16 additions & 7 deletions met-web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,8 @@ const App = () => {
if (!tenant.id) {
return;
}

try {
const supportedLanguages = Object.values(Languages);
const supportedLanguages: string[] = Object.values(Languages);
const translationPromises = supportedLanguages.map((languageId) => getTranslationFile(languageId));
const translationFiles = await Promise.all(translationPromises);

Expand All @@ -129,25 +128,31 @@ const App = () => {
}
});

// Fetch the common.json file separately
const commonTranslations = await getTranslationFile('common');
if (commonTranslations) {
translationsObj['common'] = commonTranslations.default;
}

setTranslations(translationsObj);
} catch (error) {
console.error('Error preloading translations:', error);
}
};

const getTranslationFile = async (languageId: string) => {
const getTranslationFile = async (localeId: string) => {
try {
const translationFile = await import(`./locales/${languageId}/${tenant.id}.json`);
const translationFile = await import(`./locales/${localeId}.json`);
return translationFile;
} catch (error) {
const defaultTranslationFile = await import(`./locales/${languageId}/default.json`);
const defaultTranslationFile = await import(`./locales/en.json`);
return defaultTranslationFile;
}
};

useEffect(() => {
preloadTranslations();
}, [tenant.id]); // Preload translations when tenant id changes
}, [language.id, tenant.id]); // Preload translations when language id or tenant id changes

const loadTranslation = async () => {
if (!tenant.id || !translations[language.id]) {
Expand All @@ -157,7 +162,11 @@ const App = () => {
i18n.changeLanguage(language.id); // Set the language for react-i18next

try {
i18n.addResourceBundle(language.id, tenant.id, translations[language.id]);
// adding language based translation resources to default namespace 'default'. like en.json, fr.json etc
i18n.addResourceBundle(language.id, 'default', translations[language.id]);
// adding common translation resource file (common.json) to namespace 'common'
i18n.addResourceBundle(language.id, 'common', translations['common']);

dispatch(loadingTenant(false));
} catch (error) {
dispatch(loadingTenant(false));
Expand Down
5 changes: 2 additions & 3 deletions met-web/src/DocumentTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react';
import { Helmet } from 'react-helmet-async';
import { useAppTranslation } from 'hooks';
const DocumentTitle = () => {
const { t: translate } = useAppTranslation();
return (
<Helmet>
<title>{translate('header.title')}</title>
{/* TODO: LANG-BACKEND - Change the value to show tenant specific */}
<title>Modern Engagement</title>
</Helmet>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ const CommentReview = () => {
};

const defaultVerdict = comment_status_id !== CommentStatus.Pending ? comment_status_id : CommentStatus.Approved;
const threatEmailContact = translate('comment.admin.review.threatContactEmail');
// TODO: LANG-BACKEND - Change the value to show tenant specific
const threatEmailContact = '[email protected]';
return (
<MetPageGridContainer>
<EmailPreviewModal
Expand Down Expand Up @@ -407,8 +408,10 @@ const CommentReview = () => {
}
/>
<MetSmallTextOld bold color="#d32f2f" marginLeft={'3em'} mt={'-1em'}>
{translate('comment.admin.review.threatTextOne')}{' '}
{translate('comment.admin.review.threatContact')}{' '}
{translate('comment.admin.review.threatTextOne')}
{/* TODO: LANG-BACKEND - Change the value to show tenant specific //
comment.admin.review.threatContact */}
{'FirstName LastName'}
{translate('comment.admin.review.threatTextTwo')}{' '}
<Link href={`mailto:${threatEmailContact}`}>{threatEmailContact}</Link>
</MetSmallTextOld>
Expand Down
9 changes: 4 additions & 5 deletions met-web/src/components/landing/LandingComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ import { MetHeader1Old, MetParagraphOld } from 'components/common';
import TileBlock from './TileBlock';
import { Container } from '@mui/system';
import LandingPageBanner from 'assets/images/LandingPageBanner.png';
import { useAppTranslation } from 'hooks';
import FilterBlock from './FilterBlock';
import FilterDrawer from './FilterDrawer';
const LandingComponent = () => {
const { t: translate } = useAppTranslation();

return (
<Grid container direction="row" justifyContent="center" alignItems="center">
<FilterDrawer />
Expand Down Expand Up @@ -47,10 +44,12 @@ const LandingComponent = () => {
rowSpacing={2}
>
<Grid item xs={12}>
<MetHeader1Old>{translate('landing.banner.header')}</MetHeader1Old>
{/* TODO: LANG-BACKEND - Change the value to show tenant specific */}
<MetHeader1Old>Government Digital Experience Division</MetHeader1Old>
</Grid>
<Grid item xs={12}>
<MetParagraphOld>{translate('landing.banner.description')}</MetParagraphOld>
{/* TODO: LANG-BACKEND - Change the value to show tenant specific */}
<MetParagraphOld>Description about the office and public engagement.</MetParagraphOld>
</Grid>
</Grid>
</Grid>
Expand Down
11 changes: 6 additions & 5 deletions met-web/src/components/layout/Header/InternalHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBars } from '@fortawesome/pro-regular-svg-icons/faBars';
import { HeaderProps } from './types';
import { useNavigate } from 'react-router-dom';
import { useAppTranslation } from 'hooks';

const InternalHeader = ({ drawerWidth = 280 }: HeaderProps) => {
const isMediumScreen: boolean = useMediaQuery((theme: Theme) => theme.breakpoints.up('md'));
const [open, setOpen] = useState(false);
const [imageError, setImageError] = useState(false);
const navigate = useNavigate();
const { t: translate } = useAppTranslation();

const logoUrl = translate('common.logoUrl');
// TODO: LANG-BACKEND - Change the value to show tenant specific
const logoUrl = '';
return (
<>
<AppBar
Expand Down Expand Up @@ -101,7 +100,8 @@ const InternalHeader = ({ drawerWidth = 280 }: HeaderProps) => {
}}
sx={{ flexGrow: 1, cursor: 'pointer' }}
>
{translate('header.title')}
{/* TODO: LANG-BACKEND - Change the value to show tenant specific */}
{'Modern Engagement'}
</HeaderTitleOld>
) : (
<HeaderTitleOld
Expand All @@ -110,7 +110,8 @@ const InternalHeader = ({ drawerWidth = 280 }: HeaderProps) => {
}}
sx={{ flexGrow: 1, cursor: 'pointer' }}
>
{translate('header.smallTitle')}
{/* TODO: LANG-BACKEND - Change the value to show tenant specific */}
{'MET'}
</HeaderTitleOld>
)}
<Button
Expand Down
12 changes: 8 additions & 4 deletions met-web/src/components/layout/Header/PublicHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ const PublicHeader = () => {
const { t: translate } = useAppTranslation();
const { engagementViewMounted, availableEngagementTranslations } = useContext(LanguageContext);

const logoUrl = translate('common.logoUrl');
const headerTitle = translate('header.title');
// TODO: LANG-BACKEND - Change the value to show tenant specific
const logoUrl = '';
// TODO: LANG-BACKEND - Change the value to show tenant specific
const headerTitle = 'Modern Engagement';

return (
<Box sx={{ flexGrow: 1 }}>
Expand All @@ -46,7 +48,8 @@ const PublicHeader = () => {
>
<img
src={logoUrl}
alt={translate('common.defaultText')}
// TODO: LANG-BACKEND - Change the value to show tenant specific
alt="Site Logo"
style={{
objectFit: 'cover',
height: '5em',
Expand Down Expand Up @@ -74,7 +77,8 @@ const PublicHeader = () => {
onClick={() => {
navigate(`/${language}`);
}}
alt={translate('common.defaultBCText')}
// TODO: LANG-BACKEND - Change the value to show tenant specific
alt="British Columbia Logo"
/>
</When>
<HeaderTitleOld
Expand Down
27 changes: 21 additions & 6 deletions met-web/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,30 @@ export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

export const useAppTranslation = () => {
const translate = useTranslation();
const tenantId = sessionStorage.getItem('tenantId');
// Every language has its own default and common namespaces
const translate = useTranslation(['default', 'common']);

const { t } = translate;

/**
* Look to see if a string has a language-level translation (if it's related to an engagement, survey, widget, static
* etc.). If none is found, look for a common static text translation found in the common locale file.
**/
const tDynamic = (key: string) => {
// Create a dynamic translation key using the tenantId
const dynamicKey = `${tenantId}:${key}`;
return t(dynamicKey);
// Create a dynamic translation key using the `default` namespace
const dynamicKey = `default:${key}`;
// getting language level translations for the key
const value = t(dynamicKey);
// If the value is the same as the key, then the key does not exist in the language translations, can be check in common locale file
if (key === value) {
const dynamicKey = `common:${key}`;
const value = t(dynamicKey);
// If the value is the same as the key it does not exist in the either language level or common translations
if (key == value) {
console.log('Error getting translation for ', key);
}
return value;
}
return value;
};

return { ...translate, t: tDynamic };
Expand Down
1 change: 1 addition & 0 deletions met-web/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ i18n.use(initReactI18next).init({
interpolation: {
escapeValue: false,
},
defaultNS: 'default', // default namespace as `default`
});

export default i18n;
100 changes: 100 additions & 0 deletions met-web/src/locales/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"notFound": {
"paragraph": "Suggestions to help you find what you're looking for:",
"list": [
"Check that the web URL has been entered correctly",
"Go to our",
"homepage",
"and browse through our past and current engagements",
"Telephone Device for the Deaf (TDD) across B.C.: 711",
"If you would like to email us, please contact *********@gov.bc.ca."
],
"header": [
"The page you're looking for cannot be found.",
"The page you're looking for might have been removed, moved or is temporarily unavailable."
]
},
"notAvailable": {
"label": "Sorry, this engagement is not available."
},
"footer": {
"body": "The B.C. Public Service acknowledges the territories of First Nations around B.C. and is grateful to carry out our work on these lands. We acknowledge the rights, interests, priorities, and concerns of all Indigenous Peoples - First Nations, Métis and Inuit - respecting and acknowledging their distinct cultures, histories, rights, laws, and governments.",
"connectWithUs": "CONNECT WITH US",
"moreInfo": "MORE INFO",
"home": "Home",
"accessibility": "Accessibility",
"aboutGov": "About gov.bc.ca",
"copyright": "Copyright",
"disclaimer": "Disclaimer",
"login": "Admin Login",
"privacy": "Privacy",
"copyrightNotice": "© 2023 Government of British Columbia",
"defaultLogo": "British Columbia Logo"
},
"feedback": {
"websiteFeedback": "Website Feedback",
"notification": {
"success": "Your Feedback has been sent.",
"error": "Error occurred while sending your feedback."
},
"submitModal": {
"header": "Thank you for your feedback",
"button": "Close"
},
"feedbackModal": {
"label": [
"How do you like our feedback platform?",
"What else would you like to share with us?"
],
"disclaimer": "Please do not include any personal information in your feedback. Feedback that includes personal information will be deleted.",
"button": "Submit"
}
},
"landingPage": {
"tile": {
"error": "Error while loading",
"status": "Status:"
}
},
"comment": {
"admin": {
"review": {
"threatTextOne": "Select this option if there is a threat/menace in the comment(s). No email will be sent. Contact",
"threatTextTwo": "at"
}
}
},
"landing": {
"filters": {
"drawer": {
"openButton": "Filter",
"title": "Filter Engagements",
"apply": "Apply Filters",
"statusFilter": "Engagement Status",
"filterHeader": "Filter by {0}"
},
"clear": "Clear Filters",
"search": "Search Engagements",
"searchPlaceholder": "Engagement Title",
"status": {
"all": "All Engagements",
"open": "Open Engagements",
"closed": "Closed Engagements",
"upcoming": "Upcoming Engagements"
},
"aria": {
"closeDrawer": "Close filter options",
"openDrawer": "Open more filter options",
"deleteFilterChip": "{0} filter - press to remove",
"metadataFilterChip": "{0} filter - {1}",
"selected": "Applied",
"notSelected": "Not Applied",
"applyFilters": "Apply Filters and close filter options",
"statusFilter": "Engagement Status Selector - {0} selected"
}
}
},
"common": {
"logout": "Logout"
}
}
Loading
Loading