-
Notifications
You must be signed in to change notification settings - Fork 255
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
Refactor property value internationalization (fixes #3470) #3482
base: master
Are you sure you want to change the base?
Conversation
f28b81c
to
84298aa
Compare
Codecov Report
@@ Coverage Diff @@
## master #3482 +/- ##
==========================================
- Coverage 88.91% 88.80% -0.11%
==========================================
Files 198 198
Lines 3409 3439 +30
==========================================
+ Hits 3031 3054 +23
- Misses 378 385 +7
Continue to review full report at Codecov.
|
c0102d0
to
f4152fd
Compare
This admittedly huge changeset refactors the way the correct language value for a given property value is determined. A recent change in the Manifesto library made it possible to pass a list of languages (in descending order of preference) to the `PropertyValue.getValue` and `PropertyValue.getValues` methods, instead of relying on a single default locale that would be set when parsing the manifest. This allows for a better user experience, since we can now dynamically respond to changes in the user's language preferences without having to re-parse the manifest. Additionally, we can make use of the browser's language preferences to better match the user's language abilities. However, this required a substantial reworking of quite a few parts of Mirador, namely: - Introduced a new `config.userLanguages` redux state variable that has the list of languages in descending order of preference (as returned by i18next.languages after setting the configured language) - Every selector that would previously simply call `getValue` on a property value was changed to retrieve the user languages from the store and pass them to `getValue`. Additionally, for property values that are displayed in the companion window, where the locale can be overridden separately from the global language, selectors are extended to take a third `overrideLanguages` parameter that allows customization of the languages passed to `getValue`/`getValues` - When changing the global language setting, the value in the companion window's `LocalePicker` (if enabled) now will select the next-best available language according to the langauge pereferences, if the desired language is not part of the metadata. As a whole, these changes now allow on-the-fly switching of languages via both the global language selector and the companion window locale picker for all property values parsed from the manifest, with support for falling back according to the user's client language preferences.
f4152fd
to
ea883b6
Compare
return (resource | ||
&& resource.getLabel | ||
&& resource.getLabel().length > 0) | ||
? resource.getLabel().getValue() | ||
? resource.getLabel().getValue(langs) |
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.
Can you remind me of the manifesto behavior if there's no label in a given language? Is there a fallback or something?
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.
Currently the behavior is to simply pick the first value, with no regard for the (legacy) defaultLocale
. I'm still planning on submitting a PR that uses that instead, but haven't gotten around to it yet.
@@ -30,11 +30,11 @@ const reorder = (list, startIndex, endIndex) => { | |||
/** */ | |||
export class CanvasLayers extends Component { | |||
/** */ | |||
static getUseableLabel(resource, index) { | |||
static getUseableLabel(resource, index, langs) { |
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.
This probably goes for all these label helpers... I wonder if we should refactor these back into the instance, now that they depend on some state data?
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.
Probably a good idea, yes! Or maybe refactor it into a utility function? I've seen this exact static method (and minor variations of it) in more than a handful components.
? resource.getLabel().getValue() | ||
: String(index + 1); | ||
? resource.getLabel().getValue(langs) | ||
: resource.id; |
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.
Why resource.id
instead of the index value?
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.
Sorry about that, it was probably an ill-advised attempt a a unification of the various getUsableLabel
methods that went nowhere in the end, I'll revert!
Just checked, index
was never passed in this component, so the fallback would always be "NaN"
(String(undefined + 1)
). Using the resource identifier seems more sensible.
// If `locale` is not among the available locales, it should be the first available | ||
// locale that matches the language preferences from the `userLanguages` store value | ||
if (availableLocales.indexOf(locale) < 0) { | ||
locale = userLanguages.find(l => availableLocales.indexOf(l) >= 0) ?? availableLocales[0]; |
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.
Should we push a default fallback locale into settings? It probably shouldn't happen, but 🤷
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.
Well, there's already the language
value in the store that determines the language of the whole app, which is included in the userLanguages
list. I'm not sure if an additional metadataFallbackLocale
really makes sense, wouldn't it be identical to language
in most usage scenarios?
Any update on this? |
It's been over a year, any update on this? If this is still considered relevant, I can rebase my changes on top of the latest changes. |
This admittedly huge changeset refactors the way the correct language value for a given property value is determined. A recent change in the Manifesto library made it possible to pass a list of languages (in descending order of preference) to the
PropertyValue.getValue
andPropertyValue.getValues
methods, instead of relying on a single default locale that would be set when parsing the manifest. This allows for a better user experience, since we can now dynamically respond to changes in the user's language preferences without having to re-parse the manifest. Additionally, we can make use of the browser's language preferences to better match the user's language abilities.However, this required a substantial reworking of quite a few parts of Mirador, namely:
config.userLanguages
redux state variable that has the list of languages in descending order of preference (as returned by i18next.languages after setting the configured language)getValue
on a property value was changed to retrieve the user languages from the store and pass them togetValue
. Additionally, for property values that are displayed in the companion window, where the locale can be overridden separately from the global language, selectors are extended to take a thirdoverrideLanguages
parameter that allows customization of the languages passed togetValue
/getValues
LocalePicker
(if enabled) now will select the next-best available language according to the langauge pereferences, if the desired language is not part of the metadata.As a whole, these changes now allow on-the-fly switching of languages via both the global language selector and the companion window locale picker for all property values parsed from the manifest, with support for falling back according to the user's client language preferences.
I'd be grateful for a careful review, I had quite a bit of trouble keeping all the parts involved in my head, there might be things I have missed or not done as elegant as they could be.
The changes can be tested in this new integration test:
https://deploy-preview-3482--mirador-dev.netlify.app/__tests__/integration/mirador/i18n.html