0.0.6 โ€ข Published 3 years ago

fluent-typescript v0.0.6

Weekly downloads
3
License
MIT
Repository
github
Last release
3 years ago

fluent-typescript

๐Ÿ“ฆ Generate automatically TypeScript declarations for Fluent files

Fluent is a Mozilla's programming language for natural-sounding translations. And fluent-typescript is a tool to automatically generate type definitions for its mensagens. So you'll have safer changes on your translates messages by types safes provided by TS. Never more will have a missing variable or forget to delete an old message. Sounds like magic, right?

Fluent client supported:

:warning: It's a working in process project! At this moment, you should not use it on production!

How to use

As the first step, you need to install this package, of course:

> npm install fluent-typescript --save-dev
- or -
> yarn add fluent-typescript --dev

The following steps depends on which Fluent client that you are using:

vanilla

You could check a complete example on /example-vanilla folder. Check its readme.

Step by step:

1 - Add this script on your package.json config:

{
  "scripts": {
    "fluent-typescript": "./node_modules/.bin/fluent-typescript vanilla ./assets/locales/"
  }
},

The argument ./assets/locales/ is the path where the type definition file will be saved.

2 - Run fluent-typescript:

> npm run fluent-typescript

Now, your FTL files will be compiled into a .d.ts. The last remaining step is import it on our code.

3 - Add a cast on FluentBundle call:

const bundle = new FluentBundle('pt-br') as FluentBundleTyped

Finish! Now you have amazing types on your translations messages ๐ŸŽ‰

react-18next

You could check a complete example on /example-react-18next folder. Check its readme.

1 - You also need to install @fluent/bundle

> npm install @fluent/bundle --save-dev
- or -
> yarn add @fluent/bundle --dev

2 - Add this script on your package.json config:

{
  "scripts": {
    "fluent-typescript": "./node_modules/.bin/fluent-typescript react-18next ./assets/locales/"
  }
},

The argument ./assets/locales/ is the path where the type definition file will be saved.

3 - Run fluent-typescript:

> npm run fluent-typescript

Now, your FTL files will be compiled into a .d.ts, and the type of t function returned by useTranslation will be patched, working out-of-the-box!

:warning: At this moment, it only works with useTranslation. Always when possible, prefer to use that instead of Trans or withTranslation, because you have type safe only with t function.

Finish! Now you have amazing types on your translations messages ๐ŸŽ‰

fluent-react

You could check a complete example on /example-fluent-react folder. Check its readme.

1 - Add this script on your package.json config:

{
  "scripts": {
    "fluent-typescript": "./node_modules/.bin/fluent-typescript fluent-react ./assets/locales/"
  }
},

The argument ./assets/locales/ is the path where the type definition file will be saved.

2 - Run fluent-typescript:

> npm run fluent-typescript

Now, your FTL files will be compiled into a .d.ts, and the type of Localized component from @fluent/react will be patched!

To use the patched version of Localized, you should add the prop typed. For example:

-<Localized id='hello' vars={{ firstName, lastName }}>
+<Localized typed id='hello' vars={{ firstName, lastName }}>
  <h1>Hello!</h1>
</Localized>

:warning: At this moment, it only works with Localized. Always when possible, prefer to use that instead of useLocalization, because you have type safe only with Localized component.

Finish! Now you have amazing types on your translations messages ๐ŸŽ‰

Flags

--no-watch

If you just want to emit the type definition, without running the watcher, you can use the flag --no-watch.

For instance:

> fluent-typescript vanilla ./assets/locales/ --no-watcha

How types are compiled

Asymmetric translations

tl;dr: You should always use all variables that a message could need.

Detailed explanation:

Let's say that we have a hello message on our application and we should translate that to Japanese and Portuguese. Since in Japanese is more common to use the last name, and in Portuguese is more natural to use the first name, we'll have that:

# locales/jp/translations.ftl
hello = ใ“ใ‚“ใซใกใฏ{ $lastName }

# locales/pt-br/translations.ftl
hello = Olรก { $firstName }

Despite that in practice we could just use firstName or lastName, our type definition file want to be most safe that could, so you'll always need to use all possibles arguments required by a message:

bundle.formatPattern(helloMessage.value, { firstName: 'Macabeus', lastName: 'Aquino' }) // ok
bundle.formatPattern(helloMessage.value, { firstName: 'Macabeus' }) // error
bundle.formatPattern(helloMessage.value, { lastName: 'Aquino' }) // error

Analogously on a message with selector. You should always use all variables:

award =
  { $place ->
     [first]  You won first! Your prize is { $amount } bitcoins
    *[other] You won { $place }! Congratulations!
  }
bundle.formatPattern(helloMessage.value, { place: 'first', amount: 0.1 }) // ok
bundle.formatPattern(helloMessage.value, { place: 'second', amount: 0 }) // ok
bundle.formatPattern(helloMessage.value, { place: 'first' }) // error
bundle.formatPattern(helloMessage.value, { place: 'second' }) // error

Developing fluent-typescript

When developing fluent-typescript, is important to build and watch, so you could check the changes automatically on the examples apps:

> npm run start

Check the readme on each example's folders to learn how to run them.

You also could and run tests:

> npm run test
0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

4 years ago

0.0.3

4 years ago