feat: setup localisation with lingui

This commit is contained in:
Henry
2025-06-23 23:43:16 +01:00
parent 014fdbb7d8
commit f105e951e6
23 changed files with 2970 additions and 308 deletions

3
.gitignore vendored
View File

@@ -48,4 +48,5 @@ dist/
docker-compose.override.yml
# runtime env
__ENV.js
__ENV.js
i18n.cache

13
apps/web/i18n.json Normal file
View File

@@ -0,0 +1,13 @@
{
"version": 0,
"locale": {
"source": "en",
"targets": ["fr"]
},
"buckets": {
"po": {
"include": ["src/locales/[locale]/messages.po"]
}
},
"$schema": "https://lingo.dev/schema/i18n.json"
}

91
apps/web/i18n.lock Normal file
View File

@@ -0,0 +1,91 @@
version: 1
checksums:
8033ed03a24d7c4898c90a5365297c20:
"%231%20Hacker%20News/singular": de271b412c6c022d5c427d29fc70e0ba
1%20user/singular: 3b547431ab12f0fba84307e6a81109d8
A%20powerful%2C%20flexible%20kanban%20app%20that%20helps%20you%20organise%20work%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20track%20progress%2C%20and%20deliver%20results%E2%80%94all%20in%20one%20place./singular: 31f455ed399f410c37aae3f948cc750c
Activity%20logs/singular: 8b1f0bb96a905646ecfad1cfdfa42168
Admin%20roles/singular: 32a5d78073b9bb9a246773afba8831df
All%20seats%20are%20free%20during%20the%20beta%20until%20Sept%201st!/singular: 015cec3899cf99e37c3cf231d432e31d
Board%20visibility/singular: b4205f3058297833a626156057c24b26
Collaborate%20seamlessly%20with%20your%20team./singular: c5f10e431aaf8b51519bc009a4a4080c
Coming%20soon/singular: ee2b0671e00972773210c5be5a9ccb89
Comments/singular: 502237cd1044491c48494aa60967a985
Complete%20control%20and%20ownership%3A/singular: 0d8b682ba873272217425ccfc96aa9cd
Connect%20your%20favorite%20tools%20to%20streamline%20your%20workflow./singular: 033c5dcdb059ccb634aef7fe63f2f45d
Control%20who%20can%20view%20and%20edit%20your%20boards./singular: 2a7e0bec29bac26280de707e2fe8bce5
Custom%20domain/singular: b09e7a9c187b7163b4a6cfc78042fe42
Discuss%20and%20collaborate%20on%20cards./singular: f2e87816709f602130831ead50bba457
Do%20you%20offer%20a%20free%20plan%3F/singular: 3ef16b0994f0d9ae17067782ca9bed1b
Docs/singular: 55fea190a0c0fb32acd3dc986cd3cc91
Everything%20in%20the%20free%20plan%2C%20plus%3A/singular: 62b44c4973b92b806c69a4b15e0256dc
Everything%20you%20need%2C%20free%20forever.%20Unlimited%20boards%2C%20unlimited%20lists%2C%20unlimited%20cards.%20Upgrade%20any%20time./singular: fa21632ab1468edf10acda2fe7b71323
FAQs/singular: dc36d7992372ccd419b39ef51cf5b16c
Features/singular: 341ff316a339b106a178f0b8d362951b
Find%20answers%20to%20common%20questions%20about%20the%20project.%20Can't%20find%20what%20you're%20looking%20for%3F%20Feel%20free%20to%20%3C0%3Econtact%20us%3C%2F0%3E./singular: 4d99230dad703bf2d71ba670c2f79d3d
For%20long-term%20sustainability%2C%20we%20recognise%20all%20good%20open%20source%20projects%20need%20a%20source%20of%20revenue.%20Ours%20comes%20from%20the%20paid%20cloud%20offering%20for%20workspaces%20with%20multiple%20users%20(free%20during%20the%20beta)%20and%20for%20custom%20workspace%20slugs.%20There's%20no%20obligation%20to%20use%20it%2C%20and%20you%20can%20self-host%20the%20software%20on%20your%20own%20infrastructure%20free%20of%20charge./singular: 4eedacd4311ff69bf0fd87083c90a268
Free/singular: 0326365539c004f6088656f692602078
Free%2C%20forever/singular: ae4f2f81e88a50b5f250ef8e8e77e74b
Get%20started/singular: 5c783951b0100a168bdd2161ff294833
Get%20Started/singular: 1d5f030c4ec9c869e647ae060518b948
Get%20started%20for%20free%20today/singular: 41e129eba0f6411337b54a7a08ea1709
Get%20started%20for%20free%2C%20with%20no%20usage%20limits.%20For%20collaboration%2C%20upgrade%20to%20a%20plan%20that%20fits%20the%20size%20of%20your%20team./singular: ddea69fa5d7b4023724296e1287872b6
Get%20started%20on%20Cloud/singular: ed926f526266ad2063283c58e6f4284a
Go%20to%20app/singular: 896d0441384dcd2bfb3b23d61ff1944d
Host%20Kan%20on%20your%20own%20infrastructure.%20Ideal%20for%20organisations%20that%20need%20complete%20control%20over%20their%20data./singular: 8e7ae0783d60ef4624d3caf9bfc3747f
How%20do%20I%20get%20a%20custom%20URL%3F/singular: 5b28fb95969c0dd19e1b9c9ab8a5fb29
How%20do%20I%20import%20my%20Trello%20boards%3F/singular: 44b30a727150cb93364af0a10346012a
How%20do%20I%20invite%20team%20members%3F/singular: e620622060a06288e86ccda35395db87
How%20do%20I%20self-host%3F/singular: ec0b6afc8ad2f581b512c0fd82926b75
How%20is%20the%20project%20funded%3F/singular: ba7e936f7b1b5faa47df59a0ef990092
Import%20your%20Trello%20boards%20and%20hit%20the%20ground%20running./singular: d66d13649f81342f8b3a4f3b54370c20
Importing%20your%20Trello%20boards%20into%20Kan%20is%20easy.%20You%20can%20follow%20our%20step-by-step%20guide%20%3C0%3Ehere%3C%2F0%3E./singular: ca88dc22801fef08fee1ecfb1bf6914e
Individuals/singular: 83bfc81f20e60556c44ec80c7d0603ec
Integrations/singular: 0ccce343287704cd90150c32e2fcad36
Kanban%20is%20better%20with%20a%20team.%20Perfect%20for%20small%20and%20growing%20teams%20looking%20to%20collaborate./singular: a77bee43046b260797c8936ad23e9223
Kanban%20reimagined/singular: 613ccfdd9f54c66cbf68cfa313498766
Labels%20%26%20Filters/singular: 8f0bdd6084516f8241cb613178114390
Monthly/singular: 818f1192e32bb855597f930d3e78806e
No%20credit%20card%20required/singular: 2090aa4171dc0b60735069f89b592883
Organize%20and%20find%20cards%20quickly%20with%20powerful%20filtering%20tools./singular: 1b9898c4b21e9dff413b4f76dc59db56
Own%20your%20data/singular: cc2178dac4bdf6b07f030cfc2a7510e6
per%20user%2Fmonth/singular: 72af182c1ba6df6732640f4d8a78d360
Pricing/singular: ce27f1aeacccc542a174c4b2bce022b0
Priority%20email%20support/singular: 678538c912a770b1e1416ecdb8e299b1
Questions%3F/singular: c7c3a47f8b230ce7a43f3c090f21d683
Roadmap/singular: c60f4a1acf30e566861bf130f13b9ae7
Run%20on%20your%20own%20infrastructure/singular: eba804911562b8dbf9d69c3e27f1d708
Save%20time%20with%20reusable%20board%20templates./singular: d0f2d7d0fd682ceaf4ca12c6353fd75a
Self%20Host/singular: 43fbce2027548b712002e489a20a621a
Self%20host%20with%20Github/singular: 972155419bcc9f8f9bad9f5ad3538774
Sign%20in/singular: cb8757c7450e17de1e226e82fb0fa4a2
Simple%20pricing/singular: 5aa2bece93a71947b268498a58062937
Simple%2C%20visual%20task%20management%20that%20just%20works.%20Drag%20and%20drop%20cards%2C%20collaborate%20with%20your%20team%2C%20and%20get%20more%20done./singular: f4f138f83017d43dab2882cc08e07bdb
Star%20on%20Github/singular: e5cb0428f1ac6485688f120d78742875
Support%20the%20development%20of%20the%20project/singular: c63bab228ab2b1be4370c668a99cd278
Teams/singular: b63448c05270497973ac4407047dae02
Templates/singular: 8ed62f56c81fa96c0f3182acb331bf63
The%20main%20difference%20between%20Kan%20and%20Trello%20is%20that%20Kan%20is%20open%20source%2C%20allowing%20anyone%20to%20view%2C%20modify%2C%20and%20contribute%20to%20our%20code.%20Our%20cloud%20offering%20also%20offers%20no%20restrictions%20on%20features%20for%20individual%20use%2C%20whereas%20Trello%20locks%20basic%20features%20such%20as%20the%20number%20of%20boards%20you%20can%20create%20behind%20a%20paywall./singular: db6e22cc955c5fbe547feedeb48f8719
The%20open%20source%20%3C0%2F%3E%20alternative%20to%20Trello/singular: 692cb2e8a8e610953c996826beed45a2
Track%20all%20card%20changes%20with%20detailed%20activity%20history./singular: 0d3bac559c71ec4b8734f9f212320de5
Trello%20imports/singular: 6827eca403faa8f89891d17827e72af9
Unlimited%20activity%20log/singular: 8c993de94cda0deac19ba14ecafce6a5
Unlimited%20boards/singular: cb4fd858137ce825c2f1904d142d8042
Unlimited%20boards%2C%20unlimited%20lists%2C%20unlimited%20cards.%20No%20credit%20card%20required./singular: 8d9733137deb26664d76b55ad561c42c
Unlimited%20cards/singular: f44c1050c4d6aa39c8cdf5f4a7d12577
Unlimited%20comments/singular: 31dbcf487c49a9997142e96bb3ab0040
Unlimited%20lists/singular: 5c418701b27b9acbc5dd199719007362
View%20docs/singular: 43ce54f27bb1e3f1880b56e03ab38871
View%20our%20roadmap./singular: 1dd7ec80e1635951b1c90d592d1d07dc
We%20are%20using%20the%20%3C0%3EAGPL-3.0%20license%3C%2F0%3E./singular: 08c5ddd938a2a70f61d684e41e18697a
We're%20just%20getting%20started.%20/singular: 2dfa121e0ff1914e08068308a81973c0
What%20license%20are%20you%20using%3F/singular: 59d00e1bf28edc21b77fec94875f57ca
What's%20the%20difference%20between%20Kan%20and%20Trello%3F/singular: 7a02f507dd6abbfab1fdae0b172d31b7
When%20Trello%20launched%20in%202011%2C%20it%20blew%20everyone%20away%20with%20its%20carefully%20designed%20simplicity%2C%20but%20over%20time%20(and%20atlassification)%20it%20lost%20its%20magic%20and%20grew%20into%20something%20closer%20to%20%22Jira%20Lite%22.%20This%20project%20is%20our%20attempt%20to%20recapture%20the%20original%20magic%20of%20Trello%E2%80%99s%20simplicity%2C%20in%20open%20source./singular: a09fb6c21ae2d7ba45f3c6f3983cbab6
Why%20make%20an%20open%20source%20Trello%3F/singular: 090833338ba8c64ef7a75e0f2615b34b
Workspace%20members/singular: 1857292f9567c556c781a23bd7e10544
Yearly/singular: 87f43e016c19cb25860f456549a2f431
Yes%2C%20we%20offer%20an%20forever%20free%20plan%20for%20individual%20use.%20No%20restrictions%2C%20no%20paywalls%2C%20no%20limits./singular: 963cee303d0ff13c1719f4575e774fe3
You%20can%20get%20a%20custom%20workspace%20URL%2C%20like%20%3C0%3Ekan.bn%2Fkan%3C%2F0%3E%2C%20by%20going%20into%20your%20%3C1%3Eworkspace%20settings%3C%2F1%3E%20and%20purchasing%20a%20pro%20workspace%20subscription.%20All%20subscriptions%20help%20fund%20the%20development%20of%20the%20project!/singular: 41dd145ef56f539e12dc064a9807c660
You%20can%20invite%20team%20members%20by%20clicking%20the%20%22Invite%22%20button%20in%20the%20top%20right%20corner%20of%20the%20%3C0%3Emembers%20page%3C%2F0%3E%20and%20entering%20their%20email%20address.%20They%20will%20receive%20an%20email%20with%20a%20link%20to%20join%20the%20workspace./singular: 47e125eb9b4c11cab5a2f4b3ab08e883
You%20can%20self-host%20by%20following%20the%20instructions%20in%20our%20%3C0%3Erepo%3C%2F0%3E./singular: a6152a41b2d8f64d5a657e5b8bc808a9

