ionic-team / ionic-stencil-conference-app

A conference app built with Stencil to demonstrate Ionic
MIT License
90 stars 30 forks source link

how to go for i18n support? #69

Open ghost opened 6 years ago

ghost commented 6 years ago

Right now there is no support for internationalisation in this app. Considering this is the most feature rich inspiration for building an ionic-stencil app, can someone guide on how to add i18n to this?

amazzoccone commented 6 years ago

👍 @vivekdwivedi did you find a solution to this?

ghost commented 6 years ago

Not yet

simonhaenisch commented 6 years ago

It's quite simple to implement a service yourself in a couple of lines:

// localization.ts

export let translation: Translation;

export const loadTranslation = async (locale = 'en-us') => {
  translation = await fetch(`/assets/i18n/${locale}.json`).then(async res => res.json());
};

interface Translation { /* for Intellisense */ }
// app-root.tsx

import { loadTranslation, translation } from '../services/localisation';

@Component({ tag: 'app-root' })
export class AppRoot {
  async componentWillLoad() {
    await loadTranslation();
  }

  render() {
    return (
      <ion-app>
        <h1>{translation.SOME_KEY}</h1>
      </ion-app>
    );
  }
}

If you want Intellisense in your .json files as well, you can define a JSON schema in the VS Code workspace settings (.vscode/settings.json):

{
  "json.schemas": [
    {
      "fileMatch": ["pwa/src/assets/i18n/*.json"],
      "schema": { /* ... */ }
    }
  ]
}

There are also tools to convert a JSON schema into a Typescript interface or the other way round.


The only issue with this is that if you want to hot-reload your components whenever translation changes (i. e. you load a different locale through a user setting), then you will need to implement something smarter to trigger a re-render (e. g. add a translation state in app-root and pass that through your app via props or stencil-state-tunnel or redux or something else). My very simplistic but not so user-friendly approach for the moment is to save the user's locale selection in local storage and reload the window after they change it.

Another thing I'm trying is to use Typescript files to define the translations rather than JSON files... means I wouldn't need to fetch anything at runtime if I just bundle them all (not sure whether there is a good way to dynamically import those at the moment).

davidquintard commented 5 years ago

Since pipes does not exist in stencil, is it a bad practice to create a component "translator" and so use it like this ?

render() {
    return (
      <ion-app>
        <translator key="SOME_KEY"></translator>
      </ion-app>
    );
  }
simonhaenisch commented 5 years ago

@pairmix doesn't sound so bad either... how does your translator component know which locale to use though?

BTW Angular pipes are just syntactic sugar for function calls, e. g. 'SOME_KEY' | translate could also just be implemented as translate('SOME_KEY').

davidquintard commented 5 years ago

The only way i see is to add locale to component param.

render() {
    return (
      <ion-app>
        <translator key="SOME_KEY" locale="fr_FR"></translator>
      </ion-app>
    );
  }

I have no idea how to implement such pipes, i'm not an expert. I just want to migrate my ionic app into stencil with minimum changes.

arjunyel commented 5 years ago

Some people on the Slack channel said they use Polyglot or i18next http://airbnb.io/polyglot.js/ https://www.i18next.com/