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 4 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
17 changes: 11 additions & 6 deletions met-web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ const App = () => {
if (!tenant.id) {
return;
}

try {
const supportedLanguages = Object.values(Languages);
const supportedLanguages: string[] = Object.values(Languages);
// Adding keyword `common` into supportedLanguages to fetch locale/common.json
supportedLanguages.push('common');
Copy link
Collaborator

Choose a reason for hiding this comment

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

In reading this code, one would expect supportedLanguages to be a list of languages. I think adding the common entry could be confusing, although I can see that it simplifies the work a little bit.

For readability, I'd recommend either renaming Languages to LocaleFiles or some other solution that can make things a bit easier to understand.

Copy link
Collaborator Author

@ratheesh-aot ratheesh-aot May 27, 2024

Choose a reason for hiding this comment

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

Separated the code to load a common translation file

const translationPromises = supportedLanguages.map((languageId) => getTranslationFile(languageId));
const translationFiles = await Promise.all(translationPromises);

Expand All @@ -137,17 +138,17 @@ const App = () => {

const getTranslationFile = async (languageId: string) => {
try {
const translationFile = await import(`./locales/${languageId}/${tenant.id}.json`);
const translationFile = await import(`./locales/${languageId}.json`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again, here you might expect languageId to only correspond to a language, but now it can also be the word "common". I think we need to update variable names to account for this, or possibly restructure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed to localeId

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 +158,11 @@ const App = () => {
i18n.changeLanguage(language.id); // Set the language for react-i18next

try {
i18n.addResourceBundle(language.id, tenant.id, translations[language.id]);
// adding resource to default namespace 'default'
i18n.addResourceBundle(language.id, 'default', translations[language.id]);
// adding common translation resource file 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
21 changes: 16 additions & 5 deletions met-web/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,26 @@ 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;

Copy link
Collaborator

Choose a reason for hiding this comment

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

The language system in MET is inherently a bit confusing. The comments in this file are great so far, and maybe we could add a higher-level one above this function. Would this comment describe the intended behaviour?

Suggested change
/**
* Look to see if a string has a tenant-level translation (if it's related to an engagement, survey, widget, static
* tenant text, etc.). If none is found, look for a common static text translation found in the common locale file.
**/

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated the comments

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}`;
const value = t(dynamicKey);
// If the value is the same as the key, then the key does not exist in the `default` namespace, so try the `common` namespace
if (key === value) {
const dynamicKey = `common:${key}`;
const value = t(dynamicKey);
// If the value is the same as the key log error and return the key
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