Skip to content

Feature/custom translations frontend #857

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

rvveber
Copy link
Collaborator

@rvveber rvveber commented Apr 8, 2025

Adds the possibilty to inject/override custom translations at runtime.

@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 2 times, most recently from 10cd759 to d285bd1 Compare April 8, 2025 14:36
@rvveber rvveber mentioned this pull request Apr 8, 2025
9 tasks
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 2 times, most recently from 4ff16fa to 81fd1ed Compare April 8, 2025 15:12
@AntoLC AntoLC requested review from AntoLC and lunika April 8, 2025 15:19
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 2 times, most recently from b9b16aa to 06b91a1 Compare April 14, 2025 17:14
@rvveber rvveber requested a review from AntoLC April 14, 2025 17:14
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from 06b91a1 to af92119 Compare April 16, 2025 10:47
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 2 times, most recently from a65fca6 to cddc429 Compare May 7, 2025 14:21
@rvveber rvveber requested a review from AntoLC May 7, 2025 14:26
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from cddc429 to 9a9b717 Compare May 7, 2025 14:28
@rvveber rvveber marked this pull request as draft May 8, 2025 09:44
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 3 times, most recently from 5f855f1 to ed137ef Compare May 8, 2025 17:53
@rvveber rvveber marked this pull request as ready for review May 8, 2025 17:57
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from ed137ef to 2e7f552 Compare May 12, 2025 14:52
@rvveber rvveber marked this pull request as draft May 12, 2025 14:58
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from 2e7f552 to 6a036b3 Compare May 12, 2025 15:02
@rvveber rvveber marked this pull request as ready for review May 12, 2025 15:22
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from 6a036b3 to 6a75453 Compare May 12, 2025 15:43
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 2 times, most recently from 0080fdc to bf65c8b Compare May 13, 2025 10:51
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 3 times, most recently from d86f811 to f7abb03 Compare May 13, 2025 11:23
@@ -11,5 +11,5 @@ export interface User {
email: string;
full_name: string;
short_name: string;
language: string;
language?: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

language can be undefined from the backend ?

Copy link
Collaborator Author

@rvveber rvveber May 20, 2025

Choose a reason for hiding this comment

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

Yes, language is nullable.
It was introduced with the language synchronization feature and should've been changed back then.

It allows us to update the users preferred language automatically from the i18n browser detected language - without overriding his existing preference.

Comment on lines 11 to 7
const currentCustomTranslations: Resource = useMemo(
() => currentConfig?.theme_customization?.translations || {},
[currentConfig],
);

Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
const currentCustomTranslations: Resource = useMemo(
() => currentConfig?.theme_customization?.translations || {},
[currentConfig],
);
const currentCustomTranslations: Resource = currentConfig?.theme_customization?.translations || {};

Comment on lines 38 to 27
return {
currentCustomTranslations,
customizeTranslations,
};
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

You don't seem to need to export them.

);

