-
-
Notifications
You must be signed in to change notification settings - Fork 5
SF-3311 Add TranslocoInterceptor to wrap English strings for Arabic UI #3204
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
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
✅ All tests successful. No failed tests found. Additional details and impacted files@@ Coverage Diff @@
## master #3204 +/- ##
==========================================
+ Coverage 81.85% 81.87% +0.01%
==========================================
Files 601 602 +1
Lines 34500 34526 +26
Branches 5591 5578 -13
==========================================
+ Hits 28241 28267 +26
- Misses 5426 5438 +12
+ Partials 833 821 -12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Could you just check if the string provided is identical to the English string (since that's what we always fall back to), rather than trying to detect Arabic? This would make it work for other languages as well, with no need to detect the script. |
This change utilizes the TranslocoInterceptor interface to check the strings in our localization files for untranslated values. If an RTL value is supplied (via the UI language), it will wrap any strings that don't contain an RTL character. Currently only Arabic is supported, but you could easily add more. This allows punctuation to appear in the correct place for English sentences when the UI is set to Arabic. I didn't encounter any places in the app that are using preSaveTranslationKey, but it was required for the interface. The preSaveTranslation method is called once for each localization file that's in use, for a total of two times.
… Arabic This should allow us to support more RTL languages without further changes. It requires the TranslocoService, gotten lazily via the Injector, to get the English translations. It also requires the use of a startup method via APP_INITIALIZER to load the English translations before the interceptor runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this new logic something that should be demonstrated in i18n-story.module.ts
?
I think that could help given the subtleness of how a future update to transloco (I notice transloco has moved to a new npm package @jsverse/transloco
) could inadvertently nerf this fix, as we rely on injecting into their dependency chain.
Reviewed 4 of 4 files at r1, all commit messages.
Reviewable status: all files reviewed, 8 unresolved discussions (waiting on @Nateowami)
src/SIL.XForge.Scripture/ClientApp/src/app/shared/ltr-marker.interceptor.spec.ts
line 12 at r1 (raw file):
const LRE = '\u202A'; const PDF = '\u202C';
See comment above about defining the constants in utils.ts.
Code quote:
const LRE = '\u202A';
const PDF = '\u202C';
src/SIL.XForge.Scripture/ClientApp/src/app/app.module.ts
line 101 at r1 (raw file):
{ provide: OverlayContainer, useClass: InAppRootOverlayContainer }, provideHttpClient(withInterceptorsFromDi()), { provide: TRANSLOCO_INTERCEPTOR, useClass: LtrMarkerInterceptor },
Do think this line should be moved to xforge-common\xforge-common.module.ts
where the other TRANSLOCO_
providers are?
You could alternatively move those providers out of there and put them here if you think that is more logical. My only real point is I think they should be together...somewhere.
Code quote:
{ provide: TRANSLOCO_INTERCEPTOR, useClass: LtrMarkerInterceptor },
src/SIL.XForge.Scripture/ClientApp/src/app/app-init.ts
line 11 at r1 (raw file):
* @returns A function that returns a Promise which resolves when English translations are loaded. */ export function preloadEnglishTranslations(translocoService: TranslocoService): () => Promise<any> {
NIT: Should this be Promise<Translation>
?
Code quote:
Promise<any>
src/SIL.XForge.Scripture/ClientApp/src/app/app-init.ts
line 11 at r1 (raw file):
* @returns A function that returns a Promise which resolves when English translations are loaded. */ export function preloadEnglishTranslations(translocoService: TranslocoService): () => Promise<any> {
I am wondering whether this function should be in app/shared/utils.ts
? Just seems odd to have a new file that just exports one small function.
Code quote:
preloadEnglishTranslations
src/SIL.XForge.Scripture/ClientApp/src/app/shared/ltr-marker.interceptor.ts
line 25 at r1 (raw file):
preSaveTranslation(translation: Translation, langOfTranslationFile: string): Translation { const activeUiLocale = I18nService.getLocale(langOfTranslationFile); const uiIsRtl = activeUiLocale?.direction === 'rtl';
NIT: Please define the types.
Code quote:
const activeUiLocale = I18nService.getLocale(langOfTranslationFile);
const uiIsRtl = activeUiLocale?.direction === 'rtl';
src/SIL.XForge.Scripture/ClientApp/src/app/shared/ltr-marker.interceptor.ts
line 28 at r1 (raw file):
if (uiIsRtl) { const englishTranslations = this.translocoService.getTranslation('en');
NIT: Please define the type.
Code quote:
const englishTranslations = this.translocoService.getTranslation('en');
src/SIL.XForge.Scripture/ClientApp/src/app/shared/ltr-marker.interceptor.ts
line 45 at r1 (raw file):
// This suggests the current value is an untranslated fallback to English. // Wrap with LTR markers if not already wrapped. if (!currentValue.startsWith('\u202A') && !currentValue.endsWith('\u202C')) {
You could define these constants as POP_DIRECTIONAL_FORMATTING
and LEFT_TO_RIGHT_EMBEDDING
along side export const RIGHT_TO_LEFT_MARK
in utils.ts
, then you would not need to define them in your spec.ts
. (It would also make your code more readable here, as I forgot which one is which!)
Code quote:
f (!currentValue.startsWith('\u202A') && !currentValue.endsWith('\u202C')) {
src/SIL.XForge.Scripture/ClientApp/src/app/shared/ltr-marker.interceptor.ts
line 57 at r1 (raw file):
if (uiIsRtl) { const englishTranslations = this.translocoService.getTranslation('en');
NIT: Please define the types.
Code quote:
const activeUiLocale = I18nService.getLocale(langOfValue);
const uiIsRtl = activeUiLocale?.direction === 'rtl';
if (uiIsRtl) {
const englishTranslations = this.translocoService.getTranslation('en');
This change utilizes the TranslocoInterceptor interface to check the strings in our localization files for untranslated values. If an RTL value is supplied (via the UI language), it will wrap any strings that don't contain an RTL character. Currently only Arabic is supported, but you could easily add more. This allows punctuation to appear in the correct place for English sentences when the UI is set to Arabic.
I didn't encounter any places in the app that are using preSaveTranslationKey, but it was required for the interface. The preSaveTranslation method is called once for each localization file that's in use, for a total of two times.
This change is