-
Notifications
You must be signed in to change notification settings - Fork 828
feat(community): add auto-localized notes demo (NextJS) #1857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
hi your PR is missing changeset. Please add the changeset by following instructions here. Make sure you've joined our discord to see this message. If you haven't you need to:
Please also sign your commits. Only one of your commits is verified. |
📝 WalkthroughWalkthroughAdds a new Next.js demo app under Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client as "Client (page.tsx)"
participant Server as "Next.js Server Action\n(actions/translate.ts)"
participant Lingo as "lingo.dev SDK / API"
Client->>Server: recognizeText(text)
Server->>Lingo: recognizeLocale(text)
Lingo-->>Server: detectedLocale
Server-->>Client: detectedLocale
Client->>Server: translateText(text, from, to)
Server->>Lingo: localizeText({ sourceLocale: from, targetLocale: to, text })
Lingo-->>Server: translatedText
Server-->>Client: translatedText
Client->>Client: prepend note(original, translated, detectedLang)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@community/auto-localized-notes/app/globals.css`:
- Around line 22-26: The body CSS currently hardcodes "Arial, Helvetica,
sans-serif" so the declared Geist font variables are ignored; update the body
selector's font-family to use the declared CSS variable (e.g., replace
font-family: Arial, Helvetica, sans-serif; with font-family: var(--font-sans,
Arial, Helvetica, sans-serif);) so the Geist font variable is applied while
keeping a fallback.
In `@community/auto-localized-notes/app/page.tsx`:
- Around line 147-152: The Translated label is using the current dropdown state
`{lang}` instead of the note's actual target language; update the Note type (or
whatever model holds notes) to include a targetLang field, set that field when
creating a note in handleSubmit (use the selected lang value at submit time),
and change the JSX to render the stored target language (e.g., use
note.targetLang instead of lang) so existing notes keep their original
translation language regardless of later dropdown changes.
- Around line 27-46: The handleSubmit function lacks error handling for the
async server actions recognizeText and translateText, so failures are swallowed
and users get no feedback; wrap the startTransition callback in a try/catch (or
place try/catch inside the async callback) to catch errors from
recognizeText/translateText, set an error state (e.g., setError or a local error
flag) and avoid mutating state on failure, and optionally call setText("") only
on success; update UI to render the error state. Reference handleSubmit,
recognizeText, translateText, setNotes, and setText when making the changes.
In `@community/auto-localized-notes/package.json`:
- Around line 11-15: The package.json is missing the lingo.dev SDK that
app/actions/translate.ts imports; add "lingo.dev" to the "dependencies" object
in package.json (using the appropriate SDK version your demo expects) and
reinstall deps so the demo is self-contained and builds correctly; update
package.json's "dependencies" to include "lingo.dev" and run npm/yarn install to
pick up the new dependency.
🧹 Nitpick comments (3)
community/auto-localized-notes/README.md (1)
55-77: Add language specifiers to fenced code blocks.The shell command blocks are missing language identifiers, which affects syntax highlighting and accessibility.
Suggested fix
-``` +```bash git clone <repo-url> cd auto-localized-notes```diff -``` +```bash npm install # or pnpm install```diff -``` +```bash npm run dev```diff -``` +```text http://localhost:3000</details> </blockquote></details> <details> <summary>community/auto-localized-notes/app/layout.tsx (1)</summary><blockquote> `26-28`: **Consider setting `<html lang>` from the detected locale.** If the page renders non‑English content, hardcoding `lang="en"` can confuse screen readers and SEO. You could derive it from `Accept-Language` or your detected locale and pass it into the layout. </blockquote></details> <details> <summary>community/auto-localized-notes/app/page.tsx (1)</summary><blockquote> `23-25`: **Avoid `any` type for event handlers.** Use the proper React event type for better type safety. <details> <summary>✨ Suggested improvement</summary> ```diff - const handleChange = (e: any) => { + const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => { setLang(e.target.value); };
| body { | ||
| background: var(--background); | ||
| color: var(--foreground); | ||
| font-family: Arial, Helvetica, sans-serif; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the declared font variables instead of hardcoded Arial.
Right now the Geist font variables are set but never used, so the app renders with Arial/Helvetica. Switching to the variable makes the font import effective.
♻️ Suggested change
body {
background: var(--background);
color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
+ font-family: var(--font-sans, Arial, Helvetica, sans-serif);
}🤖 Prompt for AI Agents
In `@community/auto-localized-notes/app/globals.css` around lines 22 - 26, The
body CSS currently hardcodes "Arial, Helvetica, sans-serif" so the declared
Geist font variables are ignored; update the body selector's font-family to use
the declared CSS variable (e.g., replace font-family: Arial, Helvetica,
sans-serif; with font-family: var(--font-sans, Arial, Helvetica, sans-serif);)
so the Geist font variable is applied while keeping a fallback.
| const handleSubmit = () => { | ||
| if (!text.trim()) return; | ||
|
|
||
| startTransition(async () => { | ||
| const detectedLang = await recognizeText(text); | ||
| const result = await translateText(text, detectedLang, lang); | ||
|
|
||
| setNotes((prev) => [ | ||
| { | ||
| id: crypto.randomUUID(), | ||
| original: text, | ||
| translated: result, | ||
| detectedLang: detectedLang, | ||
| }, | ||
| ...prev, | ||
| ]); | ||
|
|
||
| setText(""); | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for server action calls.
If recognizeText or translateText fails (e.g., network error, service unavailable), the error will be silently ignored and the user receives no feedback. Consider wrapping in try/catch and displaying an error state.
🛡️ Suggested fix with error handling
+ const [error, setError] = useState<string | null>(null);
+
const handleSubmit = () => {
if (!text.trim()) return;
+ setError(null);
startTransition(async () => {
- const detectedLang = await recognizeText(text);
- const result = await translateText(text, detectedLang, lang);
-
- setNotes((prev) => [
- {
- id: crypto.randomUUID(),
- original: text,
- translated: result,
- detectedLang: detectedLang,
- },
- ...prev,
- ]);
-
- setText("");
+ try {
+ const detectedLang = await recognizeText(text);
+ const result = await translateText(text, detectedLang, lang);
+
+ setNotes((prev) => [
+ {
+ id: crypto.randomUUID(),
+ original: text,
+ translated: result,
+ detectedLang: detectedLang,
+ },
+ ...prev,
+ ]);
+
+ setText("");
+ } catch (err) {
+ setError("Translation failed. Please try again.");
+ }
});
};🤖 Prompt for AI Agents
In `@community/auto-localized-notes/app/page.tsx` around lines 27 - 46, The
handleSubmit function lacks error handling for the async server actions
recognizeText and translateText, so failures are swallowed and users get no
feedback; wrap the startTransition callback in a try/catch (or place try/catch
inside the async callback) to catch errors from recognizeText/translateText, set
an error state (e.g., setError or a local error flag) and avoid mutating state
on failure, and optionally call setText("") only on success; update UI to render
the error state. Reference handleSubmit, recognizeText, translateText, setNotes,
and setText when making the changes.
| <div className="space-y-1"> | ||
| <p className="text-xs font-semibold text-gray-500 dark:text-gray-400"> | ||
| Translated ({lang}) | ||
| </p> | ||
| <p className="text-sm whitespace-pre-wrap">{note.translated}</p> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Translated language label shows current selection, not the actual target language.
Line 149 displays {lang} which is the currently selected language in the dropdown, not the language the note was actually translated to. If a user creates a note translated to French, then changes the dropdown to Spanish, the existing note will incorrectly show "Translated (es)" even though the text is in French.
🐛 Suggested fix: store target language per note
Update the Note type to include targetLang:
type Note = {
id: string;
original: string;
translated: string;
detectedLang: string;
+ targetLang: string;
};Store it when creating the note in handleSubmit:
setNotes((prev) => [
{
id: crypto.randomUUID(),
original: text,
translated: result,
detectedLang: detectedLang,
+ targetLang: lang,
},
...prev,
]);Display the stored value in the JSX:
<p className="text-xs font-semibold text-gray-500 dark:text-gray-400">
- Translated ({lang})
+ Translated ({note.targetLang})
</p>🤖 Prompt for AI Agents
In `@community/auto-localized-notes/app/page.tsx` around lines 147 - 152, The
Translated label is using the current dropdown state `{lang}` instead of the
note's actual target language; update the Note type (or whatever model holds
notes) to include a targetLang field, set that field when creating a note in
handleSubmit (use the selected lang value at submit time), and change the JSX to
render the stored target language (e.g., use note.targetLang instead of lang) so
existing notes keep their original translation language regardless of later
dropdown changes.
| "dependencies": { | ||
| "next": "16.1.4", | ||
| "react": "19.2.3", | ||
| "react-dom": "19.2.3" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing lingo.dev dependency.
The demo uses lingo.dev SDK in app/actions/translate.ts but doesn't declare it as a dependency. Add it to ensure the demo is self-contained:
Suggested fix
"dependencies": {
"next": "16.1.4",
"react": "19.2.3",
- "react-dom": "19.2.3"
+ "react-dom": "19.2.3",
+ "lingo.dev": "^0.122.1"
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "dependencies": { | |
| "next": "16.1.4", | |
| "react": "19.2.3", | |
| "react-dom": "19.2.3" | |
| }, | |
| "dependencies": { | |
| "next": "16.1.4", | |
| "react": "19.2.3", | |
| "react-dom": "19.2.3", | |
| "lingo.dev": "^0.122.1" | |
| }, |
🤖 Prompt for AI Agents
In `@community/auto-localized-notes/package.json` around lines 11 - 15, The
package.json is missing the lingo.dev SDK that app/actions/translate.ts imports;
add "lingo.dev" to the "dependencies" object in package.json (using the
appropriate SDK version your demo expects) and reinstall deps so the demo is
self-contained and builds correctly; update package.json's "dependencies" to
include "lingo.dev" and run npm/yarn install to pick up the new dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@community/auto-localized-notes/app/actions/translate.ts`:
- Around line 9-35: Both translateText and recognizeText currently return
sentinel error strings ("error translating the text"/"error detecting the
language") which can collide with valid outputs; change their error handling to
return null (or a structured error object) instead of strings and preserve
logging. Specifically, in translateText and recognizeText catch blocks
(functions named translateText and recognizeText) replace the string returns
with return null (or an Error-style result) and keep console.error(error) so
callers can detect failures explicitly and handle null results appropriately.
- Around line 5-7: Check for process.env.LINGODOTDEV_API_KEY and throw a clear
error before initializing LingoDotDevEngine to fail fast; if the env var is
missing, log/throw a descriptive message like "Missing LINGODOTDEV_API_KEY" and
abort initialization so you don't create lingoDotDev with undefined. Update the
initialization site where new LingoDotDevEngine({ apiKey:
process.env.LINGODOTDEV_API_KEY }) is called to validate the env var, then
create lingoDotDev only after the check passes.
| const lingoDotDev = new LingoDotDevEngine({ | ||
| apiKey: process.env.LINGODOTDEV_API_KEY, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
LingoDotDevEngine apiKey requirement undefined behavior
💡 Result:
LingoDotDevEngine requires an apiKey in its constructor config (it’s documented as “Required” / “The SDK requires an API key”). If you pass apiKey: undefined (or omit it), that’s not a supported/defined configuration—the SDK will still attempt to call the Lingo.dev Engine, but requests will fail authentication because there’s no valid key to send. Use a real key (commonly via process.env.LINGODOTDEV_API_KEY) and consider adding your own upfront validation to throw a clear error when it’s missing. [1], [2]
Sources:
[1] https://docs.lingo.dev/setup/sdk
[2] https://lingo.dev/en/sdk/javascript
🏁 Script executed:
find . -type f -name "translate.ts" | head -20Repository: lingodotdev/lingo.dev
Length of output: 122
🏁 Script executed:
cat -n community/auto-localized-notes/app/actions/translate.tsRepository: lingodotdev/lingo.dev
Length of output: 1063
Fail fast if LINGODOTDEV_API_KEY is missing.
The LingoDotDevEngine requires a valid API key (documented as required by Lingo.dev SDK). Passing undefined is not a supported configuration—the SDK will initialize but requests will fail at runtime with authentication errors, making misconfiguration hard to diagnose. Add an explicit guard with a clear error before SDK initialization.
✅ Suggested change
-const lingoDotDev = new LingoDotDevEngine({
- apiKey: process.env.LINGODOTDEV_API_KEY,
-});
+const apiKey = process.env.LINGODOTDEV_API_KEY;
+if (!apiKey) {
+ throw new Error("Missing LINGODOTDEV_API_KEY");
+}
+const lingoDotDev = new LingoDotDevEngine({
+ apiKey,
+});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const lingoDotDev = new LingoDotDevEngine({ | |
| apiKey: process.env.LINGODOTDEV_API_KEY, | |
| }); | |
| const apiKey = process.env.LINGODOTDEV_API_KEY; | |
| if (!apiKey) { | |
| throw new Error("Missing LINGODOTDEV_API_KEY"); | |
| } | |
| const lingoDotDev = new LingoDotDevEngine({ | |
| apiKey, | |
| }); |
🤖 Prompt for AI Agents
In `@community/auto-localized-notes/app/actions/translate.ts` around lines 5 - 7,
Check for process.env.LINGODOTDEV_API_KEY and throw a clear error before
initializing LingoDotDevEngine to fail fast; if the env var is missing,
log/throw a descriptive message like "Missing LINGODOTDEV_API_KEY" and abort
initialization so you don't create lingoDotDev with undefined. Update the
initialization site where new LingoDotDevEngine({ apiKey:
process.env.LINGODOTDEV_API_KEY }) is called to validate the env var, then
create lingoDotDev only after the check passes.
| export async function translateText( | ||
| text: string, | ||
| fromLang: string, | ||
| toLang: string, | ||
| ) { | ||
| try { | ||
| const result = await lingoDotDev.localizeText(text, { | ||
| sourceLocale: fromLang, | ||
| targetLocale: toLang, | ||
| }); | ||
|
|
||
| return result; | ||
| } catch (error) { | ||
| console.error(error); | ||
| return "error translating the text"; | ||
| } | ||
| } | ||
|
|
||
| export async function recognizeText(text: string) { | ||
| try { | ||
| const detectedLang = await lingoDotDev.recognizeLocale(text); | ||
|
|
||
| return detectedLang; | ||
| } catch (error) { | ||
| console.error(error); | ||
| return "error detecting the language"; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid returning sentinel error strings.
Returning "error …" makes failures indistinguishable from valid translations/locales. Prefer null (or a structured result) so callers can handle errors explicitly.
✅ Suggested change
-export async function translateText(
+export async function translateText(
text: string,
fromLang: string,
toLang: string,
-) {
+): Promise<string | null> {
try {
const result = await lingoDotDev.localizeText(text, {
sourceLocale: fromLang,
targetLocale: toLang,
});
return result;
} catch (error) {
console.error(error);
- return "error translating the text";
+ return null;
}
}
-export async function recognizeText(text: string) {
+export async function recognizeText(text: string): Promise<string | null> {
try {
const detectedLang = await lingoDotDev.recognizeLocale(text);
return detectedLang;
} catch (error) {
console.error(error);
- return "error detecting the language";
+ return null;
}
}🤖 Prompt for AI Agents
In `@community/auto-localized-notes/app/actions/translate.ts` around lines 9 - 35,
Both translateText and recognizeText currently return sentinel error strings
("error translating the text"/"error detecting the language") which can collide
with valid outputs; change their error handling to return null (or a structured
error object) instead of strings and preserve logging. Specifically, in
translateText and recognizeText catch blocks (functions named translateText and
recognizeText) replace the string returns with return null (or an Error-style
result) and keep console.error(error) so callers can detect failures explicitly
and handle null results appropriately.
|
Hey @IRjSI! Just checking in - are you still working on this PR? We noticed there are some comments that may need addressing. If you need more time, no problem! Just let us know. If we don't hear back within a week, we'll close this to keep the repo tidy, but you can always reopen when ready. |
Summary
This PR adds a community demo showcasing the usage of the lingo.dev SDK with a minimal Next.js application.
The app demonstrates:
Checklist
mainSummary by CodeRabbit
New Features
Documentation
Style
Chores
✏️ Tip: You can customize this high-level summary in your review settings.