Fluent is an great DSL for localization. This project allows you to generate TypeScript types for yours .ftl
files.
Npm:
npx fluent2ts
Bun:
bunx fluent2ts
Yarn:
yarn dlx fluent2ts
Pnpm:
pnpm exec fluent2ts
After that, the locales.types.ts
file is automatically generated in the src
folder. You can also change this path by specifying the -o
(or --output
) argument. For example - npx fluent2ts -o src/some/i18n.ts
.
You can also specify the glob pattern to search for .ftl
files are specified after the command. For example npx fluent2ts locales/**/*.ftl
. By default it is **/*.ftl
.
You can also use watch mode
and regenerate the types when the file has been modified. To do this, simply specify the --watch
(or -w
) argument. For example, npx fluent2ts -w
.
2024-05-28.21-03-51.mp4
For example for this:
# Simple things are simple.
hello-user = Hello, {$userName}!
# Complex things are possible.
shared-photos =
{$userName} {$photoCount ->
[one] added a new photo
*[other] added {$photoCount} new photos
} to {$userGender ->
[male] his stream
[female] her stream
*[other] their stream
}.
The following will be generated:
import type {
FluentBundle,
FluentVariable,
Message as FluentMessage,
// @ts-ignore
} from "@fluent/bundle";
export interface LocalesMap {
"hello-user": {
userName: FluentVariable;
};
"shared-photos": {
userName: FluentVariable;
photoCount: FluentVariable;
userGender: FluentVariable;
};
}
export interface Message<Key extends keyof LocalesMap> extends FluentMessage {
id: Key;
}
export interface TypedFluentBundle extends FluentBundle {
getMessage<Key extends keyof LocalesMap>(key: Key): Message<Key>;
formatPattern<Key extends keyof LocalesMap>(
key: Key,
...args: LocalesMap[Key] extends never ? [] : [args: LocalesMap[Key]]
): string;
formatPattern<Key extends keyof LocalesMap>(
key: Key,
args: LocalesMap[Key] extends never ? null : LocalesMap[Key],
errors?: Error[] | null
): string;
}