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

RFC: i18n #419

Closed
claviska opened this issue Apr 16, 2021 · 69 comments
Closed

RFC: i18n #419

claviska opened this issue Apr 16, 2021 · 69 comments
Assignees
Labels
i18n Anything related to internationalization.

Comments

@claviska
Copy link
Member

claviska commented Apr 16, 2021

It's time to start thinking about i18n. This discussion will be scoped to localization, whereas #191 will focus on RTL support.

There is a need for common labels in components that need to be localized. An example is in dialog/drawer/tab/tag, which all feature a built-in close button. Currently, the buttons don't have a label so screen readers don't announce them properly.

Important: I don't expect there to be many terms, nor do I want users to rely on Shoelace to power their app's localization. At this point in the library's development, a simple solution is preferred over a robust one.


Updated to reflect new requirements and information.

@claviska claviska added this to the v2.0.0 release milestone Apr 16, 2021
@claviska claviska self-assigned this Apr 16, 2021
@claviska claviska added the i18n Anything related to internationalization. label Apr 16, 2021
@mcjazzyfunky

This comment has been minimized.

@prantlf

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@hanc2006

This comment has been minimized.

@prantlf

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@hanc2006

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@claviska

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@claviska

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@claviska

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@claviska

This comment has been minimized.

@claviska
Copy link
Member Author

I'm trying to keep the discussion focused on a solution instead of hypotheticals so we don't get derailed. I feel like we're close and there have been some good suggestions in this thread.

Please don't take me hiding comments personally. 💙

@mcjazzyfunky

This comment has been minimized.

@claviska

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@hanc2006

This comment has been minimized.

hanc2006 added a commit to hanc2006/shoelace that referenced this issue Jul 23, 2021
@mcjazzyfunky

This comment has been minimized.

@mcjazzyfunky

This comment has been minimized.

@claviska
Copy link
Member Author

claviska commented Dec 6, 2021

Thanks again for all the discussions and ideas thus far. Trying to determine the best way to move forward with localization — without being too opinionated — has been an exhausting undertaking. This is one of the last remaining building blocks before a stable 2.0 can be released.

Here's a summary of the approach I've decided to take based on feedback, discussions, and experimentations throughout the year. First, a few things need to be clearly identified:

  • It's very rare (but not impossible) that a page will use more than one language
  • There's no efficient way to detect the current language or direction without expensive DOM traversal
  • The page language is always defined by <html lang="...">
  • Subsequent languages used on the page are defined using lang on specific elements, e.g. <sl-tab lang="es">

Based on this:

  • Shoelace components detect the locale using this.lang || document.documentElement.lang
    • We are not honoring lang attributes on ancestor elements by design for performance reasons. That is, wrapping <div lang="..."> around a component will not localize the component.
  • Shoelace uses English as the default/fallback language. Additional translations can be imported by the consumer statically or dynamically.

Most of this doesn't matter to end users. What does matter to end users is how simple it is to load Shoelace in a specific language:

<html lang="es">
  <head>
    <link rel="stylesheet" href="/shoelace/dist/themes/light.css">
    <script type="module" src="/shoelace/dist/shoelace.js"></script>
    <script type="module" src="/shoelace/dist/translations/es.js"></script>
  </head>

  <body>
    ...
  </body>
</html>

In most cases, <html lang> is already set so the only thing 99.9% of users need to do is import their target language. If they update <html lang>, all localized components will update automatically.


That said, I've released 2.0 of @shoelace-style/localize which uses the Reactive Controller pattern. This results in a small, elegant DX for component developers.

Here's a Lit component localizing a term, date, and number:

import { LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
import { LocalizeController } from '@shoelace-style/localize/dist/lit.js';

@customElement('my-element')
export class MyElement extends LitElement {
  private localize = new LocalizeController(this);

  @property() lang: string;

  render() {
    return html`
      <!-- Term -->
      ${this.localize.term('hello')}

      <!-- Date -->
      ${this.localize.date('2021-09-15 14:00:00 ET'), { month: 'long', day: 'numeric', year: 'numeric' }}

      <!-- Number/currency -->
      ${this.localize.number(1000, { style: 'currency', currency: 'USD'})}
    `;
  }
}

I've already implemented these changes in a local branch and I'm finishing up documentation before merging it into next. I expect to have all existing components fully localized in the next day or two.

@claviska
Copy link
Member Author

claviska commented Dec 7, 2021

I'm closing this since localization has been implemented. There's still work to be done to support RTL languages, but the scope of this issue is complete finally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
i18n Anything related to internationalization.
Projects
None yet
Development

No branches or pull requests

4 participants