15
apps/web/lingui.config.ts Normal file
View File

@@ -0,0 +1,15 @@
import type { LinguiConfig } from "@lingui/conf";
const config: LinguiConfig = {
locales: ["en", "fr"],
sourceLocale: "en",
catalogs: [
{
path: "src/locales/{locale}/messages",
include: ["src"],
exclude: ["**/node_modules/**"],
},
],
};
export default config;

View File

@@ -46,7 +46,8 @@ const config = {
],
},
experimental: {
instrumentationHook: true,
// instrumentationHook: true,
swcPlugins: [["@lingui/swc-plugin", {}]],
},
};

View File

@@ -11,7 +11,10 @@
"lint": "eslint",
"start": "pnpm with-env next start",
"typecheck": "tsc --noEmit",
"with-env": "dotenv -e ../../.env --"
"with-env": "dotenv -e ../../.env --",
"lingui:extract": "lingui extract",
"lingui:compile": "lingui compile --typescript",
"lingui:extract:watch": "lingui extract --watch"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.802.0",
@@ -22,6 +25,10 @@
"@kan/auth": "workspace:*",
"@kan/db": "workspace:^",
"@kan/shared": "workspace:^",
"@lingui/babel-preset-react": "^2.9.2",
"@lingui/conf": "^5.3.2",
"@lingui/macro": "^5.3.2",
"@lingui/react": "^5.3.2",
"@t3-oss/env-nextjs": "^0.11.1",
"@tailwindcss/typography": "^0.5.16",
"@tanstack/react-query": "catalog:",
@@ -38,7 +45,7 @@
"aws-sdk": "^2.1692.0",
"date-fns": "^4.1.0",
"geist": "^1.3.1",
"next": "^14.2.15",
"next": "^15.3.4",
"next-logger": "^5.0.1",
"next-runtime-env": "^1.7.2",
"nextjs-cors": "^2.2.0",
@@ -50,6 +57,7 @@
"react-dom": "catalog:react18",
"react-hook-form": "^7.51.1",
"react-icons": "^5.5.0",
"react-intl": "^6.8.9",
"react-lottie-player": "^1.5.5",
"react-markdown": "^10.1.0",
"superjson": "2.2.1",
@@ -63,6 +71,9 @@
"@kan/stripe": "workspace:*",
"@kan/tailwind-config": "workspace:*",
"@kan/tsconfig": "workspace:*",
"@lingui/cli": "^5.3.2",
"@lingui/loader": "^5.3.2",
"@lingui/swc-plugin": "^5.5.2",
"@types/node": "^20.17.7",
"@types/react": "catalog:react18",
"@types/react-beautiful-dnd": "^13.1.7",

View File

@@ -0,0 +1,25 @@
import { useLocalisation } from "~/hooks/useLocalisation";
import { localeNames } from "~/locales";
export function LanguageSelector() {
const { locale, setLocale, availableLocales } = useLocalisation();
console.log(locale, availableLocales);
return (
<div className="flex items-center space-x-2">
<select
id="language-select"
value={locale}
onChange={(e) => setLocale(e.target.value as any)}
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
>
{availableLocales.map((loc) => (
<option key={loc} value={loc}>
{localeNames[loc]}
</option>
))}
</select>
</div>
);
}

View File

@@ -0,0 +1,16 @@
import { useLingui } from "@lingui/react";
import { useLinguiContext } from "~/providers/lingui";
export function useLocalisation() {
const { i18n } = useLingui();
const { locale, setLocale, availableLocales } = useLinguiContext();
return {
locale,
setLocale,
availableLocales,
formatDate: i18n.date,
formatNumber: i18n.number,
};
}

View File

