Skip to content

Commit

Permalink
feat(i18n): implement localization using LinguiJS
Browse files Browse the repository at this point in the history
  • Loading branch information
AmruthPillai committed Nov 10, 2023
1 parent 13d9141 commit 6ad4358
Show file tree
Hide file tree
Showing 108 changed files with 4,631 additions and 798 deletions.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ Thumbs.db

# Generated Files
.nx
.swc
stats.html
libs/prisma

# Environment Variables
*.env*
!.env.example
!.env.example

# Lingui Compiled Messages
apps/client/src/locales/_build/
apps/client/src/locales/**/*.js
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
"https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json": [
"tools/compose/*"
]
}
},
"i18n-ally.localesPaths": [
"apps/client/src/locales"
]
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
![App Version](https://img.shields.io/github/package-json/version/AmruthPillai/Reactive-Resume/v4?label=version)
[![Docker Pulls](https://img.shields.io/docker/pulls/amruthpillai/reactive-resume)](https://hub.docker.com/repository/docker/amruthpillai/reactive-resume)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/AmruthPillai)](https://github.com/sponsors/AmruthPillai)
[![Crowdin](https://badges.crowdin.net/reactive-resume/localized.svg)](https://crowdin.com/project/reactive-resume)

# Reactive Resume

Expand Down
22 changes: 21 additions & 1 deletion apps/client/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,29 @@
"config": "tailwind.config.js"
}
},
"plugins": ["lingui"],
"rules": {
// react-hooks
"react-hooks/exhaustive-deps": "off"
"react-hooks/exhaustive-deps": "off",

// lingui
"lingui/no-unlocalized-strings": 2,
"lingui/t-call-in-function": 2,
"lingui/no-single-variables-to-translate": 2,
"lingui/no-expression-in-message": 2,
"lingui/no-single-tag-to-translate": 2,
"lingui/no-trans-inside-trans": 2,
"lingui/text-restrictions": [
2,
{
"rules": [
{
"patterns": ["''", "\"", "’", "“"],
"message": "This string contains forbidden characters"
}
]
}
]
}
},
{
Expand Down
1 change: 1 addition & 0 deletions apps/client/public/scripts/initialize-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
try {
if (
localStorage.theme === "dark" ||
// eslint-disable-next-line lingui/no-unlocalized-strings
window.matchMedia("(prefers-color-scheme: dark)").matches
) {
document.documentElement.classList.add("dark");
Expand Down
30 changes: 15 additions & 15 deletions apps/client/src/components/ai-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@lingui/macro";
import {
CaretDown,
ChatTeardropText,
Expand Down Expand Up @@ -39,15 +40,14 @@ export const AiActions = ({ value, onChange, className }: Props) => {

const onClick = async (action: Action, mood?: Mood) => {
setLoading(action);
let result = value;

// await new Promise((resolve) => setTimeout(resolve, 2000));
let result = value;

if (action === "improve") result = await improveWriting(value);
if (action === "fix") result = await fixGrammar(value);
if (action === "tone" && mood) result = await changeTone(value, mood);

onChange("Result" + result);
onChange(result);

setLoading(false);
};
Expand All @@ -67,52 +67,52 @@ export const AiActions = ({ value, onChange, className }: Props) => {
className="-rotate-90 bg-background px-2 text-[10px] leading-[10px]"
>
<MagicWand size={10} className="mr-1" />
AI
{t`AI`}
</Badge>
</div>

<Button size="sm" variant="outline" disabled={!!loading} onClick={() => onClick("improve")}>
{loading === "improve" ? <CircleNotch className="animate-spin" /> : <PenNib />}
<span className="ml-2 text-xs">Improve Writing</span>
<span className="ml-2 text-xs">{t`Improve Writing`}</span>
</Button>

<Button size="sm" variant="outline" disabled={!!loading} onClick={() => onClick("fix")}>
{loading === "fix" ? <CircleNotch className="animate-spin" /> : <Exam />}
<span className="ml-2 text-xs">Fix Spelling & Grammar</span>
<span className="ml-2 text-xs">{t`Fix Spelling & Grammar`}</span>
</Button>

<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="sm" variant="outline" disabled={!!loading}>
{loading === "tone" ? <CircleNotch className="animate-spin" /> : <ChatTeardropText />}
<span className="mx-2 text-xs">Change Tone</span>
<span className="mx-2 text-xs">{t`Change Tone`}</span>
<CaretDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={() => onClick("tone", "casual")}>
<span role="img" aria-label="Casual">
<span role="img" aria-label={t`Casual`}>
🙂
</span>
<span className="ml-2">Casual</span>
<span className="ml-2">{t`Casual`}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onClick("tone", "professional")}>
<span role="img" aria-label="Professional">
<span role="img" aria-label={t`Professional`}>
💼
</span>
<span className="ml-2">Professional</span>
<span className="ml-2">{t`Professional`}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onClick("tone", "confident")}>
<span role="img" aria-label="Confident">
<span role="img" aria-label={t`Confident`}>
😎
</span>
<span className="ml-2">Confident</span>
<span className="ml-2">{t`Confident`}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onClick("tone", "friendly")}>
<span role="img" aria-label="Friendly">
<span role="img" aria-label={t`Friendly`}>
😊
</span>
<span className="ml-2">Friendly</span>
<span className="ml-2">{t`Friendly`}</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
35 changes: 21 additions & 14 deletions apps/client/src/components/copyright.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t, Trans } from "@lingui/macro";
import { cn } from "@reactive-resume/utils";

type Props = {
Expand All @@ -12,23 +13,29 @@ export const Copyright = ({ className }: Props) => (
)}
>
<span>
Licensed under{" "}
<a
target="_blank"
rel="noopener noreferrer nofollow"
href="https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE"
>
MIT
</a>
<Trans>
Licensed under{" "}
<a
target="_blank"
rel="noopener noreferrer nofollow"
href="https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE"
>
MIT
</a>
</Trans>
</span>
<span>By the community, for the community.</span>
<span>{t`By the community, for the community.`}</span>
<span>
A passion project by{" "}
<a target="_blank" rel="noopener noreferrer nofollow" href="https://www.amruthpillai.com/">
Amruth Pillai
</a>
<Trans>
A passion project by{" "}
<a target="_blank" rel="noopener noreferrer nofollow" href="https://www.amruthpillai.com/">
Amruth Pillai
</a>
</Trans>
</span>

<span className="mt-2 font-bold">Reactive Resume v{appVersion}</span>
<span className="mt-4">
{t`Reactive Resume`} {"v" + appVersion}
</span>
</div>
);
3 changes: 2 additions & 1 deletion apps/client/src/components/icon.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@lingui/macro";
import { useTheme } from "@reactive-resume/hooks";
import { cn } from "@reactive-resume/utils";

Expand Down Expand Up @@ -25,7 +26,7 @@ export const Icon = ({ size = 32, className }: Props) => {
src={src}
width={size}
height={size}
alt="Reactive Resume"
alt={t`Reactive Resume`}
className={cn("rounded-sm", className)}
/>
);
Expand Down
3 changes: 2 additions & 1 deletion apps/client/src/components/logo.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@lingui/macro";
import { useTheme } from "@reactive-resume/hooks";
import { cn } from "@reactive-resume/utils";

Expand Down Expand Up @@ -25,7 +26,7 @@ export const Logo = ({ size = 32, className }: Props) => {
src={src}
width={size}
height={size}
alt="Reactive Resume"
alt={t`Reactive Resume`}
className={cn("rounded-sm", className)}
/>
);
Expand Down
7 changes: 5 additions & 2 deletions apps/client/src/components/user-options.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@lingui/macro";
import {
DropdownMenu,
DropdownMenuContent,
Expand All @@ -24,12 +25,14 @@ export const UserOptions = ({ children }: Props) => {

<DropdownMenuContent side="top" align="start" className="w-48">
<DropdownMenuItem onClick={() => navigate("/dashboard/settings")}>
Settings
{t`Settings`}
{/* eslint-disable-next-line lingui/no-unlocalized-strings */}
<KeyboardShortcut>⇧S</KeyboardShortcut>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => logout()}>
Logout
{t`Logout`}
{/* eslint-disable-next-line lingui/no-unlocalized-strings */}
<KeyboardShortcut>⇧Q</KeyboardShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
Expand Down
16 changes: 16 additions & 0 deletions apps/client/src/libs/lingui.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { i18n } from "@lingui/core";
import { t } from "@lingui/macro";

export const getLocales = () => ({
"en-US": t`English`,
"de-DE": t`German`,
});

export const defaultLocale = "en-US";

export async function dynamicActivate(locale: string) {
const { messages } = await import(`../locales/${locale}.po`);

i18n.load(locale, messages);
i18n.activate(locale);
}
Loading

0 comments on commit 6ad4358

Please sign in to comment.