-
Notifications
You must be signed in to change notification settings - Fork 841
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
Allow EuiI18n | string everywhere translated text is expected #2474
Comments
I have, as of late, been frustrated that we don't also just have a simple function that returns a string for this. Kibana does have something like this: title={i18n.translate('xpack.lens.indexPattern.noPatternsLabel', {
defaultMessage: 'No index patterns',
})} |
Thoughts on the existing setup, some paths we could take, and my opinion at the end Existing implementation with React componentsRelying on React components:
Because of these benefits, we originally opted to use the render props pattern as the sole means of implementing i18n in EUI. Other ideasReact hookWe've discussed and wanted to add a useI18n hook which would provide the same functionality, but be cleaner. I believe this could be used directly in e.g.
It would also be usable outside of attributes, const [button, buttonActive] = useI18n(
['euiColumnSorting.button', 'euiColumnSorting.buttonActive']
['Sort fields', 'fields sorted']
);
...
return (
<EuiButtonEmpty
size="xs"
iconType="sortable"
color="text"
className={controlBtnClasses}
data-test-subj="dataGridColumnSortingButton"
onClick={() => setIsOpen(!isOpen)}>
{numberOfSortedFields > 0
? `${numberOfSortedFields} ${buttonActive}`
: button}
</EuiButtonEmpty>
); Drawback: Hooks cannot be used in logic branches (e.g. if statements, branches), code that would be written as:
would need to be written as
Babel pluginInstead of a hook, we can add a magic function that looks identical to the hook - it's just function after all - that is converted to the existing EuiI18n structure, e.g.
transparently becomes
Benefits: Ease of the hooks use without the no-branching requirement Drawbacks:
Non-React serviceSimilar to Kibana's
Opinionhidden so you can form your own thoughts firstThere are a lot of pros for keeping the functionality tied to React's context & render flows, and the drawbacks on a non-React service are far from insignificant. I strongly recommend avoiding that solution. I think hooks make more sense in EUI than a magic function. The two drawbacks of hooks are potential bugginess when used conditionally and less readability when needing to use those values conditionally. The bugginess is mitigated by the A magic function + babel plugin solves both the readability & conditionality problems, but strains the mental model and requires effort from consumers if they want to use the magic in their application. Hooks are well-known and understood within React, and consuming applications could use our hook directly without any additional education or setup. With a magic function, there is some additional documentation/education for consumers who'd also need changes to their babel config to use the same pattern in their app. |
Hello - I've just started to work with eui in my project - it's amazing :) About the hook - you want the hook only to access context - then you can return helpers in any shape you like :) // 1) conditionals
const {i18n} = useI18n();
return isThing
? <a aria-label={i18n('firstToken', 'some value')} />
: <button aria-label={i18n('secondToken', 'some other value')} />
// 2) or something smarter
const {i18n} = useI18n<TMappingsShape>('myScope'); // firstToken => "myScope.firstToken" :)
const secondTxt = i18n('secondToken', 'some value')
return isThing
? <a aria-label={i18n('firstToken', 'some value')} />
: <button aria-label={secondTxt} />
// 3) maybe providing some local mappings "from the bottom" ?
const scopedMapping = {
defaults: {
localToken: "hello"
}
}
const {i18n} = useI18n<TGlobalMappingsShape>('scope', scopedMapping);
return <button aria-label={i18n('localToken')}>{i18n('globalButtons.okMsg')}</button> Actually, I'm going to play with it a bit in my project - but I have a tiny roadblock - could you consider exporting eui/src/components/context/context.tsx Line 38 in 5d29a4a
Cheers! |
It is, effectively, exported - though if the setup does not support your needs, I'm curious what you're doing :) The context consumer is exported through EuiI18nConsumer and its provider is wrapped by EuiContext. This split is intentional, to ensure that a "required" context value is provided (or at least known and considered) if/when there is a new EUI context. Essentially, we want any consumer to be usable independently but require all providers be set together. |
While reviewing a PR making use of
EuiI18n
, I came across this fairly boilerplate code making use of the render method to get the translated text:It got me wondering, can we not generically allow HTML attributes to be specified as
EuiI18n | string
parameters, thus bridging the gap and enabling simpler usage of translation?Then could we take this a step further and push that into all EUI components, like
EuiNavDrawerGroup
'slabel
s.The text was updated successfully, but these errors were encountered: