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

Unified strategy for providing localized labels within components #1090

Closed
4 of 5 tasks
jattasNI opened this issue Mar 1, 2023 · 4 comments · Fixed by #1388
Closed
4 of 5 tasks

Unified strategy for providing localized labels within components #1090

jattasNI opened this issue Mar 1, 2023 · 4 comments · Fixed by #1388
Assignees

Comments

@jattasNI
Copy link
Contributor

jattasNI commented Mar 1, 2023

🧹 Tech Debt

Labels for Icons

There are several places where components display icons. Each of these might benefit from:

  1. setting title so that sighted users can hover over them to see the icon explained in a tooltip
  2. setting aria-label or other attributes so that screen reader users can understand their purpose
    Those strings should be localized. Since we've decided that localization is an application concern and not a Nimble concern, we need to provide (hopefully consistent) APIs for clients to supply these strings.

We may also decide not to set title and to exclude the icon from the accessibility tree if its meaning is provided in other ways. We should consult with Leslie and with web best practice docs to come up with guidance for this.

The icons we've identified so far:

  1. increment/decrement buttons on numeric text input A11y labels on increment/decrement buttons of numeric are not localized #617
  2. action menu button in table cells Provide an action menu within a table cell #859
  3. sort icon in table header (and soon other icons from UX Design for basic column/row interactions #885 like grouping, collapse all, column menu)
  4. banner and tooltip severity

This will also inform related work like the following, though the solution might be different:

  1. Table allows configuration of icon column type #1013
  2. icons as the primary content of a table column header

Other Labels in Nimble Components

We also have other labels in Nimble components that will need a way for clients to localize them, such as the banner dismiss button, buttons (expand/collapse group, collapse all groups, etc) in the table, and menu items in the table.

Goals

  1. Document policy about when providing this content is necessary
  2. Decide on an approach that's consistent across components
  3. Document that approach
  4. Ensure the work to adopt the approach for existing and known future use cases is tracked

Possible Implementations

See HLD: #1272

Tasks

  • Write HLD
  • Create nimble-label-provider-core and nimble-label-provider-table, and uptake them in nimble-components
  • Add label provider integration for Angular and Blazor
  • Remove banner dismissButtonLabel (obsolete due to dismiss label on LabelProviderCore)
  • Revisit per-component accessibility notes doc and try to document them in Storybook instead
@jattasNI jattasNI added tech debt triage New issue that needs to be reviewed labels Mar 1, 2023
@m-akinc m-akinc added needs investigation Further research is needed to identify solution and removed triage New issue that needs to be reviewed labels Mar 7, 2023
@mollykreis
Copy link
Contributor

We need to make sure that the solution is scalable because some components, such as the table will have many strings that need to be localized. For example:

  • label & tooltip for Collapse All button
  • label & tooltip for Collapse Group/Row button
  • label & tooltip for Toggle selection of all rows checkbox for whole table & group rows
  • label & tooltip for Toggle selection checkbox
  • Menu item text for items in the column menus -- Sort ascending, Sort descending, Group by column, Size to fit, etc

@rajsite
Copy link
Member

rajsite commented Apr 24, 2023

Options brainstorming:

Slots

Create slots per localized string on the element.

<nimble-table>
   <span slot="collapse-all-button-label">Hello World</span>
</nimble-table>

Pros:

  • Useful for mixed content (if that is even needed, maybe not?)
  • Can maybe make shareable slotted content within a framework
    • Angular: Create a shared component that emits elements with those slots
    • Blazor: I expect a blazor component written that way would work too
  • Slots can have default content easily

Cons:

  • DOM gets littered with many additional elements for providing localized strings
  • Lots of duplicated slotted content / elements. Have to emit into every table element as children.

Attributes

Create attribute per localized string on the element.

<nimble-table
    collapse-all-button-label="Hello World"
></nimble-table>

Pros:

  • Easy discovery of available properties? Type checked in Angular at least

Cons:

  • Maybe not as easy to share / reuse attribute configuration?
    • Angular: Might need to write a custom directive that will emit the attributes onto the host. I think that works
    • Blazor: ?
  • Lots of duplicated attributes. Have to emit into every table element as children.
  • Only text content (maybe that's okay)

Design Tokens

Conceptually the localized strings are very similar to the sharing pattern of Design Tokens. Vast majority of the time you want to use the same value (increment button text or collapse button text is not control instance specific) but want to adjust to a global config, i.e. theme or language. But also want to be able to override for specific controls as needed.

Create non-css property design tokens, similar to the theme and direction design tokens.
Use the theme-provider to define the value.

<nimble-theme-provider
    table-collapse-all-button-label="Hello World"
>
<nimble-table></nimble-table>
</nimble-theme-provider>

Pros:

  • Easy discovery of localized string configuration. They are all on the theme-provider.
  • Can configure once for the whole page in one spot, does not need to be per control. Much fewer duplicated attributes / slotted elements in the page.
  • Can override for specific elements as needed by wrapping in a theme-provider.
  • Can configure to be attribute or slotted on the theme provider. But if don't need mixed content then attribute makes sense.
  • User provided control-specific content should still be provided via attributes / slots. This is for control provided content (the table control defines the collapse button, not the user).

Cons:

  • Abuse of the tokens system / not intended use-case?
  • Maybe not very extensible? Only nimble-components defined within nimble can add new attributes to the theme-provider.
    • Custom columns cannot plugin new properties they may need on the theme-provider. Maybe not a big deal? Then can just use attributes / slots? The custom columns we offer directly from nimble could register their localized strings on the theme-provider...

@atmgrifter00
Copy link
Contributor

As part of this PR, we are lowering the threshold for the Lighthouse Accessibility score. This is to allow the collapse-all button to be submitted without it having a localizable label. When we address this issue we need to re-up the threshold to 90.

@jattasNI
Copy link
Contributor Author

The theme provider is a cool idea. Another pro is that we could likely single-source the strings in a way that each SLE app doesn't need their own list that would need to be updated every time Nimble adds a new string. For example, we could create sl-theme-provider in systemlink-lib-angular with a child nimble-theme-provider that has all the strings tagged for i18n.

half formed brainstorming👇

That made me realize that it would be cool to have a way for apps to get a list of English Nimble strings that need to be translated. Ideally that list could be imported into the app's localization infrastructure so that they'd automatically get the English version, automatically trigger translation to other languages, and automatically pick up new strings that we add.

How do Angular apps extract strings from their dependent libraries? Could we mark up nimble-angular in the same way we do systemlink-lib-angular and have apps translate the strings inside it? Then it'd be nimble-angular's responsibility to consume the translated strings to configure each component, possibly using one of the approaches above. (I'm not sure when this code would run)

For Blazor, is there a way we could publish a resx file of English strings for apps to translate and then have NimbleBlazor use the translated resx files?

@m-akinc m-akinc moved this to Current Iteration in Nimble Design System Priorities May 2, 2023
@msmithNI msmithNI self-assigned this May 2, 2023
@msmithNI msmithNI moved this from Current Iteration to In progress in Nimble Design System Priorities May 5, 2023
@msmithNI msmithNI changed the title Unified strategy for providing localized title and aria label for icons within components Unified strategy for providing localized labels within components Jun 9, 2023
@msmithNI msmithNI removed the needs investigation Further research is needed to identify solution label Jun 9, 2023
msmithNI added a commit that referenced this issue Jun 14, 2023
# Pull Request

## 🤨 Rationale

#1090

## 👩‍💻 Implementation

N/A (HLD and doc updates)

## 🧪 Testing

N/A

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
msmithNI added a commit that referenced this issue Jul 13, 2023
# Pull Request

## 🤨 Rationale

Partially addresses #1090 (Angular/Blazor changes will be in subsequent
PRs)

## 👩‍💻 Implementation

See the
[HLD](https://github.com/ni/nimble/tree/main/specs/labels-and-localization)
for the implementation plan for the label providers.

This PR creates the LabelProvider classes in nimble-components, and
creates/uptakes label DesignTokens in `nimble-banner`,
`nimble-number-field`, and `nimble-table`

## 🧪 Testing

- Verified that each label appears in the expected spots in the DOM for
the affected components. Note that the current labels are mostly not
user-visible (except that grouped table columns will now have a
'Grouped' tooltip on that icon in the header). Future table changes
(i.e. the column header menu) will introduce new visible label tokens.
- Added autotests
- For label providers: verify token naming, and that label provider
attribute updates result in token updates
- For controls using labels: verify that the label token values are used
in the controls as expected
- Updated
[Storybook](https://60e89457a987cf003efc0a5b-tbdnyzeaxa.chromatic.com/)
- Each component using labels has a new "Localizable labels" row in
their Storybook controls/API section
- Under "Tokens" is a new ["Label Providers"
section](https://60e89457a987cf003efc0a5b-tbdnyzeaxa.chromatic.com/?path=/docs/tokens-label-providers--docs).
Each label provider has a section with a table that has the token name,
JS property name, HTML attribute name, and English default value of the
label.

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
- Updated nimble-components Readme and Contributing docs with
Localization sections.
msmithNI added a commit that referenced this issue Jul 24, 2023
# Pull Request

## 🤨 Rationale

Partially addresses #1090 (Blazor changes will be a subsequent PR)

## 👩‍💻 Implementation

See the
[HLD](https://github.com/ni/nimble/tree/main/specs/labels-and-localization)
for the implementation plan for the label providers.

This PR adds in nimble-angular:
- `NimbleLabelProviderCoreDirective` and
`NimbleLabelProviderTableDirective` (standard wrappers)
- `NimbleLabelProviderCoreWithDefaultsDirective` and
`NimbleLabelProviderCoreWithDefaultsDirective`: Apps will use these
directives to automatically initialize the label providers with the
localized strings (which use `$localize` from `@angular/localize`, which
is now an optional peer dependency for nimble-angular)
- 2 new secondary entry points, `@ni/nimble-angular/label-provider/core`
and `@ni/nimble-angular/label-provider/table`
- In my prototype, until I added separate entry points, as soon as an
app pulled in new nimble-angular version, Nimble's localized strings
would be pulled into their resource files (even without depending on the
new modules). Whereas, with secondary entry points, the app needs to
explicitly import `NimbleLabelProviderCoreModule` and/or
`NimbleLabelProviderTableModule` to get the strings pulled in, which
seemed like better behavior.

## 🧪 Testing

- Added autotests for new directives
- Update Angular example app to pull in the label providers the same way
apps will, i.e. `<nimble-label-provider-core
withDefaults></nimble-label-provider-core>`. Note that there's not
additional translation logic in the example app though, so this just
uses the English strings (so basically a no-op, just there as an
example).

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
- Updated Readme and contributing docs for nimble-angular with
Localization info
msmithNI added a commit that referenced this issue Jul 24, 2023
# Pull Request

## 🤨 Rationale

Partially addresses #1090 (a few small followup items remain in the work
item once Angular/Blazor PRs go in)

## 👩‍💻 Implementation

See the
[HLD](https://github.com/ni/nimble/tree/main/specs/labels-and-localization)
for the implementation plan for the label providers.

The Blazor integration is fairly rudimentary (just the label provider
APIs). To fully use them in a Blazor app, the client apps need to handle
localizing the strings themselves, as outlined in the Readme updates.

## 🧪 Testing

Added basic autotests. Added label providers to example app MainLayout
(matches guidance from the Readme).

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
- Updated Readme to add Localization guidance. Also added brief guidance
on NimbleThemeProvider since it wasn't mentioned in this Readme.
msmithNI added a commit that referenced this issue Jul 25, 2023
# Pull Request

## 🤨 Rationale

Follow-up tech debt from adding the label providers (#1090).

The banner's close button text can now be controlled by the
`popupDismiss` label on `nimble-label-provider-core`, so the
`dismissButtonLabel` property on `nimble-banner` is no longer needed. We
decided to remove the property in [PR discussion on
#1328](#1328 (comment)).

## 👩‍💻 Implementation

Remove property and update tests.

## 🧪 Testing

Updated autotests / Storybook.

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
@msmithNI msmithNI linked a pull request Jul 25, 2023 that will close this issue
1 task
msmithNI added a commit that referenced this issue Jul 27, 2023
# Pull Request

## 🤨 Rationale

Resolves #1090

In [PR discussion on
#1272](#1272 (comment)),
we decided that the per-component accessibility notes would be better
documented in Storybook (by the other component docs), instead of in
accessibility.md.

Resolves #1393 

## 👩‍💻 Implementation

For components with accessibility notes not already documented in
Storybook:
- Create an mdx docs page for them, if it wasn't already present. Based
on PR comments on the recent PR by Jesse, I think this is the general
direction we're going for component docs.
- Add a Usage Docs / Accessibility section at the bottom, and add the
notes from accessibility.md. The button/spinner mdx have these sections,
so again following the existing patterns.

## 🧪 Testing

Manual verification in Storybook.

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
@msmithNI msmithNI moved this from In progress to Done in Nimble Design System Priorities Jul 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging a pull request may close this issue.

6 participants