@@ -0,0 +1,380 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-06-23 23:21+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:33
msgid "1 user"
msgstr "1 user"
#: src/views/home/index.tsx:71
msgid ""
"A powerful, flexible kanban app that helps you organise work,\n"
" track progress, and deliver results—all in one place."
msgstr ""
"A powerful, flexible kanban app that helps you organise work,\n"
" track progress, and deliver results—all in one place."
#: src/views/home/components/Features.tsx:102
msgid "Activity logs"
msgstr "Activity logs"
#: src/views/home/components/Pricing.tsx:52
msgid "Admin roles"
msgstr "Admin roles"
#: src/views/home/components/Pricing.tsx:98
msgid "All seats are free during the beta until Sept 1st!"
msgstr "All seats are free during the beta until Sept 1st!"
#: src/views/home/components/Features.tsx:77
msgid "Board visibility"
msgstr "Board visibility"
#: src/views/home/components/Features.tsx:83
msgid "Collaborate seamlessly with your team."
msgstr "Collaborate seamlessly with your team."
#: src/views/home/components/Features.tsx:66
msgid "Coming soon"
msgstr "Coming soon"
#: src/views/home/components/Features.tsx:97
msgid "Comments"
msgstr "Comments"
#: src/views/home/components/Pricing.tsx:67
msgid "Complete control and ownership:"
msgstr "Complete control and ownership:"
#: src/views/home/components/Features.tsx:114
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connect your favorite tools to streamline your workflow."
#: src/views/home/components/Features.tsx:78
msgid "Control who can view and edit your boards."
msgstr "Control who can view and edit your boards."
#: src/views/home/components/Pricing.tsx:71
msgid "Custom domain"
msgstr "Custom domain"
#: src/views/home/components/Features.tsx:98
msgid "Discuss and collaborate on cards."
msgstr "Discuss and collaborate on cards."
#: src/views/home/components/Faqs.tsx:79
msgid "Do you offer a free plan?"
msgstr "Do you offer a free plan?"
#: src/views/home/components/Header.tsx:16
msgid "Docs"
msgstr "Docs"
#: src/views/home/components/Pricing.tsx:49
msgid "Everything in the free plan, plus:"
msgstr "Everything in the free plan, plus:"
#: src/views/home/components/Pricing.tsx:30
msgid "Everything you need, free forever. Unlimited boards, unlimited lists, unlimited cards. Upgrade any time."
msgstr "Everything you need, free forever. Unlimited boards, unlimited lists, unlimited cards. Upgrade any time."
#: src/views/home/components/Faqs.tsx:140
msgid "FAQs"
msgstr "FAQs"
#: src/views/home/components/Header.tsx:14
#: src/views/home/components/Features.tsx:124
msgid "Features"
msgstr "Features"
#: src/views/home/components/Faqs.tsx:147
msgid "Find answers to common questions about the project. Can't find what you're looking for? Feel free to <0>contact us</0>."
msgstr "Find answers to common questions about the project. Can't find what you're looking for? Feel free to <0>contact us</0>."
#: src/views/home/components/Faqs.tsx:40
msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge."
msgstr "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge."
#: src/views/home/components/Pricing.tsx:29
#: src/views/home/components/Pricing.tsx:29
msgid "Free"
msgstr "Free"
#: src/views/home/components/Pricing.tsx:31
msgid "Free, forever"
msgstr "Free, forever"
#: src/views/home/components/Header.tsx:102
#: src/views/home/components/Header.tsx:141
#: src/views/home/components/Cta.tsx:61
msgid "Get started"
msgstr "Get started"
#: src/views/home/components/Pricing.tsx:28
#: src/views/home/components/Pricing.tsx:46
msgid "Get Started"
msgstr "Get Started"
#: src/views/home/components/Cta.tsx:54
msgid "Get started for free today"
msgstr "Get started for free today"
#: src/views/home/components/Pricing.tsx:93
msgid "Get started for free, with no usage limits. For collaboration, upgrade to a plan that fits the size of your team."
msgstr "Get started for free, with no usage limits. For collaboration, upgrade to a plan that fits the size of your team."
#: src/views/home/index.tsx:76
msgid "Get started on Cloud"
msgstr "Get started on Cloud"
#: src/views/home/components/Header.tsx:96
#: src/views/home/components/Header.tsx:133
msgid "Go to app"
msgstr "Go to app"
#: src/views/home/components/Pricing.tsx:66
msgid "Host Kan on your own infrastructure. Ideal for organisations that need complete control over their data."
msgstr "Host Kan on your own infrastructure. Ideal for organisations that need complete control over their data."
#: src/views/home/components/Faqs.tsx:60
msgid "How do I get a custom URL?"
msgstr "How do I get a custom URL?"
#: src/views/home/components/Faqs.tsx:45
msgid "How do I import my Trello boards?"
msgstr "How do I import my Trello boards?"
#: src/views/home/components/Faqs.tsx:104
msgid "How do I invite team members?"
msgstr "How do I invite team members?"
#: src/views/home/components/Faqs.tsx:120
msgid "How do I self-host?"
msgstr "How do I self-host?"
#: src/views/home/components/Faqs.tsx:37
msgid "How is the project funded?"
msgstr "How is the project funded?"
#: src/views/home/components/Features.tsx:88
msgid "Import your Trello boards and hit the ground running."
msgstr "Import your Trello boards and hit the ground running."
#: src/views/home/components/Faqs.tsx:48
msgid "Importing your Trello boards into Kan is easy. You can follow our step-by-step guide <0>here</0>."
msgstr "Importing your Trello boards into Kan is easy. You can follow our step-by-step guide <0>here</0>."
#: src/views/home/components/Pricing.tsx:25
msgid "Individuals"
msgstr "Individuals"
#: src/views/home/components/Features.tsx:113
msgid "Integrations"
msgstr "Integrations"
#: src/views/home/components/Pricing.tsx:48
msgid "Kanban is better with a team. Perfect for small and growing teams looking to collaborate."
msgstr "Kanban is better with a team. Perfect for small and growing teams looking to collaborate."
#: src/views/home/components/Features.tsx:128
msgid "Kanban reimagined"
msgstr "Kanban reimagined"
#: src/views/home/components/Features.tsx:92
msgid "Labels & Filters"
msgstr "Labels & Filters"
#: src/views/home/components/Pricing.tsx:13
msgid "Monthly"
msgstr "Monthly"
#: src/views/home/index.tsx:86
msgid "No credit card required"
msgstr "No credit card required"
#: src/views/home/components/Features.tsx:93
msgid "Organize and find cards quickly with powerful filtering tools."
msgstr "Organize and find cards quickly with powerful filtering tools."
#: src/views/home/components/Pricing.tsx:70
msgid "Own your data"
msgstr "Own your data"
#: src/views/home/components/Pricing.tsx:14
#: src/views/home/components/Pricing.tsx:19
msgid "per user/month"
msgstr "per user/month"
#: src/views/home/components/Pricing.tsx:86
#: src/views/home/components/Header.tsx:15
msgid "Pricing"
msgstr "Pricing"
#: src/views/home/components/Pricing.tsx:53
msgid "Priority email support"
msgstr "Priority email support"
#: src/views/home/components/Faqs.tsx:144
msgid "Questions?"
msgstr "Questions?"
#: src/views/home/components/Header.tsx:13
msgid "Roadmap"
msgstr "Roadmap"
#: src/views/home/components/Pricing.tsx:69
msgid "Run on your own infrastructure"
msgstr "Run on your own infrastructure"
#: src/views/home/components/Features.tsx:108
msgid "Save time with reusable board templates."
msgstr "Save time with reusable board templates."
#: src/views/home/components/Pricing.tsx:61
msgid "Self Host"
msgstr "Self Host"
#: src/views/home/index.tsx:82
msgid "Self host with Github"
msgstr "Self host with Github"
#: src/views/home/components/Header.tsx:100
#: src/views/home/components/Header.tsx:138
msgid "Sign in"
msgstr "Sign in"
#: src/views/home/components/Pricing.tsx:90
msgid "Simple pricing"
msgstr "Simple pricing"
#: src/views/home/components/Features.tsx:131
msgid "Simple, visual task management that just works. Drag and drop cards, collaborate with your team, and get more done."
msgstr "Simple, visual task management that just works. Drag and drop cards, collaborate with your team, and get more done."
#: src/views/home/index.tsx:37
msgid "Star on Github"
msgstr "Star on Github"
#: src/views/home/components/Pricing.tsx:54
msgid "Support the development of the project"
msgstr "Support the development of the project"
#: src/views/home/components/Pricing.tsx:43
msgid "Teams"
msgstr "Teams"
#: src/views/home/components/Features.tsx:107
msgid "Templates"
msgstr "Templates"
#: src/views/home/components/Faqs.tsx:32
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
#: src/views/home/index.tsx:65
msgid "The open source <0/> alternative to Trello"
msgstr "The open source <0/> alternative to Trello"
#: src/views/home/components/Features.tsx:103
msgid "Track all card changes with detailed activity history."
msgstr "Track all card changes with detailed activity history."
#: src/views/home/components/Features.tsx:87
msgid "Trello imports"
msgstr "Trello imports"
#: src/views/home/components/Pricing.tsx:38
msgid "Unlimited activity log"
msgstr "Unlimited activity log"
#: src/views/home/components/Pricing.tsx:34
msgid "Unlimited boards"
msgstr "Unlimited boards"
#: src/views/home/components/Cta.tsx:57
msgid "Unlimited boards, unlimited lists, unlimited cards. No credit card required."
msgstr "Unlimited boards, unlimited lists, unlimited cards. No credit card required."
#: src/views/home/components/Pricing.tsx:36
msgid "Unlimited cards"
msgstr "Unlimited cards"
#: src/views/home/components/Pricing.tsx:37
msgid "Unlimited comments"
msgstr "Unlimited comments"
#: src/views/home/components/Pricing.tsx:35
msgid "Unlimited lists"
msgstr "Unlimited lists"
#: src/views/home/components/Pricing.tsx:64
msgid "View docs"
msgstr "View docs"
#: src/views/home/components/Features.tsx:146
msgid "View our roadmap."
msgstr "View our roadmap."
#: src/views/home/components/Faqs.tsx:90
msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "We are using the <0>AGPL-3.0 license</0>."
#: src/views/home/components/Features.tsx:144
msgid "We're just getting started. "
msgstr "We're just getting started. "
#: src/views/home/components/Faqs.tsx:87
msgid "What license are you using?"
msgstr "What license are you using?"
#: src/views/home/components/Faqs.tsx:29
msgid "What's the difference between Kan and Trello?"
msgstr "What's the difference between Kan and Trello?"
#: src/views/home/components/Faqs.tsx:24
msgid "When Trello launched in 2011, it blew everyone away with its carefully designed simplicity, but over time (and atlassification) it lost its magic and grew into something closer to \"Jira Lite\". This project is our attempt to recapture the original magic of Trellos simplicity, in open source."
msgstr "When Trello launched in 2011, it blew everyone away with its carefully designed simplicity, but over time (and atlassification) it lost its magic and grew into something closer to \"Jira Lite\". This project is our attempt to recapture the original magic of Trellos simplicity, in open source."
#: src/views/home/components/Faqs.tsx:21
msgid "Why make an open source Trello?"
msgstr "Why make an open source Trello?"
#: src/views/home/components/Pricing.tsx:51
#: src/views/home/components/Features.tsx:82
msgid "Workspace members"
msgstr "Workspace members"
#: src/views/home/components/Pricing.tsx:18
msgid "Yearly"
msgstr "Yearly"
#: src/views/home/components/Faqs.tsx:82
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
#: src/views/home/components/Faqs.tsx:63
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
#: src/views/home/components/Faqs.tsx:107
msgid "You can invite team members by clicking the \"Invite\" button in the top right corner of the <0>members page</0> and entering their email address. They will receive an email with a link to join the workspace."
msgstr "You can invite team members by clicking the \"Invite\" button in the top right corner of the <0>members page</0> and entering their email address. They will receive an email with a link to join the workspace."
#: src/views/home/components/Faqs.tsx:123
msgid "You can self-host by following the instructions in our <0>repo</0>."
msgstr "You can self-host by following the instructions in our <0>repo</0>."

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,379 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-06-23 23:21+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fr\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:33
msgid "1 user"
msgstr "1 utilisateur"
#: src/views/home/index.tsx:71
msgid ""
"A powerful, flexible kanban app that helps you organise work,\n"
" track progress, and deliver results—all in one place."
msgstr ""
"Une application kanban puissante et flexible qui vous aide à organiser votre travail,\n"
" suivre la progression et livrer des résultats — le tout en un seul endroit."
#: src/views/home/components/Features.tsx:102
msgid "Activity logs"
msgstr "Journaux d'activité"
#: src/views/home/components/Pricing.tsx:52
msgid "Admin roles"
msgstr "Rôles d'administrateur"
#: src/views/home/components/Pricing.tsx:98
msgid "All seats are free during the beta until Sept 1st!"
msgstr "Tous les sièges sont gratuits pendant la bêta jusqu'au 1er sept. !"
#: src/views/home/components/Features.tsx:77
msgid "Board visibility"
msgstr "Visibilité du tableau"
#: src/views/home/components/Features.tsx:83
msgid "Collaborate seamlessly with your team."
msgstr "Collaborez en toute fluidité avec votre équipe."
#: src/views/home/components/Features.tsx:66
msgid "Coming soon"
msgstr "Bientôt disponible"
#: src/views/home/components/Features.tsx:97
msgid "Comments"
msgstr "Commentaires"
#: src/views/home/components/Pricing.tsx:67
msgid "Complete control and ownership:"
msgstr "Contrôle et propriété complets :"
#: src/views/home/components/Features.tsx:114
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connectez vos outils favoris pour simplifier votre flux de travail."
#: src/views/home/components/Features.tsx:78
msgid "Control who can view and edit your boards."
msgstr "Contrôlez qui peut voir et modifier vos tableaux."
#: src/views/home/components/Pricing.tsx:71
msgid "Custom domain"
msgstr "Domaine personnalisé"
#: src/views/home/components/Features.tsx:98
msgid "Discuss and collaborate on cards."
msgstr "Discutez et collaborez sur les cartes."
#: src/views/home/components/Faqs.tsx:79
msgid "Do you offer a free plan?"
msgstr "Proposez-vous un plan gratuit ?"
#: src/views/home/components/Header.tsx:16
msgid "Docs"
msgstr "Documentation"
#: src/views/home/components/Pricing.tsx:49
msgid "Everything in the free plan, plus:"
msgstr "Tout ce qui est inclus dans le plan gratuit, plus :"
#: src/views/home/components/Pricing.tsx:30
msgid "Everything you need, free forever. Unlimited boards, unlimited lists, unlimited cards. Upgrade any time."
msgstr "Tout ce dont vous avez besoin, gratuit pour toujours. Tableaux illimités, listes illimitées, cartes illimitées. Possibilité de mise à niveau à tout moment."
#: src/views/home/components/Faqs.tsx:140
msgid "FAQs"
msgstr "FAQ"
#: src/views/home/components/Header.tsx:14
#: src/views/home/components/Features.tsx:124
msgid "Features"
msgstr "Fonctionnalités"
#: src/views/home/components/Faqs.tsx:147
msgid "Find answers to common questions about the project. Can't find what you're looking for? Feel free to <0>contact us</0>."
msgstr "Trouvez des réponses aux questions fréquentes sur le projet. Vous ne trouvez pas ce que vous cherchez ? N'hésitez pas à <0>nous contacter</0>."
#: src/views/home/components/Faqs.tsx:40
msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge."
msgstr "Pour une durabilité à long terme, nous reconnaissons que tous les bons projets open source ont besoin d'une source de revenus. La nôtre provient de l'offre cloud payante pour les espaces de travail avec plusieurs utilisateurs (gratuite pendant la bêta) et pour les slugs d'espace de travail personnalisés. Il n'y a aucune obligation de l'utiliser, et vous pouvez auto-héberger le logiciel sur votre propre infrastructure gratuitement."
#: src/views/home/components/Pricing.tsx:29
msgid "Free"
msgstr "Gratuit"
#: src/views/home/components/Pricing.tsx:31
msgid "Free, forever"
msgstr "Gratuit, pour toujours"
#: src/views/home/components/Header.tsx:102
#: src/views/home/components/Header.tsx:141
#: src/views/home/components/Cta.tsx:61
msgid "Get started"
msgstr "Commencer"
#: src/views/home/components/Pricing.tsx:28
#: src/views/home/components/Pricing.tsx:46
msgid "Get Started"
msgstr "Commencer"
#: src/views/home/components/Cta.tsx:54
msgid "Get started for free today"
msgstr "Commencez gratuitement aujourd'hui"
#: src/views/home/components/Pricing.tsx:93
msgid "Get started for free, with no usage limits. For collaboration, upgrade to a plan that fits the size of your team."
msgstr "Commencez gratuitement, sans limites d'utilisation. Pour la collaboration, passez à un forfait adapté à la taille de votre équipe."
#: src/views/home/index.tsx:76
msgid "Get started on Cloud"
msgstr "Commencer sur le Cloud"
#: src/views/home/components/Header.tsx:96
#: src/views/home/components/Header.tsx:133
msgid "Go to app"
msgstr "Accéder à l'application"
#: src/views/home/components/Pricing.tsx:66
msgid "Host Kan on your own infrastructure. Ideal for organisations that need complete control over their data."
msgstr "Hébergez Kan sur votre propre infrastructure. Idéal pour les organisations qui ont besoin d'un contrôle total sur leurs données."
#: src/views/home/components/Faqs.tsx:60
msgid "How do I get a custom URL?"
msgstr "Comment obtenir une URL personnalisée ?"
#: src/views/home/components/Faqs.tsx:45
msgid "How do I import my Trello boards?"
msgstr "Comment importer mes tableaux Trello ?"
#: src/views/home/components/Faqs.tsx:104
msgid "How do I invite team members?"
msgstr "Comment inviter des membres de l'équipe ?"
#: src/views/home/components/Faqs.tsx:120
msgid "How do I self-host?"
msgstr "Comment faire pour auto-héberger ?"
#: src/views/home/components/Faqs.tsx:37
msgid "How is the project funded?"
msgstr "Comment le projet est-il financé ?"
#: src/views/home/components/Features.tsx:88
msgid "Import your Trello boards and hit the ground running."
msgstr "Importez vos tableaux Trello et commencez immédiatement."
#: src/views/home/components/Faqs.tsx:48
msgid "Importing your Trello boards into Kan is easy. You can follow our step-by-step guide <0>here</0>."
msgstr "L'importation de vos tableaux Trello dans Kan est simple. Vous pouvez suivre notre guide étape par étape <0>ici</0>."
#: src/views/home/components/Pricing.tsx:25
msgid "Individuals"
msgstr "Particuliers"
#: src/views/home/components/Features.tsx:113
msgid "Integrations"
msgstr "Intégrations"
#: src/views/home/components/Pricing.tsx:48
msgid "Kanban is better with a team. Perfect for small and growing teams looking to collaborate."
msgstr "Kanban est meilleur en équipe. Parfait pour les petites équipes et celles en croissance qui cherchent à collaborer."
#: src/views/home/components/Features.tsx:128
msgid "Kanban reimagined"
msgstr "Kanban réinventé"
#: src/views/home/components/Features.tsx:92
msgid "Labels & Filters"
msgstr "Étiquettes & filtres"
#: src/views/home/components/Pricing.tsx:13
msgid "Monthly"
msgstr "Mensuel"
#: src/views/home/index.tsx:86
msgid "No credit card required"
msgstr "Aucune carte de crédit requise"
#: src/views/home/components/Features.tsx:93
msgid "Organize and find cards quickly with powerful filtering tools."
msgstr "Organisez et trouvez rapidement des cartes avec des outils de filtrage puissants."
#: src/views/home/components/Pricing.tsx:70
msgid "Own your data"
msgstr "Maîtrisez vos données"
#: src/views/home/components/Pricing.tsx:14
#: src/views/home/components/Pricing.tsx:19
msgid "per user/month"
msgstr "par utilisateur/mois"
#: src/views/home/components/Pricing.tsx:86
#: src/views/home/components/Header.tsx:15
msgid "Pricing"
msgstr "Tarifs"
#: src/views/home/components/Pricing.tsx:53
msgid "Priority email support"
msgstr "Support par e-mail prioritaire"
#: src/views/home/components/Faqs.tsx:144
msgid "Questions?"
msgstr "Des questions ?"
#: src/views/home/components/Header.tsx:13
msgid "Roadmap"
msgstr "Feuille de route"
#: src/views/home/components/Pricing.tsx:69
msgid "Run on your own infrastructure"
msgstr "Exécutez sur votre propre infrastructure"
#: src/views/home/components/Features.tsx:108
msgid "Save time with reusable board templates."
msgstr "Gagnez du temps avec des modèles de tableaux réutilisables."
#: src/views/home/components/Pricing.tsx:61
msgid "Self Host"
msgstr "Auto-hébergement"
#: src/views/home/index.tsx:82
msgid "Self host with Github"
msgstr "Auto-hébergement avec Github"
#: src/views/home/components/Header.tsx:100
#: src/views/home/components/Header.tsx:138
msgid "Sign in"
msgstr "Se connecter"
#: src/views/home/components/Pricing.tsx:90
msgid "Simple pricing"
msgstr "Tarification simple"
#: src/views/home/components/Features.tsx:131
msgid "Simple, visual task management that just works. Drag and drop cards, collaborate with your team, and get more done."
msgstr "Gestion de tâches visuelle et simple qui fonctionne parfaitement. Glissez-déposez des cartes, collaborez avec votre équipe et accomplissez davantage."
#: src/views/home/index.tsx:37
msgid "Star on Github"
msgstr "Étoile sur Github"
#: src/views/home/components/Pricing.tsx:54
msgid "Support the development of the project"
msgstr "Soutenir le développement du projet"
#: src/views/home/components/Pricing.tsx:43
msgid "Teams"
msgstr "Équipes"
#: src/views/home/components/Features.tsx:107
msgid "Templates"
msgstr "Modèles"
#: src/views/home/components/Faqs.tsx:32
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "La principale différence entre Kan et Trello est que Kan est open source, permettant à chacun de consulter, modifier et contribuer à notre code. Notre offre cloud ne comporte également aucune restriction sur les fonctionnalités pour un usage individuel, alors que Trello verrouille des fonctionnalités de base comme le nombre de tableaux que vous pouvez créer derrière un paywall."
#: src/views/home/index.tsx:65
msgid "The open source <0/> alternative to Trello"
msgstr "L'alternative open source <0/> à Trello"
#: src/views/home/components/Features.tsx:103
msgid "Track all card changes with detailed activity history."
msgstr "Suivez tous les changements de cartes avec un historique d'activité détaillé."
#: src/views/home/components/Features.tsx:87
msgid "Trello imports"
msgstr "Importations Trello"
#: src/views/home/components/Pricing.tsx:38
msgid "Unlimited activity log"
msgstr "Journal d'activité illimité"
#: src/views/home/components/Pricing.tsx:34
msgid "Unlimited boards"
msgstr "Tableaux illimités"
#: src/views/home/components/Cta.tsx:57
msgid "Unlimited boards, unlimited lists, unlimited cards. No credit card required."
msgstr "Tableaux illimités, listes illimitées, cartes illimitées. Aucune carte de crédit requise."
#: src/views/home/components/Pricing.tsx:36
msgid "Unlimited cards"
msgstr "Cartes illimitées"
#: src/views/home/components/Pricing.tsx:37
msgid "Unlimited comments"
msgstr "Commentaires illimités"
#: src/views/home/components/Pricing.tsx:35
msgid "Unlimited lists"
msgstr "Listes illimitées"
#: src/views/home/components/Pricing.tsx:64
msgid "View docs"
msgstr "Voir la documentation"
#: src/views/home/components/Features.tsx:146
msgid "View our roadmap."
msgstr "Consultez notre feuille de route."
#: src/views/home/components/Faqs.tsx:90
msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Nous utilisons la <0>licence AGPL-3.0</0>."
#: src/views/home/components/Features.tsx:144
msgid "We're just getting started. "
msgstr "Nous ne faisons que commencer. "
#: src/views/home/components/Faqs.tsx:87
msgid "What license are you using?"
msgstr "Quelle licence utilisez-vous ?"
#: src/views/home/components/Faqs.tsx:29
msgid "What's the difference between Kan and Trello?"
msgstr "Quelle est la différence entre Kan et Trello ?"
#: src/views/home/components/Faqs.tsx:24
msgid "When Trello launched in 2011, it blew everyone away with its carefully designed simplicity, but over time (and atlassification) it lost its magic and grew into something closer to \"Jira Lite\". This project is our attempt to recapture the original magic of Trellos simplicity, in open source."
msgstr "Quand Trello a été lancé en 2011, il a impressionné tout le monde par sa simplicité soigneusement conçue, mais au fil du temps (et de l'\"atlassification\"), il a perdu sa magie et s'est transformé en quelque chose de plus proche d'un \"Jira Lite\". Ce projet est notre tentative de retrouver la magie originelle de la simplicité de Trello, en open source."
#: src/views/home/components/Faqs.tsx:21
msgid "Why make an open source Trello?"
msgstr "Pourquoi créer un Trello open source ?"
#: src/views/home/components/Pricing.tsx:51
#: src/views/home/components/Features.tsx:82
msgid "Workspace members"
msgstr "Membres de l'espace de travail"
#: src/views/home/components/Pricing.tsx:18
msgid "Yearly"
msgstr "Annuel"
#: src/views/home/components/Faqs.tsx:82
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Oui, nous proposons un plan gratuit à vie pour un usage individuel. Aucune restriction, aucun paywall, aucune limite."
#: src/views/home/components/Faqs.tsx:63
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "Vous pouvez obtenir une URL d'espace de travail personnalisée, comme <0>kan.bn/kan</0>, en accédant à vos <1>paramètres d'espace de travail</1> et en souscrivant à un abonnement pro. Tous les abonnements contribuent à financer le développement du projet !"
#: src/views/home/components/Faqs.tsx:107
msgid "You can invite team members by clicking the \"Invite\" button in the top right corner of the <0>members page</0> and entering their email address. They will receive an email with a link to join the workspace."
msgstr "Vous pouvez inviter des membres de l'équipe en cliquant sur le bouton \"Inviter\" dans le coin supérieur droit de la <0>page des membres</0> et en saisissant leur adresse e-mail. Ils recevront un e-mail avec un lien pour rejoindre l'espace de travail."
#: src/views/home/components/Faqs.tsx:123
msgid "You can self-host by following the instructions in our <0>repo</0>."
msgstr "Vous pouvez auto-héberger en suivant les instructions dans notre <0>dépôt</0>."

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
export const locales = ["en", "fr"] as const;
export type Locale = (typeof locales)[number];
export const defaultLocale: Locale = "en";
export const localeNames: Record<Locale, string> = {
en: "English",
fr: "Français",
};