useEffect(() => {
if (currentCustomTranslations) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

currentCustomTranslations seems everytime defined.

Suggested change
if (currentCustomTranslations) {


const availableFrontendLanguages = useMemo(
() => Object.keys(i18n?.options?.resources || { en: '<- fallback' }),
[i18n],
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
[i18n],
[i18n?.options?.resources],

Comment on lines 45 to 49
log('Updating backend language (%O)', {
requested: language,
from: user.language,
to: closestBackendLanguage,
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be just during the development part I think.

Comment on lines 65 to 70
log('Updating frontend language (%O)', {
requested: language,
from: i18n.resolvedLanguage,
to: closestFrontendLanguage,
});
void i18n.changeLanguage(closestFrontendLanguage);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same it is part of the development part, should be removed.

Comment on lines 12 to 14
function createUser(): Promise<User> {
throw new Error('Not yet implemented.');
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are creating things that we don't need yet (maybe never ?), same for the deleteUser.

After this feature is made to manage the authentication, I don't know if it is the good place to add the user mutation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for your valuable feedback on the useAuthMutation pull request. I appreciate you highlighting the concerns around the scope and placement of the user-related mutations.

I agree with your observations, and I believe a couple of changes will clarify the intent and improve the structure:

  1. Renaming for Clarity:

    • You're right, the current names are a bit misleading. I propose renaming:
      • useAuthQuery to useUserQuery
      • getMe to readUser (which will default to fetching /users/me/ but could accept an ID).
      • useAuthMutation to useUserMutation.
    • This better reflects that we are fundamentally querying and mutating User data.
  2. Relocation to Entity-Specific Path:

    • Following the renaming, I'll move these hooks to a more appropriate location, such as api/entities/user/. This aligns with the idea that these are general-purpose tools for managing the User entity, not strictly tied to the authentication feature's codebase.

Regarding createUser and deleteUser:

My intention in including createUser and deleteUser (even as unimplemented stubs for now) within useUserMutation was to:

  • Establish a Complete CRUD Pattern: Provide a full, standard interface (Create, Read, Update, Delete) for the User entity from the outset. This is a common and robust pattern, similar to what one might find in ORMs, and it makes the API for User management predictable.
  • Serve as a Clear Blueprint: This structure acts as a boilerplate, clearly defining how all entity mutations should be handled. It sets an example for consistency when we add mutations for other entities in the future.
  • Enhance Readability & Single Responsibility: Grouping all mutation logic for a User (create, update, delete) within useUserMutation maintains a clear single responsibility for modifying user data. I believe this makes the code more self-documenting and easier to navigate.
  • Future Preparedness with Minimal Overhead: While these functions aren't used by the current feature iteration, defining them now prepares us for future requirements. The stubs themselves add negligible overhead but offer significant structural benefits and clarity for ongoing development.

By renaming and relocating these hooks to focus on the User entity, I believe the inclusion of the full CRUD set (even with stubs) becomes more logical as it defines the comprehensive API for User management.

I've spent considerable time researching best practices for data fetching and mutations in React, and this pattern of co-locating entity-specific hooks with a complete operational set seemed the most explicit and maintainable.

Please let me know if these proposed changes and this explanation address your concerns.
I'm keen to ensure we're building a clean and scalable foundation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We have agreed to simplify it to useUpdateUser that does not follow CRUD explicitly.

currentBackendLanguage,
currentFrontendLanguage,
changeLanguageSynchronized,
currentUser,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is currentUser necessary ?

[changeBackendLanguage, changeFrontendLanguage, currentUser],
);

useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have the feeling this useEffect is trigger often.

Copy link
Collaborator Author

@rvveber rvveber May 27, 2025

Choose a reason for hiding this comment

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

It was not good to have the useEffect in the useSynchronizedLanguage hook anyways,
as it added 1 useEffect call, everytime useSynchronizedLanguage() is instantiated.

To counteract, one would need to develop a Provider to share Context.
Since i didn't see the need for a dedicated Provider just to prevent a race condition / enable singleton pattern, i instead moved the useEffect to the ConfigProvider and simplified useSynchronizedLanguage to only be responsible for change language.

The default behavior ("sync frontend detected language to backend if backend language is null") is now handeled in the ConfigProvider. It looks more on par with what we already have in there.

@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from f7abb03 to 4d59da8 Compare May 27, 2025 15:15
@rvveber rvveber requested a review from AntoLC May 27, 2025 15:20
Part of customization PoC

Signed-off-by: Robin Weber <[email protected]>
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch 2 times, most recently from 8c383a0 to 372b8d9 Compare May 27, 2025 15:42
rvveber added 4 commits May 27, 2025 17:46
Part of customization PoC

Signed-off-by: Robin Weber <[email protected]>
Introduces dedicated mutations
(for authentication/user operations)
separating them from queries to align with best practices
for data fetching and state management.

Queries remain responsible for READ operations, while mutations
now handle CREATE, UPDATE, and DELETE actions (for user data)
improving separation of concerns.

Signed-off-by: Robin Weber <[email protected]>
- Refactors "useTranslationsCustomizer" to "useCustomTranslations"
- Refactors "useLanguageSynchronizer" to "useSynchronizedLanguage"
- Refactors "LanguagePicker" to better reflect its component role
- Refactors "LanguagePicker" to use "useSynchronizedLangue"
- Removes unused "useChangeUserLanguage"
- To change the user language, use "useAuthMutation" instead

Signed-off-by: Robin Weber <[email protected]>
- Language will only be changed if different from current language
- Added test for custom translations

Signed-off-by: Robin Weber <[email protected]>
@rvveber rvveber force-pushed the feature/custom-translations-frontend branch from 372b8d9 to bb1c96e Compare May 27, 2025 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants