Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fine-jeans-beam.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Maulik176 there's no need for a patch (it will bump the package version/trigger an NPM release).

Can you please update it to an empty changeset.

Just remove this file and run:

npx changeset --empty

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"globalonboard": patch
---

Harden onboarding pack export and task editing by escaping user content, converting edited template tasks to custom, and tightening UI defaults.
160 changes: 160 additions & 0 deletions community/global-onboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# GlobalOnboard · LingoHack25 ✨


**One onboarding checklist. Any language. Fully Configurable**
HR writes once in English, and GlobalOnboard turns it into a polished, localized employee experience by combining **Lingo CLI**, **Lingo JavaScript SDK**, and **Lingo CI**.


## 🧠 The MAIN Pillars of GlobalOnboard

- **Real personas:** HR Workspace (authoring) + Employee Experience (preview) wired together in real time.
- **Full Lingo toolchain:** Static JSON via CLI, runtime personalization via SDK, and CI automation so translations stay fresh.
- **Enterprise-ready touches:** Translation QA mode, localization health warnings, onboarding pack export, and translation spinners that prove we’re production aware.

### 🏅 Lingo Product Scorecard

| Lingo product | How GlobalOnboard uses it | Why it matters |
| --- | --- | --- |
| **Lingo CLI** | Generates `data/ui.{locale}.json` and `data/onboarding_template.{locale}.json` from English sources via `npx lingo.dev@latest run`. | Demonstrates the official static localization workflow. |
| **Lingo JavaScript SDK** | Translates the welcome note and every custom task at runtime with caching, spinners, and graceful fallbacks. | Shows dynamic personalization for each employee preview. |
| **Lingo CI** | `.github/workflows/i18n.yml` runs `npx lingo.dev@latest ci --pull-request` whenever English JSON or `i18n.json` changes. | Proves translation automation and GitHub integration end-to-end. |

---

## 🔑 Feature Highlights

| Area | What it unlocks | Lingo capability |
| --- | --- | --- |
| HR Workspace | Edit company, role, welcome note, and a fully dynamic checklist (add/delete/modify tasks). | Authoring surface for English source |
| Employee Experience | Switch between `en`, `es`, `fr`, `hi` previews with live updates + translation loading overlay. | CLI JSON + SDK runtime translations |
| Preview Modes | `Employee view` or `Translation QA` (side-by-side EN vs target locale) with Machine → Edited → Approved overrides. | Human-in-the-loop QA |
| Localization Health | Warns when translated copy is >1.5× English length, per task + summary. | QA signal |
| Onboarding Pack Export | One click generates a `.doc` bundle for the current locale (company, role, tasks, welcome note). | HR enablement |
| Lingo CI Workflow | GitHub Action auto-runs `lingo.dev ci` whenever English JSON changes. | Translation automation |

---

## 🧩 Architecture At-a-Glance

```text
HR inputs ──▶ English JSON templates ──▶ Lingo CLI generates data/ui.{locale}.json
│ │
│ └─▶ Lingo CI keeps translations up to date
├─▶ React state + localStorage overrides
└─▶ Lingo JS SDK
├─ Welcome note runtime translation
└─ Custom task translations (per locale) + caching
```

---

## 🧪 Getting Started (Local Dev)

```bash
git clone https://github.com/lingodotdev/lingo.dev.git
cd lingo.dev/community/global-onboard
npm install

# Provide your API key so CLI + SDK can translate
export LINGO_DOT_DEV_API_KEY="your-key"
# Optional alias used by some shells/CLIs
export LINGODOTDEV_API_KEY="$LINGO_DOT_DEV_API_KEY"

npm run dev
```

Visit **<http://localhost:3000>** — left panel is HR Workspace, right panel is the localized Employee preview.

---

## 🌐 Localization Workflow Cheat Sheet

### 1. Static JSON (Lingo CLI)
- Source files: `data/ui.en.json`, `data/onboarding_template.en.json`
- Configure targets in `i18n.json`
- Generate translations:
```bash
export LINGO_DOT_DEV_API_KEY="your-key"
npx lingo.dev@latest run
```
- CI automation: `.github/workflows/i18n.yml` runs `npx lingo.dev@latest ci --pull-request` on every push to `main` touching English JSON or `i18n.json`.

### 2. Runtime Personalization (Lingo JS SDK)
- Welcome note + any **custom tasks** run through `lib/lingo-client.ts`.
- We cache translations per locale, show a loading spinner overlay, and gracefully fall back to English if the SDK errors.

### 3. Translation QA Mode
- Side-by-side English vs target locale.
- Inline editing with Machine → Edited → Approved chips.
- Reset/Unlock controls to manage overrides.
- Length-based warnings + summary so HR spots risky strings fast.
- Overrides feed every other view (single preview + export).

---

## 📦 Onboarding Pack Export

1. Choose a locale via the Employee panel dropdown.
2. Ensure QA overrides are final (Approved if needed).
3. Click **Download Onboarding Pack** → generates `onboarding-pack-<locale>.doc` with:
- Locale code
- Localized company + role
- Welcome note (SDK translation if non-English)
- Full task list using effective text (overrides or machine)

