Skip to content

Commit

Permalink
1.0: Fluent, Deno support, docs, and more (#20)
Browse files Browse the repository at this point in the history
Co-authored-by: Roj <[email protected]>
Co-authored-by: EdJoPaTo <[email protected]>
Co-authored-by: KnorpelSenf <[email protected]>
Co-authored-by: Roj <[email protected]>
Co-authored-by: Loskir <[email protected]>
  • Loading branch information
6 people authored Sep 18, 2022
1 parent 15d74ca commit 632615a
Show file tree
Hide file tree
Showing 49 changed files with 1,265 additions and 939 deletions.
12 changes: 3 additions & 9 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{yml,yaml}]
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 80
1 change: 0 additions & 1 deletion .gitattributes

This file was deleted.

20 changes: 0 additions & 20 deletions .github/dependabot.yml

This file was deleted.

32 changes: 32 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Build

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: denoland/setup-deno@v1
with:
deno-version: v1.x

- name: Format
run: deno fmt --check

- name: Lint
run: deno lint

- name: Check
run: deno check src/mod.ts

- name: Test
run: deno task test

- name: Backport
run: deno task dnt 0.0.0-workflow.0
29 changes: 0 additions & 29 deletions .github/workflows/nodejs.yml

This file was deleted.

9 changes: 3 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
.nyc_output
/*-*.*.*.tgz
coverage
dist
node_modules
yarn.lock
out/
node_modules/
package-lock.json
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

6 changes: 6 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"recommendations": [
"denoland.vscode-deno",
"editorconfig.editorconfig"
]
}
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"deno.enable": true,
"deno.lint": true,
"[typescript]": {
"editor.defaultFormatter": "denoland.vscode-deno"
}
}
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)
MIT License

Copyright (c) 2016 Vitaly Domnikov
Copyright (c) 2022 Dunkan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
105 changes: 68 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,90 @@
# i18n for grammY and Telegraf
# grammY i18n

Internationalization middleware for [grammY](https://github.com/grammyjs/grammy) and [Telegraf](https://github.com/telegraf/telegraf).
Internationalization plugin for [grammY](https://grammy.dev) based on
[Project Fluent](https://projectfluent.org). Check out
[the official documentation](https://grammy.dev/plugins/i18n.html) for this
plugin.

## Installation

```bash
Node.js

```sh
npm install @grammyjs/i18n
```

Deno

```ts
import { I18n, I18nFlavor } from "https://deno.land/x/grammy_i18n/mod.ts";
```

## Example

```plaintext
yaml and json are ok
Example directory structure:
├── locales
│   ├── en.yaml
   ├── en-US.yaml
   ├── it.json
   └── ru.yaml
└── bot.js
Example project structure:

```
.
├─ locales/
├── en.ftl
├── it.ftl
└── ru.ftl
└── bot.ts
```

```js
import {Bot, session} from 'grammy'
import {I18n, pluralize} from '@grammyjs/i18n'
Example bot
[not using sessions](https://grammy.dev/plugins/i18n.html#without-sessions):

```ts
import { Bot, Context } from "https://deno.land/x/grammy/mod.ts";
import { I18n, I18nFlavor } from "https://deno.land/x/grammy_i18n/mod.ts";

// Create a new I18n instance.
const i18n = new I18n({
defaultLanguageOnMissing: true, // implies allowMissing = true
directory: 'locales',
useSession: true,
})
defaultLocale: "en",
directory: "locales",
});

// Also you can provide i18n data directly
i18n.loadLocale('en', {greeting: 'Hello!'})
// For proper typings and auto-completions in IDEs,
// extend the `Context` using `I18nFlavor`.
type MyContext = Context & I18nFlavor;

const bot = new Bot(process.env['BOT_TOKEN']!)
bot.use(session())
bot.use(i18n.middleware())
// Create a bot as usual, but use the modified Context type.
const bot = new Bot<MyContext>(""); // <- Put your bot token here

// Start message handler
bot.command('start', async ctx => ctx.reply(ctx.i18n.t('greeting')))
// Tell the bot to use the middleware from the instance.
// Remember to register this middleware before registering
// other middlewares.
bot.use(i18n.middleware());

bot.command("start", async (ctx) => {
// Use the method `t` or `translate` from the context and pass
// in the message id (key) of the message you want to get.
await ctx.reply(ctx.t("greeting"));
});

bot.start()
// Start your bot
bot.start();
```

A full example for both grammY and Telegraf are in the [examples folder](/examples).
See the [documentation](https://grammy.dev/plugins/i18n.html) and
[examples/](examples/) for more detailed examples.

## User context
## Credits

Commonly used Context functions:
Thanks to...

```ts
bot.use(ctx => {
ctx.i18n.locale() // Get current locale
ctx.i18n.locale(code) // Set current locale
ctx.i18n.t(resourceKey, [data]) // Get resource value (data will be used by template engine)
});
```
- Slava Fomin II ([@slavafomin](https://github.com/slavafomin)) for the Node.js
implementation of the
[original Fluent plugin](https://github.com/the-moebius/grammy-fluent) and the
[better Fluent integration](https://github.com/the-moebius/fluent).
- Roj ([@roj1512](https://github.com/roj1512)) for the
[Deno port](https://github.com/roj1512/fluent) of the original
[@fluent/bundle](https://github.com/projectfluent/fluent.js/tree/master/fluent-bundle)
and
[@fluent/langneg](https://github.com/projectfluent/fluent.js/tree/master/fluent-langneg)
packages.
- Dunkan ([@dcdunkan](https://github.com/dcdunkan)) for the
[Deno port](https://github.com/dcdunkan/deno_fluent) of the
[@moebius/fluent](https://github.com/the-moebius/fluent).
- And all the previous maintainers and contributors of this i18n plugin.
22 changes: 22 additions & 0 deletions deno.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"fmt": {
"files": {
"exclude": ["./out/"]
}
},
"lint": {
"files": {
"exclude": ["./out/"]
}
},
"tasks": {
"example": "cd examples && deno run --allow-net --allow-read deno.ts",
"test": "deno test --allow-read --allow-write",
"dnt": "deno run --allow-env --allow-net --allow-read --allow-run --allow-write scripts/dnt.ts"
},
"test": {
"files": {
"exclude": ["./out/"]
}
}
}
60 changes: 60 additions & 0 deletions examples/deno.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
Bot,
Context,
session,
SessionFlavor,
} from "https://deno.land/x/[email protected]/mod.ts";
import { I18n, I18nFlavor } from "../src/mod.ts";

interface SessionData {
apples: number;
}

type MyContext =
& Context
& I18nFlavor
& SessionFlavor<SessionData>;

const bot = new Bot<MyContext>(""); // <-- put your bot token here (https://t.me/BotFather)

bot.use(session({
initial: () => ({ apples: 0 }),
}));

const i18n = new I18n({
defaultLocale: "en",
useSession: true,
directory: "locales",
});

bot.use(i18n);

bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("greeting"));
});

bot.command(["en", "de", "ku", "ckb"], async (ctx) => {
const locale = ctx.msg.text.substring(1).split(" ")[0];
await ctx.i18n.setLocale(locale);
await ctx.reply(ctx.t("language-set"));
});

bot.command("add", async (ctx) => {
ctx.session.apples++;
await ctx.reply(ctx.t("cart", {
apples: ctx.session.apples,
}));
});

bot.command("cart", async (ctx) => {
await ctx.reply(ctx.t("cart", {
apples: ctx.session.apples,
}));
});

bot.command("checkout", async (ctx) => {
ctx.session.apples = 0;
await ctx.reply(ctx.t("checkout"));
});

bot.start();
Loading

0 comments on commit 632615a

Please sign in to comment.