View File

@@ -8,6 +8,7 @@ import posthog from "posthog-js";
import { PostHogProvider } from "posthog-js/react";
import { useEffect } from "react";
import { LinguiProviderWrapper } from "~/providers/lingui";
import { ModalProvider } from "~/providers/modal";
import { PopupProvider } from "~/providers/popup";
import { ThemeProvider } from "~/providers/theme";
@@ -59,19 +60,21 @@ const MyApp: AppType = ({ Component, pageProps }) => {
)}
<script src="/__ENV.js" />
<main className="font-sans">
<ThemeProvider>
<ModalProvider>
<PopupProvider>
{posthogKey ? (
<PostHogProvider client={posthog}>
<LinguiProviderWrapper>
<ThemeProvider>
<ModalProvider>
<PopupProvider>
{posthogKey ? (
<PostHogProvider client={posthog}>
<Component {...pageProps} />
</PostHogProvider>
) : (
<Component {...pageProps} />
</PostHogProvider>
) : (
<Component {...pageProps} />
)}
</PopupProvider>
</ModalProvider>
</ThemeProvider>
)}
</PopupProvider>
</ModalProvider>
</ThemeProvider>
</LinguiProviderWrapper>
</main>
</>
);

View File

@@ -0,0 +1,75 @@
import type { ReactNode } from "react";
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import { createContext, useContext, useEffect, useState } from "react";
import type { Locale } from "~/locales";
import { defaultLocale, locales } from "~/locales";
// Import compiled messages
import { messages as enMessages } from "~/locales/en/messages";
import { messages as frMessages } from "~/locales/fr/messages";
const messages = {
en: enMessages,
fr: frMessages,
};
interface LinguiContextType {
locale: Locale;
setLocale: (locale: Locale) => void;
availableLocales: Locale[];
}
const LinguiContext = createContext<LinguiContextType | undefined>(undefined);
export function useLinguiContext() {
const context = useContext(LinguiContext);
if (!context) {
throw new Error("useLinguiContext must be used within a LinguiProvider");
}
return context;
}
interface LinguiProviderProps {
children: ReactNode;
initialLocale?: Locale;
}
export function LinguiProviderWrapper({
children,
initialLocale = defaultLocale,
}: LinguiProviderProps) {
const getInitialLocale = (): Locale => {
if (typeof window !== "undefined") {
const savedLocale = localStorage.getItem("locale") as Locale;
if (savedLocale && locales.includes(savedLocale)) {
return savedLocale;
}
}
return initialLocale;
};
const [locale, setLocale] = useState<Locale>(getInitialLocale);
useEffect(() => {
const initialLocale = getInitialLocale();
i18n.load(initialLocale, messages[initialLocale]);
i18n.activate(initialLocale);
}, [getInitialLocale]);
// Save locale to localStorage and activate it when it changes
useEffect(() => {
localStorage.setItem("locale", locale);
i18n.load(locale, messages[locale]);
i18n.activate(locale);
}, [locale]);
return (
<LinguiContext.Provider
value={{ locale, setLocale, availableLocales: locales }}
>
<I18nProvider i18n={i18n}>{children}</I18nProvider>
</LinguiContext.Provider>
);
}