Perfect for HRIS uploads, emails, or sharing with managers.

---

## 🛠 Tech Stack

- **Next.js 16** (App Router, TypeScript)
- **Tailwind CSS 4** (custom gradient + glassmorphism theme)
- **Lingo.dev CLI, JS SDK, CI**
- **next-themes** + custom design tokens for dark-first UI
- **GitHub Actions** for automated localization runs

---

## 📁 Project Structure

```text
app/
layout.tsx # Root metadata + ThemeProvider
page.tsx # HR + Employee panels, QA, overrides, spinner
globals.css # Tailwind layers + design tokens
components/
mode-toggle.tsx # Shadcn-style theme toggle (hidden by default)
data/
ui.*.json # Static UI translations (CLI managed)
onboarding_template.*.json
lib/
i18n.ts # Typed loaders for JSON bundles
lingo-client.ts # SDK setup + runtime translation helpers
.github/workflows/
i18n.yml # CI job running `lingo.dev ci`
i18n.json # Bucket + locale configuration
```

---

## 🧾 Useful Scripts

- `npm run dev` – Next.js dev server
- `npm run build` – Production build
- `npm run lint` – ESLint via `eslint-config-next`

---

## ✅ Hackathon Compliance & Notes

- All code, UI, and assets created fresh during **LingoHack25**.
- API keys are required only for translation features; none are checked into the repo.
- Want more locales? Add them to `SUPPORTED_LOCALES` + `i18n.json`, re-run the CLI, and you’re done.

---

### 💬 Questions for Judges?
Open an issue or ping me — I'd love to show how GlobalOnboard can become the multilingual onboarding cockpit for any global company.
40 changes: 40 additions & 0 deletions community/global-onboard/app/api/translate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { NextResponse } from "next/server";

import { translateWithLingo } from "@/lib/lingo";
import { SUPPORTED_LOCALES, type Locale } from "@/lib/i18n";

type TranslationPayload = {
text?: string;
targetLocale?: Locale;
};

export async function POST(request: Request) {
let payload: TranslationPayload;

try {
payload = (await request.json()) as TranslationPayload;
} catch (error) {
console.error("Invalid translation payload", error);
return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
}

const { text, targetLocale } = payload;

if (!text || typeof text !== "string") {
return NextResponse.json({ error: "Missing welcome note" }, { status: 400 });
}

if (!targetLocale || !SUPPORTED_LOCALES.includes(targetLocale)) {
return NextResponse.json({ error: "Unsupported locale" }, { status: 400 });
}

try {
const translated = await translateWithLingo(text, targetLocale);
return NextResponse.json({ translated });
} catch (error) {
console.error("Lingo translation failed", error);
const message =
error instanceof Error ? error.message : "Unable to translate welcome note";
return NextResponse.json({ error: message }, { status: 500 });
}
}
Binary file added community/global-onboard/app/favicon.ico
Binary file not shown.
37 changes: 37 additions & 0 deletions community/global-onboard/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@import "tailwindcss";

:root {
--background: linear-gradient(135deg, #e3f2ff, #f9f1ff);
--foreground: #0f172a;
--muted: rgba(255, 255, 255, 0.8);
--muted-foreground: #475569;
--panel-start: #eef2ff;
--panel-end: #fdf2f8;
}

.dark {
--background: linear-gradient(145deg, #05010c, #0f172a 55%, #1f2937);
--foreground: #f8fafc;
--muted: rgba(15, 23, 42, 0.85);
--muted-foreground: #94a3b8;
--panel-start: rgba(15, 23, 42, 0.9);
--panel-end: rgba(79, 70, 229, 0.35);
}

@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--font-sans: "Inter", "Sohne", system-ui, -apple-system, blinkmacsystemfont,
"Segoe UI", sans-serif;
--font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
}

body {
background: var(--background);
color: var(--foreground);
font-family: var(--font-sans);
transition: background-color 0.3s ease, color 0.3s ease;
background-attachment: fixed;
}
8 changes: 8 additions & 0 deletions community/global-onboard/app/head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function Head() {
return (
<>
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="shortcut icon" href="/favicon.svg" type="image/svg+xml" />
</>
);
}
29 changes: 29 additions & 0 deletions community/global-onboard/app/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions community/global-onboard/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { Metadata } from "next";
import "./globals.css";
import { ThemeProvider } from "@/components/theme-provider";
import { cn } from "@/lib/utils";

export const metadata: Metadata = {
title: "GlobalOnboard",
description:
"GlobalOnboard lets HR teams create one onboarding checklist and preview it in multiple languages via Lingo.dev.",
icons: {
icon: [
{ url: "/favicon.svg", type: "image/svg+xml" },
{ url: "/favicon.svg", rel: "alternate icon", type: "image/svg+xml" },
],
},
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" className="dark" suppressHydrationWarning>
<body
className={cn(
"min-h-screen bg-background text-foreground antialiased transition-colors",
)}
>
<ThemeProvider
attribute="class"
defaultTheme="dark"
forcedTheme="dark"
enableSystem={false}
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
);
}
Loading