View File

@@ -1,4 +1,5 @@
import Link from "next/link";
import { t } from "@lingui/core/macro";
import { useEffect, useState } from "react";
import Button from "~/components/Button";
@@ -50,15 +51,14 @@ const Cta = ({ theme }: { theme: string }) => {
<p>kan.bn/{currentWorkspaceSlug}</p>
</div>
<h2 className="text-balance text-4xl font-bold tracking-tight text-light-1000 dark:text-dark-1000 sm:text-4xl">
Get started for free today
{t`Get started for free today`}
</h2>
<p className="text-md/8 mx-auto mt-6 max-w-[375px] text-pretty text-light-900 dark:text-dark-900">
Unlimited boards, unlimited lists, unlimited cards. No credit card
required.
{t`Unlimited boards, unlimited lists, unlimited cards. No credit card required.`}
</p>
<Link href="/signup">
<div className="mt-10 flex items-center justify-center gap-x-6">
<Button size="lg">Get started</Button>
<Button size="lg">{t`Get started`}</Button>
</div>
</Link>
</div>

View File

@@ -4,6 +4,8 @@ import {
DisclosureButton,
DisclosurePanel,
} from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { HiMiniMinusSmall, HiMiniPlusSmall } from "react-icons/hi2";
const Text = ({ children }: { children: React.ReactNode }) => {
@@ -16,118 +18,115 @@ const Text = ({ children }: { children: React.ReactNode }) => {
const faqs = [
{
question: "Why make an open source Trello?",
question: t`Why make an open source Trello?`,
answer: (
<Text>
When Trello launched in 2011, it blew everyone away with its carefully
designed simplicity, but over time (and atlassification) it lost its
magic and grew into something closer to "Jira Lite". This project is our
attempt to recapture the original magic of Trellos simplicity, in open
source.
{t`When Trello launched in 2011, it blew everyone away with its carefully designed simplicity, but over time (and atlassification) it lost its magic and grew into something closer to "Jira Lite". This project is our attempt to recapture the original magic of Trellos simplicity, in open source.`}
</Text>
),
},
{
question: "What's the difference between Kan and Trello?",
question: t`What's the difference between Kan and Trello?`,
answer: (
<Text>
The main difference between Kan and Trello is that Kan is open source,
allowing anyone to view, modify, and contribute to our code. Our cloud
offering also offers no restrictions on features for individual use,
whereas Trello locks basic features such as the number of boards you can
create behind a paywall.
{t`The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall.`}
</Text>
),
},
{
question: "How is the project funded?",
question: t`How is the project funded?`,
answer: (
<Text>
For long-term sustainability, we recognise all good open source projects
need a source of revenue. Ours comes from the paid cloud offering for
workspaces with multiple users (free during the beta) and for custom
workspace slugs. There's no obligation to use it, and you can self-host
the software on your own infrastructure free of charge.
{t`For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge.`}
</Text>
),
},
{
question: "How do I import my Trello boards?",
question: t`How do I import my Trello boards?`,
answer: (
<Text>
Importing your Trello boards into Kan is easy. You can follow our
step-by-step guide{" "}
<Link href="https://docs.kan.bn/imports/trello" className="underline">
here
</Link>
.
<Trans>
Importing your Trello boards into Kan is easy. You can follow our
step-by-step guide{" "}
<Link href="https://docs.kan.bn/imports/trello" className="underline">
here
</Link>
.
</Trans>
</Text>
),
},
{
question: "How do I get a custom URL?",
question: t`How do I get a custom URL?`,
answer: (
<Text>
You can get a custom workspace URL, like{" "}
<Link href="https://kan.bn/kan" className="underline">
kan.bn/kan
</Link>
, by going into your{" "}
<Link href="https://kan.bn/settings" className="underline">
workspace settings
</Link>{" "}
and purchasing a pro workspace subscription. All subscriptions help fund
the development of the project!
<Trans>
You can get a custom workspace URL, like{" "}
<Link href="https://kan.bn/kan" className="underline">
kan.bn/kan
</Link>
, by going into your{" "}
<Link href="https://kan.bn/settings" className="underline">
workspace settings
</Link>{" "}
and purchasing a pro workspace subscription. All subscriptions help
fund the development of the project!
</Trans>
</Text>
),
},
{
question: "Do you offer a free plan?",
question: t`Do you offer a free plan?`,
answer: (
<Text>
Yes, we offer an forever free plan for individual use. No restrictions,
no paywalls, no limits.
{t`Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits.`}
</Text>
),
},
{
question: "What license are you using?",
question: t`What license are you using?`,
answer: (
<Text>
We are using the{" "}
<Link
href="https://github.com/kan-bn/kan/blob/main/LICENSE"
className="underline"
>
AGPL-3.0 license
</Link>
.
<Trans>
We are using the{" "}
<Link
href="https://github.com/kan-bn/kan/blob/main/LICENSE"
className="underline"
>
AGPL-3.0 license
</Link>
.
</Trans>
</Text>
),
},
{
question: "How do I invite team members?",
question: t`How do I invite team members?`,
answer: (
<Text>
You can invite team members by clicking the "Invite" button in the top
right corner of the{" "}
<Link href="https://kan.bn/members" className="underline">
members page
</Link>{" "}
and entering their email address. They will receive an email with a link
to join the workspace.
<Trans>
You can invite team members by clicking the "Invite" button in the top
right corner of the{" "}
<Link href="https://kan.bn/members" className="underline">
members page
</Link>{" "}
and entering their email address. They will receive an email with a
link to join the workspace.
</Trans>
</Text>
),
},
{
question: "How do I self-host?",
question: t`How do I self-host?`,
answer: (
<Text>
You can self-host by following the instructions in our{" "}
<Link href="https://github.com/kanbn/kan" className="underline">
repo
</Link>
.
<Trans>
You can self-host by following the instructions in our{" "}
<Link href="https://github.com/kanbn/kan" className="underline">
repo
</Link>
.
</Trans>
</Text>
),
},
@@ -138,19 +137,21 @@ const Faqs = () => {
<div className="mx-auto max-w-[900px] px-4">
<div className="flex flex-col items-center justify-center pb-12">
<div className="flex items-center gap-2 rounded-full border bg-light-50 px-4 py-1 text-center text-xs text-light-1000 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900 lg:text-sm">
<p>FAQs</p>
<p>{t`FAQs`}</p>
</div>
<p className="mt-2 text-center text-3xl font-bold text-light-1000 dark:text-dark-1000 lg:text-4xl">
Questions?
{t`Questions?`}
</p>
<p className="text:md lg:text-md mt-3 max-w-[500px] text-center text-dark-900">
Find answers to common questions about the project. Can't find what
you're looking for? Feel free to{" "}
<Link href="mailto:support@kan.bn" className="underline">
contact us
</Link>
.
<Trans>
Find answers to common questions about the project. Can't find what
you're looking for? Feel free to{" "}
<Link href="mailto:support@kan.bn" className="underline">
contact us
</Link>
.
</Trans>
</p>
</div>
<div className="rounded-2xl bg-light-50 ring-1 ring-light-300 dark:bg-dark-50 dark:ring-dark-400">

View File

@@ -1,4 +1,5 @@
import Link from "next/link";
import { t } from "@lingui/core/macro";
import { useState } from "react";
import activityLogsIconDark from "~/assets/activity-logs-dark.json";
@@ -62,7 +63,7 @@ const FeatureItem = ({
{feature.comingSoon && (
<div className="absolute right-4 top-4 rounded-full border border-light-300 px-2 py-1 text-[10px] text-light-1000 dark:border-dark-600 dark:bg-dark-50 dark:text-dark-900">
Coming soon
{t`Coming soon`}
</div>
)}
</div>
@@ -73,45 +74,44 @@ const Features = ({ theme }: { theme: "light" | "dark" }) => {
const isDark = theme === "dark";
const features = [
{
title: "Board visibility",
description: "Control who can view and edit your boards.",
title: t`Board visibility`,
description: t`Control who can view and edit your boards.`,
icon: isDark ? boardVisibilityIconDark : boardVisibilityIconLight,
},
{
title: "Workspace members",
description: "Collaborate seamlessly with your team.",
title: t`Workspace members`,
description: t`Collaborate seamlessly with your team.`,
icon: isDark ? membersIconDark : membersIconLight,
},
{
title: "Trello imports",
description: "Import your Trello boards and hit the ground running.",
title: t`Trello imports`,
description: t`Import your Trello boards and hit the ground running.`,
icon: isDark ? importsIconDark : importsIconLight,
},
{
title: "Labels & Filters",
description:
"Organize and find cards quickly with powerful filtering tools.",
title: t`Labels & Filters`,
description: t`Organize and find cards quickly with powerful filtering tools.`,
icon: isDark ? labelsIconDark : labelsIconLight,
},
{
title: "Comments",
description: "Discuss and collaborate on cards.",
title: t`Comments`,
description: t`Discuss and collaborate on cards.`,
icon: isDark ? commentsIconDark : commentsIconLight,
},
{
title: "Activity logs",
description: "Track all card changes with detailed activity history.",
title: t`Activity logs`,
description: t`Track all card changes with detailed activity history.`,
icon: isDark ? activityLogsIconDark : activityLogsIconLight,
},
{
title: "Templates",
description: "Save time with reusable board templates.",
title: t`Templates`,
description: t`Save time with reusable board templates.`,
icon: isDark ? templatesIconDark : templatesIconLight,
comingSoon: true,
},
{
title: "Integrations",
description: "Connect your favorite tools to streamline your workflow.",
title: t`Integrations`,
description: t`Connect your favorite tools to streamline your workflow.`,
icon: isDark ? integrationsIconDark : integrationsIconLight,
comingSoon: true,
},
@@ -121,15 +121,14 @@ const Features = ({ theme }: { theme: "light" | "dark" }) => {
<>
<div className="flex flex-col items-center justify-center px-4 pb-24">
<div className="flex items-center gap-2 rounded-full border bg-light-50 px-4 py-1 text-center text-xs text-light-1000 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900 lg:text-sm">
<p>Features</p>
<p>{t`Features`}</p>
</div>
<p className="mt-2 text-center text-3xl font-bold text-light-1000 dark:text-dark-1000 lg:text-4xl">
Kanban reimagined
{t`Kanban reimagined`}
</p>
<p className="text-md lg:text-md mt-3 max-w-[500px] text-center text-dark-900">
Simple, visual task management that just works. Drag and drop cards,
collaborate with your team, and get more done.
{t`Simple, visual task management that just works. Drag and drop cards, collaborate with your team, and get more done.`}
</p>
<div className="mx-auto mt-16 w-full max-w-7xl">
<div className="grid w-full grid-cols-1 gap-4 [mask-image:linear-gradient(to_bottom,black_92%,transparent_100%)] sm:grid-cols-2 md:grid-cols-3 md:[mask-image:linear-gradient(to_bottom,black_85%,transparent_100%)] lg:grid-cols-4 lg:[mask-image:linear-gradient(to_bottom,black_85%,transparent_100%)]">
@@ -142,9 +141,9 @@ const Features = ({ theme }: { theme: "light" | "dark" }) => {
<div>
<div className="mt-8 flex items-center gap-2 rounded-full border bg-light-50 px-4 py-1 text-center text-sm text-light-1000 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900">
<p className="text-xs lg:text-sm">
{`We're just getting started. `}
{t`We're just getting started. `}
<Link href="/kan/roadmap" className="underline">
View our roadmap.
{t`View our roadmap.`}
</Link>
</p>
</div>

View File

@@ -1,6 +1,8 @@
import Link from "next/link";
import { FaDiscord, FaGithub } from "react-icons/fa";
import { LanguageSelector } from "~/components/LanguageSelector";
const navigation = {
documentation: [
{ name: "Getting started", href: "https://docs.kan.bn/introduction" },
@@ -64,6 +66,7 @@ const Footer = () => {
</div>
<StatusMarker />
<LanguageSelector />
</div>
<div className="mt-16 grid grid-cols-2 gap-8 xl:col-span-2 xl:mt-0">

View File

@@ -1,4 +1,5 @@
import Link from "next/link";
import { t } from "@lingui/core/macro";
import { useEffect, useState } from "react";
import { twMerge } from "tailwind-merge";
@@ -9,10 +10,10 @@ const Header = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const menuItems = [
{ label: "Roadmap", href: "/kan/roadmap", openInNewTab: true },
{ label: "Features", href: "#features" },
{ label: "Pricing", href: "#pricing" },
{ label: "Docs", href: "https://docs.kan.bn", openInNewTab: true },
{ label: t`Roadmap`, href: "/kan/roadmap", openInNewTab: true },
{ label: t`Features`, href: "#features" },
{ label: t`Pricing`, href: "#pricing" },
{ label: t`Docs`, href: "https://docs.kan.bn", openInNewTab: true },
];
useEffect(() => {
@@ -92,13 +93,13 @@ const Header = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
</button>
<div className="hidden w-[200px] justify-end gap-2 lg:flex">
{isLoggedIn ? (
<Button href="/boards">Go to app</Button>
<Button href="/boards">{t`Go to app`}</Button>
) : (
<>
<Button href="/login" variant="ghost">
Sign in
{t`Sign in`}
</Button>
<Button href="/signup">Get started</Button>
<Button href="/signup">{t`Get started`}</Button>
</>
)}
</div>
@@ -129,15 +130,15 @@ const Header = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
<div className="mt-8 flex flex-col gap-4">
{isLoggedIn ? (
<Button href="/boards" onClick={toggleMenu}>
Go to app
{t`Go to app`}
</Button>
) : (
<>
<Button href="/login" variant="ghost" onClick={toggleMenu}>
Sign in
{t`Sign in`}
</Button>
<Button href="/signup" onClick={toggleMenu}>
Get started
{t`Get started`}
</Button>
</>
)}

View File

@@ -1,5 +1,6 @@
import Link from "next/link";
import { Radio, RadioGroup } from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { useState } from "react";
import { HiCheckCircle } from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
@@ -9,68 +10,65 @@ type Frequency = "monthly" | "annually";
const frequencies = [
{
value: "monthly" as Frequency,
label: "Monthly",
priceSuffix: "per user/month",
label: t`Monthly`,
priceSuffix: t`per user/month`,
},
{
value: "annually" as Frequency,
label: "Yearly",
priceSuffix: "per user/month",
label: t`Yearly`,
priceSuffix: t`per user/month`,
},
];
const tiers = [
{
name: "Individuals",
name: t`Individuals`,
id: "tier-individuals",
href: "signup",
buttonText: "Get Started",
price: { monthly: "Free", annually: "Free" },
description:
"Everything you need, free forever. Unlimited boards, unlimited lists, unlimited cards. Upgrade any time.",
featureHeader: "Free, forever",
buttonText: t`Get Started`,
price: { monthly: t`Free`, annually: t`Free` },
description: t`Everything you need, free forever. Unlimited boards, unlimited lists, unlimited cards. Upgrade any time.`,
featureHeader: t`Free, forever`,
features: [
"1 user",
"Unlimited boards",
"Unlimited lists",
"Unlimited cards",
"Unlimited comments",
"Unlimited activity log",
t`1 user`,
t`Unlimited boards`,
t`Unlimited lists`,
t`Unlimited cards`,
t`Unlimited comments`,
t`Unlimited activity log`,
],
showPrice: true,
},
{
name: "Teams",
name: t`Teams`,
id: "tier-teams",
href: "signup",
buttonText: "Get Started",
buttonText: t`Get Started`,
price: { monthly: "$10.00", annually: "$8.00" },
description:
"Kanban is better with a team. Perfect for small and growing teams looking to collaborate.",
featureHeader: "Everything in the free plan, plus:",
description: t`Kanban is better with a team. Perfect for small and growing teams looking to collaborate.`,
featureHeader: t`Everything in the free plan, plus:`,
features: [
"Workspace members",
"Admin roles",
"Priority email support",
"Support the development of the project",
t`Workspace members`,
t`Admin roles`,
t`Priority email support`,
t`Support the development of the project`,
],
highlighted: true,
showPrice: true,
showPriceSuffix: true,
},
{
name: "Self Host",
name: t`Self Host`,
id: "tier-self-host",
href: "https://github.com/kanbn/kan",
buttonText: "View docs",
buttonText: t`View docs`,
price: { monthly: "-", annually: "-" },
description:
"Host Kan on your own infrastructure. Ideal for organisations that need complete control over their data.",
featureHeader: "Complete control and ownership:",
description: t`Host Kan on your own infrastructure. Ideal for organisations that need complete control over their data.`,
featureHeader: t`Complete control and ownership:`,
features: [
"Run on your own infrastructure",
"Own your data",
"Custom domain",
t`Run on your own infrastructure`,
t`Own your data`,
t`Custom domain`,
],
mostPopular: false,
showPrice: false,
@@ -85,20 +83,19 @@ const Pricing = () => {
<>
<div className="flex flex-col items-center justify-center px-4 pb-10">
<div className="flex items-center gap-2 rounded-full border bg-light-50 px-4 py-1 text-center text-xs text-light-1000 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900 lg:text-sm">
<p>Pricing</p>
<p>{t`Pricing`}</p>
</div>
<p className="mt-2 text-center text-3xl font-bold text-light-1000 dark:text-dark-1000 lg:text-4xl">
Simple pricing
{t`Simple pricing`}
</p>
<p className="text:md lg:text-md mt-3 max-w-[500px] text-center text-dark-900">
Get started for free, with no usage limits. For collaboration, upgrade
to a plan that fits the size of your team.
{t`Get started for free, with no usage limits. For collaboration, upgrade to a plan that fits the size of your team.`}
</p>
{/* Beta free pricing pill */}
<div className="mt-4 flex items-center gap-2 rounded-full bg-green-100 px-3 py-1 text-xs font-semibold text-green-800 dark:bg-green-700 dark:text-green-100">
All seats are free during the beta until Sept 1st!
{t`All seats are free during the beta until Sept 1st!`}
</div>
<div className="mt-16 flex justify-center">

View File

@@ -1,5 +1,7 @@
import Image from "next/image";
import Link from "next/link";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { IoLogoGithub, IoLogoHackernews } from "react-icons/io";
import Button from "~/components/Button";
@@ -32,7 +34,7 @@ export default function HomeView() {
target="_blank"
className="flex items-center gap-2 px-4 py-1 text-center text-xs text-light-1000 dark:text-dark-1000 lg:text-sm"
>
Star on Github
{t`Star on Github`}
<IoLogoGithub size={20} />
</Link>
</div>
@@ -46,7 +48,7 @@ export default function HomeView() {
target="_blank"
className="flex items-center gap-2 px-4 py-1 text-center text-xs text-light-1000 dark:text-dark-1000 lg:text-sm"
>
#1 Hacker News
{t`#1 Hacker News`}
<div className="relative">
<div className="absolute inset-1 bg-white" />
<IoLogoHackernews
@@ -60,27 +62,28 @@ export default function HomeView() {
</div>
<p className="mt-2 text-center text-4xl font-bold text-light-1000 dark:text-dark-1000 lg:text-5xl">
The open source <br />
alternative to Trello
<Trans>
The open source <br /> alternative to Trello
</Trans>
</p>
<p className="text-md mt-3 max-w-[450px] text-center text-dark-900 lg:max-w-[600px] lg:text-lg">
A powerful, flexible kanban app that helps you organise work,
track progress, and deliver resultsall in one place.
{t`A powerful, flexible kanban app that helps you organise work,
track progress, and deliver results—all in one place.`}
</p>
<div className="mt-6 flex gap-2">
<Button href="/signup">Get started on Cloud</Button>
<Button href="/signup">{t`Get started on Cloud`}</Button>
<Button
variant="secondary"
href="https://github.com/kanbn/kan"
openInNewTab
>
Self host with Github
{t`Self host with Github`}
</Button>
</div>
<p className="mt-4 text-center text-sm text-dark-900">
No credit card required
{t`No credit card required`}
</p>
</div>
</div>

1910
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff