├── public ├── apple-icon.png ├── placeholder.jpg ├── icon-dark-32x32.png ├── icon-light-32x32.png ├── placeholder-logo.png ├── placeholder-user.jpg ├── abstract-technology-network-connection.jpg ├── icon.svg ├── placeholder-logo.svg └── placeholder.svg ├── postcss.config.mjs ├── lib └── utils.ts ├── next.config.mjs ├── components ├── theme-provider.tsx ├── ui │ ├── progress.tsx │ ├── badge.tsx │ ├── avatar.tsx │ ├── tabs.tsx │ ├── button.tsx │ ├── card.tsx │ ├── sheet.tsx │ └── dropdown-menu.tsx ├── footer.tsx ├── header.tsx └── language-provider.tsx ├── components.json ├── tsconfig.json ├── app ├── layout.tsx ├── globals.css ├── capabilities │ └── page.tsx ├── page.tsx ├── resources │ └── page.tsx ├── governance │ └── page.tsx ├── projects │ └── page.tsx └── compliance │ └── page.tsx ├── package.json ├── tailwind.config.ts ├── styles └── globals.css ├── README-zh-hans.md └── README.md /public/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/apple-icon.png -------------------------------------------------------------------------------- /public/placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/placeholder.jpg -------------------------------------------------------------------------------- /public/icon-dark-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/icon-dark-32x32.png -------------------------------------------------------------------------------- /public/icon-light-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/icon-light-32x32.png -------------------------------------------------------------------------------- /public/placeholder-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/placeholder-logo.png -------------------------------------------------------------------------------- /public/placeholder-user.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/placeholder-user.jpg -------------------------------------------------------------------------------- /public/abstract-technology-network-connection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node/v0-ospo/main/public/abstract-technology-network-connection.jpg -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | typescript: { 4 | ignoreBuildErrors: true, 5 | }, 6 | images: { 7 | unoptimized: true, 8 | }, 9 | 10 | eslint: { 11 | ignoreDuringBuilds: true, 12 | }, 13 | output: 'export', 14 | } 15 | 16 | export default nextConfig 17 | -------------------------------------------------------------------------------- /components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import { 5 | ThemeProvider as NextThemesProvider, 6 | type ThemeProviderProps, 7 | } from 'next-themes' 8 | 9 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 10 | return {children} 11 | } 12 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "target": "ES6", 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /components/ui/progress.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as ProgressPrimitive from '@radix-ui/react-progress' 5 | 6 | import { cn } from '@/lib/utils' 7 | 8 | const Progress = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, value, ...props }, ref) => ( 12 | 20 | 24 | 25 | )) 26 | Progress.displayName = ProgressPrimitive.Root.displayName 27 | 28 | export { Progress } 29 | -------------------------------------------------------------------------------- /components/footer.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useLanguage } from "@/components/language-provider" 4 | import { Github } from "lucide-react" 5 | import Link from "next/link" 6 | 7 | export default function Footer() { 8 | const { t } = useLanguage() 9 | 10 | return ( 11 |
12 |
13 |

{t("footer.copyright")}

14 |
15 | 21 | 22 | {t("footer.sourceCode")} 23 | 24 |

{t("footer.contact")}: ospo@example.com

25 |
26 |
27 |
28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { cva, type VariantProps } from 'class-variance-authority' 3 | 4 | import { cn } from '@/lib/utils' 5 | 6 | const badgeVariants = cva( 7 | 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', 8 | { 9 | variants: { 10 | variant: { 11 | default: 12 | 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80', 13 | secondary: 14 | 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', 15 | destructive: 16 | 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80', 17 | outline: 'text-foreground', 18 | }, 19 | }, 20 | defaultVariants: { 21 | variant: 'default', 22 | }, 23 | }, 24 | ) 25 | 26 | export interface BadgeProps 27 | extends React.HTMLAttributes, 28 | VariantProps {} 29 | 30 | function Badge({ className, variant, ...props }: BadgeProps) { 31 | return ( 32 |
33 | ) 34 | } 35 | 36 | export { Badge, badgeVariants } 37 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type React from "react" 2 | import type { Metadata } from "next" 3 | import { Inter } from "next/font/google" 4 | import "./globals.css" 5 | import { ThemeProvider } from "@/components/theme-provider" 6 | import { LanguageProvider } from "@/components/language-provider" 7 | import Header from "@/components/header" 8 | import Footer from "@/components/footer" 9 | 10 | const inter = Inter({ subsets: ["latin"] }) 11 | 12 | export const metadata: Metadata = { 13 | title: "OSPO Portal", 14 | description: "Internal portal for Open Source Program Office", 15 | generator: 'v0.app' 16 | } 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: Readonly<{ 21 | children: React.ReactNode 22 | }>) { 23 | return ( 24 | 25 | 26 | 27 | 28 |
29 |
30 |
{children}
31 |
32 |
33 |
34 |
35 | 36 | 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /public/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /components/ui/avatar.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as AvatarPrimitive from '@radix-ui/react-avatar' 5 | 6 | import { cn } from '@/lib/utils' 7 | 8 | const Avatar = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | )) 21 | Avatar.displayName = AvatarPrimitive.Root.displayName 22 | 23 | const AvatarImage = React.forwardRef< 24 | React.ElementRef, 25 | React.ComponentPropsWithoutRef 26 | >(({ className, ...props }, ref) => ( 27 | 32 | )) 33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName 34 | 35 | const AvatarFallback = React.forwardRef< 36 | React.ElementRef, 37 | React.ComponentPropsWithoutRef 38 | >(({ className, ...props }, ref) => ( 39 | 47 | )) 48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName 49 | 50 | export { Avatar, AvatarImage, AvatarFallback } 51 | -------------------------------------------------------------------------------- /components/ui/tabs.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as TabsPrimitive from '@radix-ui/react-tabs' 5 | 6 | import { cn } from '@/lib/utils' 7 | 8 | const Tabs = TabsPrimitive.Root 9 | 10 | const TabsList = React.forwardRef< 11 | React.ElementRef, 12 | React.ComponentPropsWithoutRef 13 | >(({ className, ...props }, ref) => ( 14 | 22 | )) 23 | TabsList.displayName = TabsPrimitive.List.displayName 24 | 25 | const TabsTrigger = React.forwardRef< 26 | React.ElementRef, 27 | React.ComponentPropsWithoutRef 28 | >(({ className, ...props }, ref) => ( 29 | 37 | )) 38 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName 39 | 40 | const TabsContent = React.forwardRef< 41 | React.ElementRef, 42 | React.ComponentPropsWithoutRef 43 | >(({ className, ...props }, ref) => ( 44 | 52 | )) 53 | TabsContent.displayName = TabsPrimitive.Content.displayName 54 | 55 | export { Tabs, TabsList, TabsTrigger, TabsContent } 56 | -------------------------------------------------------------------------------- /components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { Slot } from '@radix-ui/react-slot' 3 | import { cva, type VariantProps } from 'class-variance-authority' 4 | 5 | import { cn } from '@/lib/utils' 6 | 7 | const buttonVariants = cva( 8 | 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', 9 | { 10 | variants: { 11 | variant: { 12 | default: 'bg-primary text-primary-foreground hover:bg-primary/90', 13 | destructive: 14 | 'bg-destructive text-destructive-foreground hover:bg-destructive/90', 15 | outline: 16 | 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', 17 | secondary: 18 | 'bg-secondary text-secondary-foreground hover:bg-secondary/80', 19 | ghost: 'hover:bg-accent hover:text-accent-foreground', 20 | link: 'text-primary underline-offset-4 hover:underline', 21 | }, 22 | size: { 23 | default: 'h-10 px-4 py-2', 24 | sm: 'h-9 rounded-md px-3', 25 | lg: 'h-11 rounded-md px-8', 26 | icon: 'h-10 w-10', 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: 'default', 31 | size: 'default', 32 | }, 33 | }, 34 | ) 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : 'button' 45 | return ( 46 | 51 | ) 52 | }, 53 | ) 54 | Button.displayName = 'Button' 55 | 56 | export { Button, buttonVariants } 57 | -------------------------------------------------------------------------------- /components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { cn } from '@/lib/utils' 4 | 5 | const Card = React.forwardRef< 6 | HTMLDivElement, 7 | React.HTMLAttributes 8 | >(({ className, ...props }, ref) => ( 9 |
17 | )) 18 | Card.displayName = 'Card' 19 | 20 | const CardHeader = React.forwardRef< 21 | HTMLDivElement, 22 | React.HTMLAttributes 23 | >(({ className, ...props }, ref) => ( 24 |
29 | )) 30 | CardHeader.displayName = 'CardHeader' 31 | 32 | const CardTitle = React.forwardRef< 33 | HTMLDivElement, 34 | React.HTMLAttributes 35 | >(({ className, ...props }, ref) => ( 36 |
44 | )) 45 | CardTitle.displayName = 'CardTitle' 46 | 47 | const CardDescription = React.forwardRef< 48 | HTMLDivElement, 49 | React.HTMLAttributes 50 | >(({ className, ...props }, ref) => ( 51 |
56 | )) 57 | CardDescription.displayName = 'CardDescription' 58 | 59 | const CardContent = React.forwardRef< 60 | HTMLDivElement, 61 | React.HTMLAttributes 62 | >(({ className, ...props }, ref) => ( 63 |
64 | )) 65 | CardContent.displayName = 'CardContent' 66 | 67 | const CardFooter = React.forwardRef< 68 | HTMLDivElement, 69 | React.HTMLAttributes 70 | >(({ className, ...props }, ref) => ( 71 |
76 | )) 77 | CardFooter.displayName = 'CardFooter' 78 | 79 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } 80 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-v0-project", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "next build", 7 | "dev": "next dev", 8 | "lint": "eslint .", 9 | "start": "next start" 10 | }, 11 | "dependencies": { 12 | "@hookform/resolvers": "^3.10.0", 13 | "@radix-ui/react-accordion": "1.2.2", 14 | "@radix-ui/react-alert-dialog": "1.1.4", 15 | "@radix-ui/react-aspect-ratio": "1.1.1", 16 | "@radix-ui/react-avatar": "1.1.2", 17 | "@radix-ui/react-checkbox": "1.1.3", 18 | "@radix-ui/react-collapsible": "1.1.2", 19 | "@radix-ui/react-context-menu": "2.2.4", 20 | "@radix-ui/react-dialog": "1.1.4", 21 | "@radix-ui/react-dropdown-menu": "2.1.4", 22 | "@radix-ui/react-hover-card": "1.1.4", 23 | "@radix-ui/react-label": "2.1.1", 24 | "@radix-ui/react-menubar": "1.1.4", 25 | "@radix-ui/react-navigation-menu": "1.2.3", 26 | "@radix-ui/react-popover": "1.1.4", 27 | "@radix-ui/react-progress": "1.1.1", 28 | "@radix-ui/react-radio-group": "1.2.2", 29 | "@radix-ui/react-scroll-area": "1.2.2", 30 | "@radix-ui/react-select": "2.1.4", 31 | "@radix-ui/react-separator": "1.1.1", 32 | "@radix-ui/react-slider": "1.2.2", 33 | "@radix-ui/react-slot": "1.1.1", 34 | "@radix-ui/react-switch": "1.1.2", 35 | "@radix-ui/react-tabs": "1.1.2", 36 | "@radix-ui/react-toast": "1.2.4", 37 | "@radix-ui/react-toggle": "1.1.1", 38 | "@radix-ui/react-toggle-group": "1.1.1", 39 | "@radix-ui/react-tooltip": "1.1.6", 40 | "@vercel/analytics": "1.3.1", 41 | "autoprefixer": "^10.4.20", 42 | "class-variance-authority": "^0.7.1", 43 | "clsx": "^2.1.1", 44 | "cmdk": "1.0.4", 45 | "date-fns": "4.1.0", 46 | "embla-carousel-react": "8.5.1", 47 | "input-otp": "1.4.1", 48 | "lucide-react": "^0.454.0", 49 | "next": "15.5.9", 50 | "next-themes": "^0.4.6", 51 | "react": "19.2.0", 52 | "react-day-picker": "9.8.0", 53 | "react-dom": "19.2.0", 54 | "react-hook-form": "^7.60.0", 55 | "react-resizable-panels": "^2.1.7", 56 | "recharts": "2.15.4", 57 | "sonner": "^1.7.4", 58 | "tailwind-merge": "^3.3.1", 59 | "tailwindcss-animate": "^1.0.7", 60 | "vaul": "^1.1.2", 61 | "zod": "3.25.76" 62 | }, 63 | "devDependencies": { 64 | "@types/node": "^22", 65 | "@types/react": "^19", 66 | "@types/react-dom": "^19", 67 | "postcss": "^8.5", 68 | "tailwindcss": "^3.4.17", 69 | "typescript": "^5" 70 | } 71 | } -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss" 2 | 3 | const config = { 4 | darkMode: ["class"], 5 | content: [ 6 | "./pages/**/*.{ts,tsx}", 7 | "./components/**/*.{ts,tsx}", 8 | "./app/**/*.{ts,tsx}", 9 | "./src/**/*.{ts,tsx}", 10 | "*.{js,ts,jsx,tsx,mdx}", 11 | ], 12 | prefix: "", 13 | theme: { 14 | container: { 15 | center: true, 16 | padding: "2rem", 17 | screens: { 18 | "2xl": "1400px", 19 | }, 20 | }, 21 | extend: { 22 | colors: { 23 | border: "hsl(var(--border))", 24 | input: "hsl(var(--input))", 25 | ring: "hsl(var(--ring))", 26 | background: "hsl(var(--background))", 27 | foreground: "hsl(var(--foreground))", 28 | primary: { 29 | DEFAULT: "hsl(var(--primary))", 30 | foreground: "hsl(var(--primary-foreground))", 31 | }, 32 | secondary: { 33 | DEFAULT: "hsl(var(--secondary))", 34 | foreground: "hsl(var(--secondary-foreground))", 35 | }, 36 | destructive: { 37 | DEFAULT: "hsl(var(--destructive))", 38 | foreground: "hsl(var(--destructive-foreground))", 39 | }, 40 | muted: { 41 | DEFAULT: "hsl(var(--muted))", 42 | foreground: "hsl(var(--muted-foreground))", 43 | }, 44 | accent: { 45 | DEFAULT: "hsl(var(--accent))", 46 | foreground: "hsl(var(--accent-foreground))", 47 | }, 48 | popover: { 49 | DEFAULT: "hsl(var(--popover))", 50 | foreground: "hsl(var(--popover-foreground))", 51 | }, 52 | card: { 53 | DEFAULT: "hsl(var(--card))", 54 | foreground: "hsl(var(--card-foreground))", 55 | }, 56 | }, 57 | borderRadius: { 58 | lg: "var(--radius)", 59 | md: "calc(var(--radius) - 2px)", 60 | sm: "calc(var(--radius) - 4px)", 61 | }, 62 | keyframes: { 63 | "accordion-down": { 64 | from: { height: "0" }, 65 | to: { height: "var(--radix-accordion-content-height)" }, 66 | }, 67 | "accordion-up": { 68 | from: { height: "var(--radix-accordion-content-height)" }, 69 | to: { height: "0" }, 70 | }, 71 | }, 72 | animation: { 73 | "accordion-down": "accordion-down 0.2s ease-out", 74 | "accordion-up": "accordion-up 0.2s ease-out", 75 | }, 76 | }, 77 | }, 78 | plugins: [require("tailwindcss-animate")], 79 | } satisfies Config 80 | 81 | export default config 82 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer utilities { 6 | .text-balance { 7 | text-wrap: balance; 8 | } 9 | } 10 | 11 | @layer base { 12 | :root { 13 | --font-sans: var(--font-geist-sans); 14 | --font-mono: var(--font-geist-mono); 15 | --background: 0 0% 100%; 16 | --foreground: 0 0% 3.9%; 17 | --card: 0 0% 100%; 18 | --card-foreground: 0 0% 3.9%; 19 | --popover: 0 0% 100%; 20 | --popover-foreground: 0 0% 3.9%; 21 | --primary: 0 0% 9%; 22 | --primary-foreground: 0 0% 98%; 23 | --secondary: 0 0% 96.1%; 24 | --secondary-foreground: 0 0% 9%; 25 | --muted: 0 0% 96.1%; 26 | --muted-foreground: 0 0% 45.1%; 27 | --accent: 0 0% 96.1%; 28 | --accent-foreground: 0 0% 9%; 29 | --destructive: 0 84.2% 60.2%; 30 | --destructive-foreground: 0 0% 98%; 31 | --border: 0 0% 89.8%; 32 | --input: 0 0% 89.8%; 33 | --ring: 0 0% 3.9%; 34 | --chart-1: 12 76% 61%; 35 | --chart-2: 173 58% 39%; 36 | --chart-3: 197 37% 24%; 37 | --chart-4: 43 74% 66%; 38 | --chart-5: 27 87% 67%; 39 | --radius: 0.5rem; 40 | --sidebar-background: 0 0% 98%; 41 | --sidebar-foreground: 240 5.3% 26.1%; 42 | --sidebar-primary: 240 5.9% 10%; 43 | --sidebar-primary-foreground: 0 0% 98%; 44 | --sidebar-accent: 240 4.8% 95.9%; 45 | --sidebar-accent-foreground: 240 5.9% 10%; 46 | --sidebar-border: 220 13% 91%; 47 | --sidebar-ring: 217.2 91.2% 59.8%; 48 | } 49 | .dark { 50 | --background: 0 0% 3.9%; 51 | --foreground: 0 0% 98%; 52 | --card: 0 0% 3.9%; 53 | --card-foreground: 0 0% 98%; 54 | --popover: 0 0% 3.9%; 55 | --popover-foreground: 0 0% 98%; 56 | --primary: 0 0% 98%; 57 | --primary-foreground: 0 0% 9%; 58 | --secondary: 0 0% 14.9%; 59 | --secondary-foreground: 0 0% 98%; 60 | --muted: 0 0% 14.9%; 61 | --muted-foreground: 0 0% 63.9%; 62 | --accent: 0 0% 14.9%; 63 | --accent-foreground: 0 0% 98%; 64 | --destructive: 0 62.8% 30.6%; 65 | --destructive-foreground: 0 0% 98%; 66 | --border: 0 0% 14.9%; 67 | --input: 0 0% 14.9%; 68 | --ring: 0 0% 83.1%; 69 | --chart-1: 220 70% 50%; 70 | --chart-2: 160 60% 45%; 71 | --chart-3: 30 80% 55%; 72 | --chart-4: 280 65% 60%; 73 | --chart-5: 340 75% 55%; 74 | --sidebar-background: 240 5.9% 10%; 75 | --sidebar-foreground: 240 4.8% 95.9%; 76 | --sidebar-primary: 224.3 76.3% 48%; 77 | --sidebar-primary-foreground: 0 0% 100%; 78 | --sidebar-accent: 240 3.7% 15.9%; 79 | --sidebar-accent-foreground: 240 4.8% 95.9%; 80 | --sidebar-border: 240 3.7% 15.9%; 81 | --sidebar-ring: 217.2 91.2% 59.8%; 82 | } 83 | } 84 | 85 | @layer base { 86 | * { 87 | @apply border-border; 88 | } 89 | body { 90 | @apply bg-background text-foreground; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer utilities { 6 | .text-balance { 7 | text-wrap: balance; 8 | } 9 | } 10 | 11 | @layer base { 12 | :root { 13 | --font-sans: var(--font-geist-sans); 14 | --font-mono: var(--font-geist-mono); 15 | --background: 0 0% 100%; 16 | --foreground: 0 0% 3.9%; 17 | --card: 0 0% 100%; 18 | --card-foreground: 0 0% 3.9%; 19 | --popover: 0 0% 100%; 20 | --popover-foreground: 0 0% 3.9%; 21 | --primary: 0 0% 9%; 22 | --primary-foreground: 0 0% 98%; 23 | --secondary: 0 0% 96.1%; 24 | --secondary-foreground: 0 0% 9%; 25 | --muted: 0 0% 96.1%; 26 | --muted-foreground: 0 0% 45.1%; 27 | --accent: 0 0% 96.1%; 28 | --accent-foreground: 0 0% 9%; 29 | --destructive: 0 84.2% 60.2%; 30 | --destructive-foreground: 0 0% 98%; 31 | --border: 0 0% 89.8%; 32 | --input: 0 0% 89.8%; 33 | --ring: 0 0% 3.9%; 34 | --chart-1: 12 76% 61%; 35 | --chart-2: 173 58% 39%; 36 | --chart-3: 197 37% 24%; 37 | --chart-4: 43 74% 66%; 38 | --chart-5: 27 87% 67%; 39 | --radius: 0.5rem; 40 | --sidebar-background: 0 0% 98%; 41 | --sidebar-foreground: 240 5.3% 26.1%; 42 | --sidebar-primary: 240 5.9% 10%; 43 | --sidebar-primary-foreground: 0 0% 98%; 44 | --sidebar-accent: 240 4.8% 95.9%; 45 | --sidebar-accent-foreground: 240 5.9% 10%; 46 | --sidebar-border: 220 13% 91%; 47 | --sidebar-ring: 217.2 91.2% 59.8%; 48 | } 49 | .dark { 50 | --background: 0 0% 3.9%; 51 | --foreground: 0 0% 98%; 52 | --card: 0 0% 3.9%; 53 | --card-foreground: 0 0% 98%; 54 | --popover: 0 0% 3.9%; 55 | --popover-foreground: 0 0% 98%; 56 | --primary: 0 0% 98%; 57 | --primary-foreground: 0 0% 9%; 58 | --secondary: 0 0% 14.9%; 59 | --secondary-foreground: 0 0% 98%; 60 | --muted: 0 0% 14.9%; 61 | --muted-foreground: 0 0% 63.9%; 62 | --accent: 0 0% 14.9%; 63 | --accent-foreground: 0 0% 98%; 64 | --destructive: 0 62.8% 30.6%; 65 | --destructive-foreground: 0 0% 98%; 66 | --border: 0 0% 14.9%; 67 | --input: 0 0% 14.9%; 68 | --ring: 0 0% 83.1%; 69 | --chart-1: 220 70% 50%; 70 | --chart-2: 160 60% 45%; 71 | --chart-3: 30 80% 55%; 72 | --chart-4: 280 65% 60%; 73 | --chart-5: 340 75% 55%; 74 | --sidebar-background: 240 5.9% 10%; 75 | --sidebar-foreground: 240 4.8% 95.9%; 76 | --sidebar-primary: 224.3 76.3% 48%; 77 | --sidebar-primary-foreground: 0 0% 100%; 78 | --sidebar-accent: 240 3.7% 15.9%; 79 | --sidebar-accent-foreground: 240 4.8% 95.9%; 80 | --sidebar-border: 240 3.7% 15.9%; 81 | --sidebar-ring: 217.2 91.2% 59.8%; 82 | } 83 | } 84 | 85 | @layer base { 86 | * { 87 | @apply border-border; 88 | } 89 | body { 90 | @apply bg-background text-foreground; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /public/placeholder-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/placeholder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README-zh-hans.md: -------------------------------------------------------------------------------- 1 | # OSPO 内部网站 2 | 3 | 简体中文 | [English](./README.md) 4 | 5 | *自动同步到您的 [v0.app](https://v0.app) 部署* 6 | 7 | [![Deployed on Vercel](https://img.shields.io/badge/Deployed%20on-Vercel-black?style=for-the-badge&logo=vercel)](https://vercel.com/pecommunity/v0-ospo-internal-website) 8 | [![Built with v0](https://img.shields.io/badge/Built%20with-v0.app-black?style=for-the-badge)](https://v0.app/chat/projects/ZLCXfbp61qN) 9 | 10 | ## 项目简介 11 | 12 | 这是一个开源项目办公室(OSPO - Open Source Program Office)的内部网站。OSPO 是企业或组织内部专门负责开源及其治理相关事项的团队。本网站作为开源管理、合规和协作的中心枢纽。 13 | 14 | ## 功能特性 15 | 16 | ### 🏠 首页 17 | - OSPO 愿景和使命展示 18 | - 主要职责概览 19 | - 团队组成和联系人信息 20 | - 重要的内外部链接 21 | 22 | ### 🎯 能力建设 23 | - 技术能力发展跟踪 24 | - 社区参与度提升计划 25 | - 培训项目和工作坊 26 | - 法律与合规能力 27 | - 指标和测量框架 28 | - 里程碑进度可视化 29 | 30 | ### 📦 项目列表 31 | - **内部开源项目**:组织内部开发和使用的项目 32 | - **参与外部贡献**:对第三方开源项目的贡献 33 | - **对外开源项目**:组织开源并维护的公开项目 34 | - 项目元数据包括 Stars、Forks 和许可证信息 35 | 36 | ### 🛡️ 开源合规 37 | - 许可证合规要求和审查流程 38 | - 合规指标和统计数据 39 | - 知识库(指南和常见问题) 40 | - SCA(软件成分分析)工具集成 41 | - **开源软件供应链**:跨安全性、维护性、社区活跃度、许可证合规和代码质量维度的健康度指标 42 | 43 | ### ⚖️ 治理政策 44 | - 开源政策和标准 45 | - 组织架构和治理委员会 46 | - 运作流程和审批工作流 47 | - 决策框架 48 | 49 | ### 📚 资源中心 50 | - **流程与指南**:标准流程、快速入门指南、最佳实践和模板 51 | - **成功案例**:展示开源采用影响力的真实案例研究 52 | 53 | ### 🌐 国际化 54 | - 完整支持中文和英文 55 | - 通过 UI 控件轻松切换语言 56 | - 持久化语言偏好设置 57 | 58 | ## 技术栈 59 | 60 | - **框架**: Next.js 15.5.9 (App Router) 61 | - **样式**: Tailwind CSS 62 | - **UI 组件**: shadcn/ui 63 | - **图标**: Lucide React 64 | - **语言**: TypeScript 65 | 66 | ## 快速开始 67 | 68 | ### 前置要求 69 | 70 | - Node.js 18.0.0 或更高版本 71 | - npm 或 yarn 72 | 73 | ### 安装步骤 74 | 75 | 1. 克隆仓库: 76 | ```bash 77 | git clone https://github.com/ospocc/v0-ospo.git 78 | cd v0-ospo 79 | ``` 80 | 81 | 2. 安装依赖: 82 | ```bash 83 | npm install 84 | # 或 85 | yarn install 86 | ``` 87 | 88 | 3. 启动开发服务器: 89 | ```bash 90 | npm run dev 91 | # 或 92 | yarn dev 93 | ``` 94 | 95 | 4. 在浏览器中打开 [http://localhost:3000](http://localhost:3000) 96 | 97 | ### 生产构建 98 | 99 | ```bash 100 | npm run build 101 | npm run start 102 | # 或 103 | yarn build 104 | yarn start 105 | ``` 106 | 107 | ## 项目结构 108 | 109 | ``` 110 | v0-ospo/ 111 | ├── app/ # Next.js App Router 页面 112 | │ ├── page.tsx # 首页 113 | │ ├── capabilities/ # 能力建设页面 114 | │ ├── projects/ # 项目列表页面 115 | │ ├── compliance/ # 开源合规页面 116 | │ ├── governance/ # 治理政策页面 117 | │ └── resources/ # 资源中心页面 118 | ├── components/ # 可复用组件 119 | │ ├── header.tsx # 导航页头 120 | │ ├── footer.tsx # 站点页脚 121 | │ └── language-provider.tsx # 国际化提供者 122 | ├── public/ # 静态资源 123 | └── ... 124 | ``` 125 | 126 | ## 配置说明 127 | 128 | ### 默认语言 129 | 130 | 要更改默认语言,请编辑 `components/language-provider.tsx`: 131 | 132 | ```typescript 133 | const [language, setLanguage] = useState("zh") // 改为 "en" 使用英文 134 | ``` 135 | 136 | ### 主题颜色 137 | 138 | 在 `tailwind.config.ts` 和 `app/globals.css` 中自定义主题颜色。 139 | 140 | ## 部署 141 | 142 | 您的项目已部署至: 143 | 144 | **[https://v0ospo.pages.dev](https://v0ospo.pages.dev)** 145 | 146 | ### 部署到 Vercel 147 | 148 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/ospocc/v0-ospo) 149 | 150 | ## 贡献 151 | 152 | 本项目会自动与 [v0.app](https://v0.app) 双向同步。要贡献代码: 153 | 154 | 1. 在此处继续构建您的应用:**[https://v0.app/chat/projects/ZLCXfbp61qN](https://v0.app/chat/projects/ZLCXfbp61qN)** 155 | 2. 更改会自动推送到本仓库 156 | 3. Vercel 会自动部署最新版本 157 | 158 | ## 许可证 159 | 160 | 本项目采用 MIT 许可证。 161 | 162 | ## 支持 163 | 164 | 如有问题或需要支持,请联系 OSPO 团队或在本仓库中提交 issue。 165 | 166 | OSPO 中文社区交流:[https://OSPO.CC](https://ospo.cc) 167 | -------------------------------------------------------------------------------- /components/header.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import Link from "next/link" 4 | import { usePathname } from "next/navigation" 5 | import { Button } from "@/components/ui/button" 6 | import { MoonIcon, SunIcon, GlobeIcon, Menu } from "lucide-react" 7 | import { useTheme } from "next-themes" 8 | import { useLanguage } from "@/components/language-provider" 9 | import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" 10 | import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet" 11 | 12 | export default function Header() { 13 | const { setTheme } = useTheme() 14 | const { language, setLanguage, t } = useLanguage() 15 | const pathname = usePathname() 16 | 17 | const navigation = [ 18 | { name: t("nav.home"), href: "/" }, 19 | { name: t("nav.capabilities"), href: "/capabilities" }, 20 | { name: t("nav.projects"), href: "/projects" }, 21 | { name: t("nav.governance"), href: "/governance" }, 22 | { name: t("nav.compliance"), href: "/compliance" }, 23 | { name: t("nav.resources"), href: "/resources" }, 24 | ] 25 | 26 | return ( 27 |
28 |
29 |
30 | 31 | OSPO 32 | 33 | 46 |
47 |
48 | {/* Mobile menu */} 49 | 50 | 51 | 55 | 56 | 57 | 70 | 71 | 72 | 73 | 74 | 75 | 79 | 80 | 81 | setLanguage("en")}>English {language === "en" && "✓"} 82 | setLanguage("zh")}>中文 {language === "zh" && "✓"} 83 | 84 | 85 | 86 | 87 | 92 | 93 | 94 | setTheme("light")}>Light 95 | setTheme("dark")}>Dark 96 | setTheme("system")}>System 97 | 98 | 99 |
100 |
101 |
102 | ) 103 | } 104 | -------------------------------------------------------------------------------- /components/ui/sheet.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as SheetPrimitive from '@radix-ui/react-dialog' 5 | import { cva, type VariantProps } from 'class-variance-authority' 6 | import { X } from 'lucide-react' 7 | 8 | import { cn } from '@/lib/utils' 9 | 10 | const Sheet = SheetPrimitive.Root 11 | 12 | const SheetTrigger = SheetPrimitive.Trigger 13 | 14 | const SheetClose = SheetPrimitive.Close 15 | 16 | const SheetPortal = SheetPrimitive.Portal 17 | 18 | const SheetOverlay = React.forwardRef< 19 | React.ElementRef, 20 | React.ComponentPropsWithoutRef 21 | >(({ className, ...props }, ref) => ( 22 | 30 | )) 31 | SheetOverlay.displayName = SheetPrimitive.Overlay.displayName 32 | 33 | const sheetVariants = cva( 34 | 'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500', 35 | { 36 | variants: { 37 | side: { 38 | top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top', 39 | bottom: 40 | 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom', 41 | left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm', 42 | right: 43 | 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm', 44 | }, 45 | }, 46 | defaultVariants: { 47 | side: 'right', 48 | }, 49 | }, 50 | ) 51 | 52 | interface SheetContentProps 53 | extends React.ComponentPropsWithoutRef, 54 | VariantProps {} 55 | 56 | const SheetContent = React.forwardRef< 57 | React.ElementRef, 58 | SheetContentProps 59 | >(({ side = 'right', className, children, ...props }, ref) => ( 60 | 61 | 62 | 67 | {children} 68 | 69 | 70 | Close 71 | 72 | 73 | 74 | )) 75 | SheetContent.displayName = SheetPrimitive.Content.displayName 76 | 77 | const SheetHeader = ({ 78 | className, 79 | ...props 80 | }: React.HTMLAttributes) => ( 81 |
88 | ) 89 | SheetHeader.displayName = 'SheetHeader' 90 | 91 | const SheetFooter = ({ 92 | className, 93 | ...props 94 | }: React.HTMLAttributes) => ( 95 |
102 | ) 103 | SheetFooter.displayName = 'SheetFooter' 104 | 105 | const SheetTitle = React.forwardRef< 106 | React.ElementRef, 107 | React.ComponentPropsWithoutRef 108 | >(({ className, ...props }, ref) => ( 109 | 114 | )) 115 | SheetTitle.displayName = SheetPrimitive.Title.displayName 116 | 117 | const SheetDescription = React.forwardRef< 118 | React.ElementRef, 119 | React.ComponentPropsWithoutRef 120 | >(({ className, ...props }, ref) => ( 121 | 126 | )) 127 | SheetDescription.displayName = SheetPrimitive.Description.displayName 128 | 129 | export { 130 | Sheet, 131 | SheetPortal, 132 | SheetOverlay, 133 | SheetTrigger, 134 | SheetClose, 135 | SheetContent, 136 | SheetHeader, 137 | SheetFooter, 138 | SheetTitle, 139 | SheetDescription, 140 | } 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSPO Internal Website 2 | 3 | [中文版](./README-zh-hans.md) | English 4 | 5 | *Automatically synced with your [v0.app](https://v0.app) deployments* 6 | 7 | [![Deployed on Vercel](https://img.shields.io/badge/Deployed%20on-Vercel-black?style=for-the-badge&logo=vercel)](https://vercel.com/pecommunity/v0-ospo-internal-website) 8 | [![Built with v0](https://img.shields.io/badge/Built%20with-v0.app-black?style=for-the-badge)](https://v0.app/chat/projects/ZLCXfbp61qN) 9 | 10 | ## Overview 11 | 12 | This is an internal website for the Open Source Program Office (OSPO) - a dedicated team within an organization responsible for open source related initiatives and governance. The website serves as a central hub for open source management, compliance, and collaboration. 13 | 14 | ## Features 15 | 16 | ### 🏠 Home 17 | - OSPO vision and mission statement 18 | - Key responsibilities overview 19 | - Team composition and contact information 20 | - Important internal and external links 21 | 22 | ### 🎯 Capabilities Building 23 | - Technology capability development tracking 24 | - Community engagement initiatives 25 | - Training programs and workshops 26 | - Legal and compliance capabilities 27 | - Metrics and measurement frameworks 28 | - Progress tracking with milestone visualization 29 | 30 | ### 📦 Projects 31 | - **Internal Open Source Projects**: Projects developed and used within the organization 32 | - **External Contributions**: Contributions to third-party open source projects 33 | - **Public Open Source Projects**: Projects open-sourced and maintained by the organization 34 | - Project metadata including stars, forks, and license information 35 | 36 | ### 🛡️ Compliance 37 | - License compliance requirements and review processes 38 | - Compliance metrics and statistics 39 | - Knowledge base with guides and FAQs 40 | - SCA (Software Composition Analysis) tools integration 41 | - **Open Source Supply Chain**: Health metrics across security, maintenance, community, license compliance, and code quality dimensions 42 | 43 | ### ⚖️ Governance 44 | - Open source policies and standards 45 | - Organizational structure and governance committees 46 | - Operating procedures and approval workflows 47 | - Decision-making frameworks 48 | 49 | ### 📚 Resources 50 | - **Process & Guidelines**: Standard processes, quick start guides, best practices, and templates 51 | - **Success Stories**: Real-world case studies showcasing open source adoption impact 52 | 53 | ### 🌐 Internationalization 54 | - Full support for Chinese and English languages 55 | - Easy language switching via UI controls 56 | - Persistent language preference 57 | 58 | ## Tech Stack 59 | 60 | - **Framework**: Next.js 15.5.9 (App Router) 61 | - **Styling**: Tailwind CSS 62 | - **UI Components**: shadcn/ui 63 | - **Icons**: Lucide React 64 | - **Language**: TypeScript 65 | 66 | ## Getting Started 67 | 68 | ### Prerequisites 69 | 70 | - Node.js 18.0.0 or higher 71 | - npm or yarn 72 | 73 | ### Installation 74 | 75 | 1. Clone the repository: 76 | ```bash 77 | git clone https://github.com/ospocc/v0-ospo.git 78 | cd v0-ospo 79 | ``` 80 | 81 | 2. Install dependencies: 82 | ```bash 83 | npm install 84 | # or 85 | yarn install 86 | ``` 87 | 88 | 3. Run the development server: 89 | ```bash 90 | npm run dev 91 | # or 92 | yarn dev 93 | ``` 94 | 95 | 4. Open [http://localhost:3000](http://localhost:3000) in your browser 96 | 97 | ### Build for Production 98 | 99 | ```bash 100 | npm run build 101 | npm run start 102 | # or 103 | yarn build 104 | yarn start 105 | ``` 106 | 107 | ## Project Structure 108 | 109 | ``` 110 | v0-ospo/ 111 | ├── app/ # Next.js App Router pages 112 | │ ├── page.tsx # Home page 113 | │ ├── capabilities/ # Capabilities building page 114 | │ ├── projects/ # Projects list page 115 | │ ├── compliance/ # Compliance page 116 | │ ├── governance/ # Governance policies page 117 | │ └── resources/ # Resources center page 118 | ├── components/ # Reusable components 119 | │ ├── header.tsx # Navigation header 120 | │ ├── footer.tsx # Site footer 121 | │ └── language-provider.tsx # i18n provider 122 | ├── public/ # Static assets 123 | └── ... 124 | ``` 125 | 126 | ## Configuration 127 | 128 | ### Default Language 129 | 130 | To change the default language, edit `components/language-provider.tsx`: 131 | 132 | ```typescript 133 | const [language, setLanguage] = useState("en") // Change to "zh" for Chinese 134 | ``` 135 | 136 | ### Theme Colors 137 | 138 | Customize theme colors in `tailwind.config.ts` and `app/globals.css`. 139 | 140 | ## Deployment 141 | 142 | Your project is live at: 143 | 144 | **[https://vercel.com/pecommunity/v0-ospo-internal-website](https://vercel.com/pecommunity/v0-ospo-internal-website)** 145 | 146 | ### Deploy to Vercel 147 | 148 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/ospocc/v0-ospo) 149 | 150 | ## Contributing 151 | 152 | This project is automatically synced with [v0.app](https://v0.app). To contribute: 153 | 154 | 1. Continue building your app on: **[https://v0.app/chat/projects/ZLCXfbp61qN](https://v0.app/chat/projects/ZLCXfbp61qN)** 155 | 2. Changes are automatically pushed to this repository 156 | 3. Vercel deploys the latest version automatically 157 | 158 | ## License 159 | 160 | This project is licensed under the MIT License. 161 | 162 | ## Support 163 | 164 | For questions or support, please contact the OSPO team or open an issue in this repository. 165 | 166 | Visit OSPO.CC community [https://OSPO.CC](https://ospo.cc) 167 | -------------------------------------------------------------------------------- /app/capabilities/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useLanguage } from "@/components/language-provider" 4 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" 5 | import { Progress } from "@/components/ui/progress" 6 | import { Hash } from "lucide-react" 7 | 8 | export default function CapabilitiesPage() { 9 | const { t } = useLanguage() 10 | 11 | const capabilities = [ 12 | { 13 | id: "governance", 14 | title: t("capabilities.governance.title"), 15 | description: t("capabilities.governance.desc"), 16 | progress: 85, 17 | milestones: [ 18 | { title: t("capabilities.milestone.policyFramework"), status: "completed", date: "2024-01" }, 19 | { title: t("capabilities.milestone.governanceCommittee"), status: "completed", date: "2024-02" }, 20 | { title: t("capabilities.milestone.complianceTooling"), status: "in-progress", date: "2024-05" }, 21 | { title: t("capabilities.milestone.auditProcess"), status: "planned", date: "2024-08" }, 22 | ], 23 | }, 24 | { 25 | id: "education", 26 | title: t("capabilities.education.title"), 27 | description: t("capabilities.education.desc"), 28 | progress: 60, 29 | milestones: [ 30 | { title: t("capabilities.milestone.basicTraining"), status: "completed", date: "2024-02" }, 31 | { title: t("capabilities.milestone.advancedWorkshops"), status: "in-progress", date: "2024-04" }, 32 | { title: t("capabilities.milestone.certificationProgram"), status: "planned", date: "2024-07" }, 33 | { title: t("capabilities.milestone.mentorshipProgram"), status: "planned", date: "2024-10" }, 34 | ], 35 | }, 36 | { 37 | id: "contribution", 38 | title: t("capabilities.contribution.title"), 39 | description: t("capabilities.contribution.desc"), 40 | progress: 40, 41 | milestones: [ 42 | { title: t("capabilities.milestone.contributionGuidelines"), status: "completed", date: "2024-03" }, 43 | { title: t("capabilities.milestone.projectSelectionFramework"), status: "in-progress", date: "2024-06" }, 44 | { title: t("capabilities.milestone.contributionMetrics"), status: "planned", date: "2024-09" }, 45 | { title: t("capabilities.milestone.communityLeadership"), status: "planned", date: "2025-01" }, 46 | ], 47 | }, 48 | { 49 | id: "innersource", 50 | title: t("capabilities.innersource.title"), 51 | description: t("capabilities.innersource.desc"), 52 | progress: 30, 53 | milestones: [ 54 | { title: t("capabilities.milestone.innersourceGuidelines"), status: "completed", date: "2024-03" }, 55 | { title: t("capabilities.milestone.pilotProjects"), status: "in-progress", date: "2024-05" }, 56 | { title: t("capabilities.milestone.toolingInfrastructure"), status: "planned", date: "2024-08" }, 57 | { title: t("capabilities.milestone.organizationRollout"), status: "planned", date: "2024-12" }, 58 | ], 59 | }, 60 | { 61 | id: "security", 62 | title: t("capabilities.security.title"), 63 | description: t("capabilities.security.desc"), 64 | progress: 70, 65 | milestones: [ 66 | { title: t("capabilities.milestone.securityScanning"), status: "completed", date: "2024-01" }, 67 | { title: t("capabilities.milestone.licenseCompliance"), status: "completed", date: "2024-02" }, 68 | { title: t("capabilities.milestone.vulnerabilityManagement"), status: "in-progress", date: "2024-04" }, 69 | { title: t("capabilities.milestone.automatedCompliance"), status: "planned", date: "2024-07" }, 70 | ], 71 | }, 72 | ] 73 | 74 | return ( 75 |
76 |
77 |

{t("capabilities.title")}

78 |

{t("capabilities.subtitle")}

79 |
80 | 81 | 82 | 83 |
84 | 85 | {t("capabilities.nav.title")} 86 |
87 |
88 | {capabilities.map((capability) => ( 89 | 94 | {capability.title} 95 | 96 | ))} 97 |
98 |
99 |
100 | {/* End navigation */} 101 | 102 |
103 | {capabilities.map((capability) => ( 104 | 105 | 106 |
107 |
108 | {capability.title} 109 | {capability.description} 110 |
111 |
112 |
{t("capabilities.progress")}
113 |
{capability.progress}%
114 |
115 |
116 |
117 | 118 | 119 | 120 |
121 |

{t("capabilities.milestones")}

122 |
123 |
124 |
125 | {capability.milestones.map((milestone, index) => ( 126 |
127 |
136 |
137 |
{milestone.title}
138 | {milestone.date} 139 |
140 |

141 | {milestone.status === "completed" 142 | ? t("capabilities.status.completed") 143 | : milestone.status === "in-progress" 144 | ? t("capabilities.status.inProgress") 145 | : t("capabilities.status.planned")} 146 |

147 |
148 | ))} 149 |
150 |
151 |
152 |
153 |
154 | ))} 155 |
156 |
157 | ) 158 | } 159 | -------------------------------------------------------------------------------- /components/ui/dropdown-menu.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu' 5 | import { Check, ChevronRight, Circle } from 'lucide-react' 6 | 7 | import { cn } from '@/lib/utils' 8 | 9 | const DropdownMenu = DropdownMenuPrimitive.Root 10 | 11 | const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger 12 | 13 | const DropdownMenuGroup = DropdownMenuPrimitive.Group 14 | 15 | const DropdownMenuPortal = DropdownMenuPrimitive.Portal 16 | 17 | const DropdownMenuSub = DropdownMenuPrimitive.Sub 18 | 19 | const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup 20 | 21 | const DropdownMenuSubTrigger = React.forwardRef< 22 | React.ElementRef, 23 | React.ComponentPropsWithoutRef & { 24 | inset?: boolean 25 | } 26 | >(({ className, inset, children, ...props }, ref) => ( 27 | 36 | {children} 37 | 38 | 39 | )) 40 | DropdownMenuSubTrigger.displayName = 41 | DropdownMenuPrimitive.SubTrigger.displayName 42 | 43 | const DropdownMenuSubContent = React.forwardRef< 44 | React.ElementRef, 45 | React.ComponentPropsWithoutRef 46 | >(({ className, ...props }, ref) => ( 47 | 55 | )) 56 | DropdownMenuSubContent.displayName = 57 | DropdownMenuPrimitive.SubContent.displayName 58 | 59 | const DropdownMenuContent = React.forwardRef< 60 | React.ElementRef, 61 | React.ComponentPropsWithoutRef 62 | >(({ className, sideOffset = 4, ...props }, ref) => ( 63 | 64 | 73 | 74 | )) 75 | DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName 76 | 77 | const DropdownMenuItem = React.forwardRef< 78 | React.ElementRef, 79 | React.ComponentPropsWithoutRef & { 80 | inset?: boolean 81 | } 82 | >(({ className, inset, ...props }, ref) => ( 83 | 92 | )) 93 | DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName 94 | 95 | const DropdownMenuCheckboxItem = React.forwardRef< 96 | React.ElementRef, 97 | React.ComponentPropsWithoutRef 98 | >(({ className, children, checked, ...props }, ref) => ( 99 | 108 | 109 | 110 | 111 | 112 | 113 | {children} 114 | 115 | )) 116 | DropdownMenuCheckboxItem.displayName = 117 | DropdownMenuPrimitive.CheckboxItem.displayName 118 | 119 | const DropdownMenuRadioItem = React.forwardRef< 120 | React.ElementRef, 121 | React.ComponentPropsWithoutRef 122 | >(({ className, children, ...props }, ref) => ( 123 | 131 | 132 | 133 | 134 | 135 | 136 | {children} 137 | 138 | )) 139 | DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName 140 | 141 | const DropdownMenuLabel = React.forwardRef< 142 | React.ElementRef, 143 | React.ComponentPropsWithoutRef & { 144 | inset?: boolean 145 | } 146 | >(({ className, inset, ...props }, ref) => ( 147 | 156 | )) 157 | DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName 158 | 159 | const DropdownMenuSeparator = React.forwardRef< 160 | React.ElementRef, 161 | React.ComponentPropsWithoutRef 162 | >(({ className, ...props }, ref) => ( 163 | 168 | )) 169 | DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName 170 | 171 | const DropdownMenuShortcut = ({ 172 | className, 173 | ...props 174 | }: React.HTMLAttributes) => { 175 | return ( 176 | 180 | ) 181 | } 182 | DropdownMenuShortcut.displayName = 'DropdownMenuShortcut' 183 | 184 | export { 185 | DropdownMenu, 186 | DropdownMenuTrigger, 187 | DropdownMenuContent, 188 | DropdownMenuItem, 189 | DropdownMenuCheckboxItem, 190 | DropdownMenuRadioItem, 191 | DropdownMenuLabel, 192 | DropdownMenuSeparator, 193 | DropdownMenuShortcut, 194 | DropdownMenuGroup, 195 | DropdownMenuPortal, 196 | DropdownMenuSub, 197 | DropdownMenuSubContent, 198 | DropdownMenuSubTrigger, 199 | DropdownMenuRadioGroup, 200 | } 201 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useLanguage } from "@/components/language-provider" 4 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" 5 | import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" 6 | import { ExternalLink, Target, Eye, CheckCircle } from "lucide-react" 7 | import Link from "next/link" 8 | 9 | export default function Home() { 10 | const { t } = useLanguage() 11 | 12 | const teamMembers = [ 13 | { 14 | name: "Alex Chen", 15 | role: t("home.team.director"), 16 | email: "alex.chen@example.com", 17 | avatar: "/placeholder.svg?height=80&width=80", 18 | }, 19 | { 20 | name: "Sarah Johnson", 21 | role: t("home.team.manager"), 22 | email: "sarah.johnson@example.com", 23 | avatar: "/placeholder.svg?height=80&width=80", 24 | }, 25 | { 26 | name: "Michael Zhang", 27 | role: t("home.team.engineer"), 28 | email: "michael.zhang@example.com", 29 | avatar: "/placeholder.svg?height=80&width=80", 30 | }, 31 | { 32 | name: "Emma Liu", 33 | role: t("home.team.legal"), 34 | email: "emma.liu@example.com", 35 | avatar: "/placeholder.svg?height=80&width=80", 36 | }, 37 | { 38 | name: "David Wang", 39 | role: t("home.team.developer"), 40 | email: "david.wang@example.com", 41 | avatar: "/placeholder.svg?height=80&width=80", 42 | }, 43 | ] 44 | 45 | const internalLinks = [ 46 | { name: "Developer Portal", url: "#" }, 47 | { name: "Legal Guidelines", url: "#" }, 48 | { name: "Contribution Workflow", url: "#" }, 49 | { name: "Training Resources", url: "#" }, 50 | ] 51 | 52 | const externalLinks = [ 53 | { name: "GitHub Organization", url: "https://github.com" }, 54 | { name: "Open Source Initiative", url: "https://opensource.org" }, 55 | { name: "FOSS Compliance", url: "https://www.linuxfoundation.org" }, 56 | { name: "InnerSource Commons", url: "https://innersourcecommons.org" }, 57 | ] 58 | 59 | return ( 60 |
61 | {/* Hero section with full-width background image */} 62 |
63 |
71 |
72 |
73 |
74 |

{t("home.title")}

75 |

{t("home.subtitle")}

76 |
77 |
78 | {/* End hero section */} 79 | 80 |
81 |
82 | {/* First Column: Vision and Mission */} 83 |
84 | 85 | 86 |
87 | 88 |
89 | {t("home.vision.title")} 90 |
91 | 92 |

{t("home.vision.content")}

93 |
94 |
95 | 96 | 97 |
98 | 99 |
100 | {t("home.mission.title")} 101 |
102 | 103 |

{t("home.mission.content")}

104 |
105 |
106 |
107 | 108 | {/* Second Column: Responsibilities */} 109 | 110 | 111 |
112 | 113 |
114 | {t("home.responsibilities.title")} 115 |
116 | 117 |
    118 |
  • 119 | 120 | {t("home.responsibilities.item1")} 121 |
  • 122 |
  • 123 | 124 | {t("home.responsibilities.item2")} 125 |
  • 126 |
  • 127 | 128 | {t("home.responsibilities.item3")} 129 |
  • 130 |
  • 131 | 132 | {t("home.responsibilities.item4")} 133 |
  • 134 |
  • 135 | 136 | {t("home.responsibilities.item5")} 137 |
  • 138 |
139 |
140 |
141 |
142 | {/* End of layout refactor */} 143 | 144 |
145 |

{t("home.team.title")}

146 |
147 | {teamMembers.map((member) => ( 148 | 149 | 150 | 151 | 152 | {member.name.substring(0, 2)} 153 | 154 |

{member.name}

155 |

{member.role}

156 |

{member.email}

157 |
158 |
159 | ))} 160 |
161 |
162 | 163 |
164 |

{t("home.links.title")}

165 |
166 | 167 | 168 | {t("home.links.internal")} 169 | 170 | 171 |
    172 | {internalLinks.map((link) => ( 173 |
  • 174 | 175 | {link.name} 176 | 177 |
  • 178 | ))} 179 |
180 |
181 |
182 | 183 | 184 | {t("home.links.external")} 185 | 186 | 187 |
    188 | {externalLinks.map((link) => ( 189 |
  • 190 | 196 | {link.name} 197 | 198 | 199 |
  • 200 | ))} 201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | ) 209 | } 210 | -------------------------------------------------------------------------------- /app/resources/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useLanguage } from "@/components/language-provider" 4 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" 5 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" 6 | import { FileCode, Award, ArrowRight, CheckCircle2 } from "lucide-react" 7 | import Link from "next/link" 8 | import { Button } from "@/components/ui/button" 9 | 10 | export default function ResourcesPage() { 11 | const { t } = useLanguage() 12 | 13 | const processes = [ 14 | { 15 | titleKey: "resources.process.contribution.title", 16 | descKey: "resources.process.contribution.desc", 17 | link: "#", 18 | steps: 5, 19 | }, 20 | { 21 | titleKey: "resources.process.license.title", 22 | descKey: "resources.process.license.desc", 23 | link: "#", 24 | steps: 4, 25 | }, 26 | { 27 | titleKey: "resources.process.release.title", 28 | descKey: "resources.process.release.desc", 29 | link: "#", 30 | steps: 7, 31 | }, 32 | { 33 | titleKey: "resources.process.security.title", 34 | descKey: "resources.process.security.desc", 35 | link: "#", 36 | steps: 6, 37 | }, 38 | { 39 | titleKey: "resources.process.request.title", 40 | descKey: "resources.process.request.desc", 41 | link: "#", 42 | steps: 4, 43 | }, 44 | { 45 | titleKey: "resources.process.incident.title", 46 | descKey: "resources.process.incident.desc", 47 | link: "#", 48 | steps: 5, 49 | }, 50 | ] 51 | 52 | const guides = [ 53 | { 54 | titleKey: "resources.guide.quickstart.title", 55 | descKey: "resources.guide.quickstart.desc", 56 | link: "#", 57 | type: "guide", 58 | }, 59 | { 60 | titleKey: "resources.guide.bestpractice.title", 61 | descKey: "resources.guide.bestpractice.desc", 62 | link: "#", 63 | type: "guide", 64 | }, 65 | { 66 | titleKey: "resources.guide.community.title", 67 | descKey: "resources.guide.community.desc", 68 | link: "#", 69 | type: "guide", 70 | }, 71 | { 72 | titleKey: "resources.guide.cla.title", 73 | descKey: "resources.guide.cla.desc", 74 | link: "#", 75 | type: "template", 76 | }, 77 | ] 78 | 79 | const cases = [ 80 | { 81 | titleKey: "resources.case.cloud.title", 82 | descKey: "resources.case.cloud.desc", 83 | department: "Cloud Infrastructure", 84 | departmentKey: "resources.case.dept.cloud", 85 | impact: "High", 86 | impactKey: "resources.case.impact.high", 87 | metrics: "35%", 88 | metricsLabel: "resources.case.cloud.metric", 89 | link: "#", 90 | }, 91 | { 92 | titleKey: "resources.case.ml.title", 93 | descKey: "resources.case.ml.desc", 94 | department: "Data Science", 95 | departmentKey: "resources.case.dept.data", 96 | impact: "High", 97 | impactKey: "resources.case.impact.high", 98 | metrics: "60%", 99 | metricsLabel: "resources.case.ml.metric", 100 | link: "#", 101 | }, 102 | { 103 | titleKey: "resources.case.devtools.title", 104 | descKey: "resources.case.devtools.desc", 105 | department: "Engineering", 106 | departmentKey: "resources.case.dept.eng", 107 | impact: "Medium", 108 | impactKey: "resources.case.impact.medium", 109 | metrics: "25%", 110 | metricsLabel: "resources.case.devtools.metric", 111 | link: "#", 112 | }, 113 | { 114 | titleKey: "resources.case.support.title", 115 | descKey: "resources.case.support.desc", 116 | department: "Customer Support", 117 | departmentKey: "resources.case.dept.support", 118 | impact: "Medium", 119 | impactKey: "resources.case.impact.medium", 120 | metrics: "40%", 121 | metricsLabel: "resources.case.support.metric", 122 | link: "#", 123 | }, 124 | ] 125 | 126 | return ( 127 |
128 |
129 |

{t("resources.title")}

130 |

{t("resources.subtitle")}

131 |
132 | 133 | 134 | 135 | 136 | 137 | {t("resources.processes.title")} 138 | 139 | 140 | 141 | {t("resources.cases.title")} 142 | 143 | 144 | 145 | 146 |
147 | {/* Processes Section */} 148 |
149 |

{t("resources.processes.section")}

150 |

{t("resources.processes.desc")}

151 |
152 | {processes.map((process) => ( 153 | 154 | 155 | {t(process.titleKey)} 156 | {t(process.descKey)} 157 | 158 | 159 |
160 | 161 | {process.steps} {t("resources.steps")} 162 | 163 | 169 |
170 |
171 |
172 | ))} 173 |
174 |
175 | 176 | {/* Guides Section */} 177 |
178 |

{t("resources.guides.section")}

179 |

{t("resources.guides.desc")}

180 |
181 | {guides.map((guide) => ( 182 | 183 | 184 |
185 |
186 | {t(guide.titleKey)} 187 | {t(guide.descKey)} 188 |
189 | 190 | {t(`resources.type.${guide.type}`)} 191 | 192 |
193 |
194 | 195 | 198 | 199 |
200 | ))} 201 |
202 |
203 |
204 |
205 | 206 | 207 |
208 |

{t("resources.cases.desc")}

209 |
210 | {cases.map((caseStudy) => ( 211 | 212 | 213 |
214 | {t(caseStudy.titleKey)} 215 | 222 | {t(caseStudy.impactKey)} 223 | 224 |
225 | {t(caseStudy.descKey)} 226 |
227 | 228 |
229 |
230 | {t("resources.case.department")}: 231 | {t(caseStudy.departmentKey)} 232 |
233 |
234 | 235 |
236 | {caseStudy.metrics} 237 | {t(caseStudy.metricsLabel)} 238 |
239 |
240 | 243 |
244 |
245 |
246 | ))} 247 |
248 |
249 |
250 |
251 |
252 | ) 253 | } 254 | -------------------------------------------------------------------------------- /app/governance/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useLanguage } from "@/components/language-provider" 4 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" 5 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" 6 | import { FileText, Users, GitBranch, Building2, Target, Shield } from "lucide-react" 7 | import { Button } from "@/components/ui/button" 8 | import Link from "next/link" 9 | 10 | export default function GovernancePage() { 11 | const { t } = useLanguage() 12 | 13 | const policies = [ 14 | { 15 | icon: FileText, 16 | titleKey: "governance.policy.overall.title", 17 | descKey: "governance.policy.overall.desc", 18 | link: "#", 19 | updated: "2024-03-15", 20 | }, 21 | { 22 | icon: Shield, 23 | titleKey: "governance.policy.contribution.title", 24 | descKey: "governance.policy.contribution.desc", 25 | link: "#", 26 | updated: "2024-02-20", 27 | }, 28 | { 29 | icon: Target, 30 | titleKey: "governance.policy.usage.title", 31 | descKey: "governance.policy.usage.desc", 32 | link: "#", 33 | updated: "2024-01-10", 34 | }, 35 | { 36 | icon: Building2, 37 | titleKey: "governance.policy.ip.title", 38 | descKey: "governance.policy.ip.desc", 39 | link: "#", 40 | updated: "2024-03-05", 41 | }, 42 | ] 43 | 44 | const orgStructure = [ 45 | { 46 | role: "governance.org.committee", 47 | roleDesc: "governance.org.committee.desc", 48 | members: ["CTO", "Legal Director", "Engineering VP", "Security Director"], 49 | }, 50 | { 51 | role: "governance.org.ospo", 52 | roleDesc: "governance.org.ospo.desc", 53 | members: ["OSPO Director", "Program Manager", "Compliance Lead", "Developer Advocate"], 54 | }, 55 | { 56 | role: "governance.org.ambassadors", 57 | roleDesc: "governance.org.ambassadors.desc", 58 | members: ["Engineering Leads", "Tech Leads", "Senior Developers"], 59 | }, 60 | ] 61 | 62 | const operations = [ 63 | { 64 | titleKey: "governance.ops.review.title", 65 | descKey: "governance.ops.review.desc", 66 | frequency: "governance.ops.review.freq", 67 | link: "#", 68 | }, 69 | { 70 | titleKey: "governance.ops.approval.title", 71 | descKey: "governance.ops.approval.desc", 72 | frequency: "governance.ops.approval.freq", 73 | link: "#", 74 | }, 75 | { 76 | titleKey: "governance.ops.audit.title", 77 | descKey: "governance.ops.audit.desc", 78 | frequency: "governance.ops.audit.freq", 79 | link: "#", 80 | }, 81 | { 82 | titleKey: "governance.ops.report.title", 83 | descKey: "governance.ops.report.desc", 84 | frequency: "governance.ops.report.freq", 85 | link: "#", 86 | }, 87 | ] 88 | 89 | return ( 90 |
91 |
92 |

{t("governance.title")}

93 |

{t("governance.subtitle")}

94 |
95 | 96 | 97 | 98 | 99 | 100 | {t("governance.tab.policies")} 101 | 102 | 103 | 104 | {t("governance.tab.organization")} 105 | 106 | 107 | 108 | {t("governance.tab.operations")} 109 | 110 | 111 | 112 | 113 |
114 |

{t("governance.policies.desc")}

115 |
116 | {policies.map((policy) => ( 117 | 118 | 119 |
120 |
121 | 122 |
123 |
124 | {t(policy.titleKey)} 125 |
126 |
127 | {t(policy.descKey)} 128 |
129 | 130 |
131 | 132 | {t("governance.updated")}: {policy.updated} 133 | 134 | 137 |
138 |
139 |
140 | ))} 141 |
142 |
143 |
144 | 145 | 146 |
147 |

{t("governance.org.desc")}

148 | 149 |
150 | {orgStructure.map((org, index) => ( 151 | 152 | 153 |
154 |
155 | {index + 1} 156 |
157 |
158 | {t(org.role)} 159 | {t(org.roleDesc)} 160 |
161 |
162 |
163 | 164 |
165 | {org.members.map((member) => ( 166 | 170 | {member} 171 | 172 | ))} 173 |
174 |
175 |
176 | ))} 177 |
178 | 179 | 180 | 181 | {t("governance.org.chart.title")} 182 | {t("governance.org.chart.desc")} 183 | 184 | 185 |
186 |
187 | {t("governance.org.committee")} 188 |
189 |
190 |
191 | {t("governance.org.ospo")} 192 |
193 |
194 |
195 |
196 | {t("governance.org.compliance")} 197 |
198 |
199 | {t("governance.org.community")} 200 |
201 |
202 | {t("governance.org.engineering")} 203 |
204 |
205 |
206 | 207 | 208 |
209 | 210 | 211 | 212 |
213 |

{t("governance.ops.desc")}

214 | 215 |
216 | {operations.map((op) => ( 217 | 218 | 219 | {t(op.titleKey)} 220 | {t(op.descKey)} 221 | 222 | 223 |
224 | 225 | {t(op.frequency)} 226 | 227 | 230 |
231 |
232 |
233 | ))} 234 |
235 | 236 | 237 | 238 | {t("governance.ops.workflow.title")} 239 | {t("governance.ops.workflow.desc")} 240 | 241 | 242 |
243 | {[1, 2, 3, 4, 5].map((step, index) => ( 244 |
245 |
246 |
247 | {step} 248 |
249 | {t(`governance.ops.step${step}`)} 250 |
251 | {index < 4 &&
} 252 |
253 | ))} 254 |
255 | 256 | 257 |
258 | 259 | 260 |
261 | ) 262 | } 263 | -------------------------------------------------------------------------------- /app/projects/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useLanguage } from "@/components/language-provider" 4 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" 5 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" 6 | import { Badge } from "@/components/ui/badge" 7 | import { ExternalLink, Github, Building2, Users, Globe } from "lucide-react" 8 | import Link from "next/link" 9 | 10 | export default function ProjectsPage() { 11 | const { t } = useLanguage() 12 | 13 | const internalProjects = [ 14 | { 15 | name: "OpenAPI Framework", 16 | description: "A framework for building and consuming RESTful APIs using OpenAPI specifications", 17 | status: "active", 18 | language: "TypeScript", 19 | repo: "https://github.internal.com/example/openapi-framework", 20 | maintainers: ["Alex Chen", "Michael Zhang"], 21 | stars: 245, 22 | }, 23 | { 24 | name: "Data Pipeline Toolkit", 25 | description: "Tools for building scalable data processing pipelines", 26 | status: "active", 27 | language: "Python", 28 | repo: "https://github.internal.com/example/data-pipeline-toolkit", 29 | maintainers: ["Sarah Johnson", "David Wang"], 30 | stars: 187, 31 | }, 32 | { 33 | name: "Config Manager", 34 | description: "A configuration management library for distributed systems", 35 | status: "incubating", 36 | language: "Go", 37 | repo: "https://github.internal.com/example/config-manager", 38 | maintainers: ["Michael Zhang"], 39 | stars: 56, 40 | }, 41 | ] 42 | 43 | const externalContributions = [ 44 | { 45 | name: "Kubernetes", 46 | description: "Container orchestration system", 47 | contribution: "Bug fixes and documentation improvements", 48 | repo: "https://github.com/kubernetes/kubernetes", 49 | contributors: ["Alex Chen", "David Wang"], 50 | prs: 23, 51 | }, 52 | { 53 | name: "TensorFlow", 54 | description: "Machine learning framework", 55 | contribution: "Added new model optimization features", 56 | repo: "https://github.com/tensorflow/tensorflow", 57 | contributors: ["Sarah Johnson"], 58 | prs: 8, 59 | }, 60 | { 61 | name: "React", 62 | description: "JavaScript library for building user interfaces", 63 | contribution: "Performance improvements and bug fixes", 64 | repo: "https://github.com/facebook/react", 65 | contributors: ["Emma Liu"], 66 | prs: 15, 67 | }, 68 | { 69 | name: "Apache Kafka", 70 | description: "Distributed streaming platform", 71 | contribution: "New connector implementations", 72 | repo: "https://github.com/apache/kafka", 73 | contributors: ["Michael Zhang"], 74 | prs: 12, 75 | }, 76 | ] 77 | 78 | const publicProjects = [ 79 | { 80 | name: "UI Component Library", 81 | description: "Reusable UI components built with React for modern web applications", 82 | status: "active", 83 | language: "TypeScript", 84 | repo: "https://github.com/company/ui-components", 85 | maintainers: ["Emma Liu", "Alex Chen"], 86 | stars: 1245, 87 | forks: 328, 88 | license: "MIT", 89 | }, 90 | { 91 | name: "Cloud SDK", 92 | description: "Official SDK for integrating with our cloud services", 93 | status: "active", 94 | language: "TypeScript", 95 | repo: "https://github.com/company/cloud-sdk", 96 | maintainers: ["David Wang", "Sarah Johnson"], 97 | stars: 892, 98 | forks: 156, 99 | license: "Apache-2.0", 100 | }, 101 | { 102 | name: "ML Toolkit", 103 | description: "Machine learning utilities and pre-trained models", 104 | status: "active", 105 | language: "Python", 106 | repo: "https://github.com/company/ml-toolkit", 107 | maintainers: ["Sarah Johnson"], 108 | stars: 2156, 109 | forks: 489, 110 | license: "Apache-2.0", 111 | }, 112 | { 113 | name: "DevOps CLI", 114 | description: "Command-line tools for DevOps automation and deployment", 115 | status: "maintenance", 116 | language: "Go", 117 | repo: "https://github.com/company/devops-cli", 118 | maintainers: ["Michael Zhang"], 119 | stars: 567, 120 | forks: 98, 121 | license: "MIT", 122 | }, 123 | ] 124 | 125 | const getStatusColor = (status: string) => { 126 | switch (status) { 127 | case "active": 128 | return "bg-green-500 hover:bg-green-600" 129 | case "maintenance": 130 | return "bg-yellow-500 hover:bg-yellow-600" 131 | case "incubating": 132 | return "bg-blue-500 hover:bg-blue-600" 133 | default: 134 | return "bg-gray-500 hover:bg-gray-600" 135 | } 136 | } 137 | 138 | return ( 139 |
140 |
141 |

{t("projects.title")}

142 |

{t("projects.subtitle")}

143 |
144 | 145 | 146 | 147 | 148 | 149 | {t("projects.internal")} 150 | 151 | 152 | 153 | {t("projects.external")} 154 | 155 | 156 | 157 | {t("projects.public")} 158 | 159 | 160 | 161 | {/* 内部开源项目 */} 162 | 163 |
164 |

{t("projects.internal.desc")}

165 |
166 |
167 | {internalProjects.map((project) => ( 168 | 169 | 170 |
171 |
172 | {project.name} 173 | {project.description} 174 |
175 | {t(`projects.${project.status}`)} 176 |
177 |
178 | 179 |
180 |
181 |
182 | {project.language} 183 | 184 | {project.stars} 185 | 186 |
187 | 193 | 194 | {t("projects.repo")} 195 | 196 |
197 |
198 |

{t("projects.maintainers")}:

199 |
200 | {project.maintainers.map((maintainer) => ( 201 | 202 | {maintainer} 203 | 204 | ))} 205 |
206 |
207 |
208 |
209 |
210 | ))} 211 |
212 |
213 | 214 | {/* 参与外部贡献 */} 215 | 216 |
217 |

{t("projects.external.desc")}

218 |
219 |
220 | {externalContributions.map((project) => ( 221 | 222 | 223 | 224 | {project.name} 225 | 226 | 227 | {project.description} 228 | 229 | 230 |
231 |
232 |

{t("projects.contribution")}:

233 |

{project.contribution}

234 |
235 |
236 | 237 | {project.prs} PRs {t("projects.merged")} 238 | 239 | 245 | 246 | {t("projects.repo")} 247 | 248 |
249 |
250 |

{t("projects.contributors")}:

251 |
252 | {project.contributors.map((contributor) => ( 253 | 254 | {contributor} 255 | 256 | ))} 257 |
258 |
259 |
260 |
261 |
262 | ))} 263 |
264 |
265 | 266 | {/* 对外开源项目 */} 267 | 268 |
269 |

{t("projects.public.desc")}

270 |
271 |
272 | {publicProjects.map((project) => ( 273 | 274 | 275 |
276 |
277 | 278 | 279 | {project.name} 280 | 281 | {project.description} 282 |
283 | {t(`projects.${project.status}`)} 284 |
285 |
286 | 287 |
288 |
289 |
290 | {project.language} 291 | 292 | {project.license} 293 | 294 |
295 |
296 |
297 | 298 | {project.stars.toLocaleString()} 299 | 300 | 301 | 302 | 308 | 309 | {project.forks.toLocaleString()} {t("projects.forks")} 310 | 311 |
312 |
313 |
314 |

{t("projects.maintainers")}:

315 |
316 | {project.maintainers.map((maintainer) => ( 317 | 318 | {maintainer} 319 | 320 | ))} 321 |
322 |
323 | 329 | 330 | {t("projects.repo")} 331 | 332 |
333 |
334 |
335 |
336 | ))} 337 |
338 |
339 |
340 |
341 | ) 342 | } 343 | -------------------------------------------------------------------------------- /app/compliance/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useState } from "react" 4 | import { useLanguage } from "@/components/language-provider" 5 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" 6 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" 7 | import { Badge } from "@/components/ui/badge" 8 | import { Progress } from "@/components/ui/progress" 9 | import { 10 | FileText, 11 | BarChart3, 12 | BookOpen, 13 | Wrench, 14 | CheckCircle2, 15 | AlertTriangle, 16 | ExternalLink, 17 | Mail, 18 | Phone, 19 | Shield, 20 | } from "lucide-react" 21 | 22 | export default function CompliancePage() { 23 | const { t } = useLanguage() 24 | const [activeTab, setActiveTab] = useState("metrics") 25 | 26 | const policies = [ 27 | { 28 | title: t("compliance.policy.license.title"), 29 | description: t("compliance.policy.license.desc"), 30 | }, 31 | { 32 | title: t("compliance.policy.review.title"), 33 | description: t("compliance.policy.review.desc"), 34 | }, 35 | { 36 | title: t("compliance.policy.contacts.title"), 37 | description: t("compliance.policy.contacts.desc"), 38 | }, 39 | ] 40 | 41 | const metrics = { 42 | overview: [ 43 | { label: t("compliance.metrics.scanned"), value: 1247, change: "+12%" }, 44 | { label: t("compliance.metrics.compliant"), value: 1198, change: "+8%" }, 45 | { label: t("compliance.metrics.issues"), value: 49, change: "-15%" }, 46 | { label: t("compliance.metrics.rate"), value: "96.1%", change: "+2.3%" }, 47 | ], 48 | licenseDistribution: [ 49 | { name: "MIT", count: 456, percentage: 38, status: "allowed" }, 50 | { name: "Apache-2.0", count: 324, percentage: 27, status: "allowed" }, 51 | { name: "BSD-3-Clause", count: 198, percentage: 16, status: "allowed" }, 52 | { name: "GPL-3.0", count: 89, percentage: 7, status: "review" }, 53 | { name: "LGPL-2.1", count: 67, percentage: 6, status: "review" }, 54 | { name: t("compliance.metrics.other"), count: 64, percentage: 5, status: "review" }, 55 | ], 56 | } 57 | 58 | const knowledgeBase = [ 59 | { 60 | category: t("compliance.kb.guides"), 61 | items: [ 62 | { title: t("compliance.kb.guide1"), type: "PDF" }, 63 | { title: t("compliance.kb.guide2"), type: "Wiki" }, 64 | { title: t("compliance.kb.guide3"), type: "PDF" }, 65 | ], 66 | }, 67 | { 68 | category: t("compliance.kb.faqs"), 69 | items: [ 70 | { title: t("compliance.kb.faq1"), type: "Wiki" }, 71 | { title: t("compliance.kb.faq2"), type: "Wiki" }, 72 | { title: t("compliance.kb.faq3"), type: "Wiki" }, 73 | ], 74 | }, 75 | { 76 | category: t("compliance.kb.training"), 77 | items: [ 78 | { title: t("compliance.kb.training1"), type: "Video" }, 79 | { title: t("compliance.kb.training2"), type: "Video" }, 80 | { title: t("compliance.kb.training3"), type: "Course" }, 81 | ], 82 | }, 83 | ] 84 | 85 | const scaTools = [ 86 | { 87 | name: "Black Duck", 88 | description: t("compliance.tools.blackduck"), 89 | status: "active", 90 | url: "#", 91 | }, 92 | { 93 | name: "Snyk", 94 | description: t("compliance.tools.snyk"), 95 | status: "active", 96 | url: "#", 97 | }, 98 | { 99 | name: "FOSSA", 100 | description: t("compliance.tools.fossa"), 101 | status: "active", 102 | url: "#", 103 | }, 104 | { 105 | name: "WhiteSource", 106 | description: t("compliance.tools.whitesource"), 107 | status: "evaluation", 108 | url: "#", 109 | }, 110 | ] 111 | 112 | const contacts = [ 113 | { 114 | name: t("compliance.contacts.lead"), 115 | role: t("compliance.contacts.leadRole"), 116 | email: "compliance-lead@example.com", 117 | phone: "+86 xxx-xxxx-xxxx", 118 | }, 119 | { 120 | name: t("compliance.contacts.legal"), 121 | role: t("compliance.contacts.legalRole"), 122 | email: "legal@example.com", 123 | phone: "+86 xxx-xxxx-xxxx", 124 | }, 125 | ] 126 | 127 | const supplyChainHealth = { 128 | overall: 82, 129 | dimensions: [ 130 | { name: t("compliance.supplyChain.security"), score: 85, desc: t("compliance.supplyChain.securityDesc") }, 131 | { name: t("compliance.supplyChain.maintenance"), score: 78, desc: t("compliance.supplyChain.maintenanceDesc") }, 132 | { name: t("compliance.supplyChain.community"), score: 88, desc: t("compliance.supplyChain.communityDesc") }, 133 | { name: t("compliance.supplyChain.license"), score: 92, desc: t("compliance.supplyChain.licenseDesc") }, 134 | { name: t("compliance.supplyChain.quality"), score: 76, desc: t("compliance.supplyChain.qualityDesc") }, 135 | ], 136 | } 137 | 138 | return ( 139 |
140 |
141 |

{t("compliance.title")}

142 |

{t("compliance.subtitle")}

143 |
144 | 145 |
146 | {metrics.overview.map((metric, index) => ( 147 | 148 | 149 |
{metric.value}
150 |

{metric.label}

151 | 152 | {metric.change} 153 | 154 |
155 |
156 | ))} 157 |
158 | {/* End metrics overview */} 159 | 160 | 161 | 162 | 163 | 164 | {t("compliance.tab.metrics")} 165 | 166 | 167 | 168 | {t("compliance.tab.policy")} 169 | 170 | 171 | 172 | {t("compliance.tab.knowledge")} 173 | 174 | 175 | 176 | {t("compliance.tab.tools")} 177 | 178 | 179 | 180 | {t("compliance.tab.supplyChain")} 181 | 182 | 183 | 184 | {/* Metrics Tab */} 185 | 186 | 187 | 188 | {t("compliance.metrics.distribution")} 189 | {t("compliance.metrics.distributionDesc")} 190 | 191 | 192 | {metrics.licenseDistribution.map((license, index) => ( 193 |
194 |
195 |
196 | {license.name} 197 | {license.status === "allowed" ? ( 198 | 199 | ) : ( 200 | 201 | )} 202 |
203 | 204 | {license.count} ({license.percentage}%) 205 | 206 |
207 | 208 |
209 | ))} 210 |
211 |
212 |
213 | 214 | {/* Policy Tab */} 215 | 216 | 217 | 218 | {t("compliance.policy.overview")} 219 | 220 | 221 | {policies.map((policy, index) => ( 222 |
223 |

{policy.title}

224 |

{policy.description}

225 |
226 | ))} 227 |
228 |
229 | 230 | 231 | 232 | {t("compliance.contacts.title")} 233 | {t("compliance.contacts.desc")} 234 | 235 | 236 |
237 | {contacts.map((contact, index) => ( 238 | 239 | 240 |
241 |

{contact.name}

242 |

{contact.role}

243 |
244 | 245 | {contact.email} 246 |
247 |
248 | 249 | {contact.phone} 250 |
251 |
252 |
253 |
254 | ))} 255 |
256 |
257 |
258 |
259 | 260 | {/* Knowledge Base Tab */} 261 | 262 | {knowledgeBase.map((category, index) => ( 263 | 264 | 265 | {category.category} 266 | 267 | 268 |
269 | {category.items.map((item, itemIndex) => ( 270 |
274 |
275 | 276 | {item.title} 277 |
278 |
279 | {item.type} 280 | 281 |
282 |
283 | ))} 284 |
285 |
286 |
287 | ))} 288 |
289 | 290 | {/* SCA Tools Tab */} 291 | 292 | 293 | 294 | {t("compliance.tools.title")} 295 | {t("compliance.tools.desc")} 296 | 297 | 298 |
299 | {scaTools.map((tool, index) => ( 300 | 301 | 302 |
303 |
304 |
305 |

{tool.name}

306 | {tool.status === "active" ? ( 307 | {t("compliance.tools.active")} 308 | ) : ( 309 | {t("compliance.tools.evaluation")} 310 | )} 311 |
312 |

{tool.description}

313 |
314 | 315 |
316 |
317 |
318 | ))} 319 |
320 |
321 |
322 | 323 | 324 | 325 | {t("compliance.tools.integration")} 326 | 327 | 328 |
329 |
330 |
331 | 332 | {t("compliance.tools.cicd")} 333 |
334 | {t("compliance.tools.configured")} 335 |
336 |
337 |
338 | 339 | {t("compliance.tools.repo")} 340 |
341 | {t("compliance.tools.configured")} 342 |
343 |
344 |
345 | 346 | {t("compliance.tools.sbom")} 347 |
348 | {t("compliance.tools.inProgress")} 349 |
350 |
351 |
352 |
353 |
354 | 355 | {/* Supply Chain Tab */} 356 | 357 | 358 | 359 | {t("compliance.supplyChain.title")} 360 | {t("compliance.supplyChain.desc")} 361 | 362 | 363 |
364 |
365 | 366 | 375 | 385 | 386 |
387 |
{supplyChainHealth.overall}
388 |
{t("compliance.supplyChain.overallHealth")}
389 |
390 |
391 |
392 | 393 |
394 | {supplyChainHealth.dimensions.map((dimension, index) => ( 395 |
396 |
397 |
398 |

{dimension.name}

399 |

{dimension.desc}

400 |
401 |
{dimension.score}
402 |
403 | 404 |
405 | ))} 406 |
407 |
408 |
409 | 410 | 411 | 412 | {t("compliance.supplyChain.riskTitle")} 413 | 414 | 415 |
416 |
417 |
418 | 419 |
420 |
{t("compliance.supplyChain.highRisk")}
421 |
{t("compliance.supplyChain.highRiskDesc")}
422 |
423 |
424 | 3 425 |
426 |
427 |
428 | 429 |
430 |
{t("compliance.supplyChain.mediumRisk")}
431 |
{t("compliance.supplyChain.mediumRiskDesc")}
432 |
433 |
434 | 12 435 |
436 |
437 |
438 | 439 |
440 |
{t("compliance.supplyChain.lowRisk")}
441 |
{t("compliance.supplyChain.lowRiskDesc")}
442 |
443 |
444 | 1232 445 |
446 |
447 |
448 |
449 |
450 | {/* End supply chain tab */} 451 |
452 |
453 | ) 454 | } 455 | -------------------------------------------------------------------------------- /components/language-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import type React from "react" 4 | import { createContext, useContext, useState, useEffect } from "react" 5 | 6 | type Language = "en" | "zh" 7 | 8 | type TranslationKey = string 9 | 10 | interface LanguageContextType { 11 | language: Language 12 | setLanguage: (lang: Language) => void 13 | t: (key: TranslationKey) => string 14 | } 15 | 16 | const LanguageContext = createContext(undefined) 17 | 18 | const translations = { 19 | en: { 20 | // Navigation 21 | "nav.home": "Home", 22 | "nav.capabilities": "Capabilities", 23 | "nav.projects": "Projects", 24 | "nav.governance": "Governance", 25 | "nav.resources": "Resources", 26 | "nav.compliance": "Compliance", 27 | 28 | // Home page 29 | "home.title": "Open Source Program Office", 30 | "home.subtitle": "Driving innovation through open source collaboration", 31 | "home.vision.title": "Our Vision", 32 | "home.vision.content": 33 | "To establish a thriving open source culture that drives innovation, collaboration, and technological excellence across our organization.", 34 | "home.mission.title": "Our Mission", 35 | "home.mission.content": 36 | "To enable and support open source adoption, contribution, and compliance throughout the organization while fostering a collaborative ecosystem with the broader open source community.", 37 | "home.responsibilities.title": "Key Responsibilities", 38 | "home.responsibilities.item1": "Open Source Strategy & Governance", 39 | "home.responsibilities.item2": "License Compliance & Risk Management", 40 | "home.responsibilities.item3": "Community Engagement & Contribution", 41 | "home.responsibilities.item4": "Developer Education & Enablement", 42 | "home.responsibilities.item5": "Project Incubation & Maintenance", 43 | "home.team.title": "Our Team", 44 | "home.team.director": "OSPO Director", 45 | "home.team.manager": "Program Manager", 46 | "home.team.engineer": "Open Source Engineer", 47 | "home.team.legal": "Legal Counsel", 48 | "home.team.developer": "Developer Advocate", 49 | "home.links.title": "Important Links", 50 | "home.links.internal": "Internal Resources", 51 | "home.links.external": "External Resources", 52 | 53 | // Capabilities page 54 | "capabilities.title": "Open Source Capabilities", 55 | "capabilities.subtitle": "Building excellence in open source practices", 56 | "capabilities.progress": "Progress", 57 | "capabilities.nav.title": "Quick Navigation", 58 | "capabilities.governance.title": "Open Source Governance", 59 | "capabilities.governance.desc": 60 | "Establish policies, processes, and guidelines for open source usage and contribution", 61 | "capabilities.education.title": "Developer Education", 62 | "capabilities.education.desc": "Provide training and resources for developers on open source best practices", 63 | "capabilities.contribution.title": "Contribution Strategy", 64 | "capabilities.contribution.desc": "Strategic approach to contributing to external open source projects", 65 | "capabilities.innersource.title": "Inner Source Program", 66 | "capabilities.innersource.desc": "Apply open source principles to internal development", 67 | "capabilities.security.title": "Security & Compliance", 68 | "capabilities.security.desc": "Ensure security and legal compliance in open source usage", 69 | "capabilities.milestones": "Milestones", 70 | "capabilities.status.completed": "Completed", 71 | "capabilities.status.inProgress": "In Progress", 72 | "capabilities.status.planned": "Planned", 73 | "capabilities.milestone.policyFramework": "Policy Framework", 74 | "capabilities.milestone.governanceCommittee": "Governance Committee", 75 | "capabilities.milestone.complianceTooling": "Compliance Tooling", 76 | "capabilities.milestone.auditProcess": "Audit Process", 77 | "capabilities.milestone.basicTraining": "Basic Training", 78 | "capabilities.milestone.advancedWorkshops": "Advanced Workshops", 79 | "capabilities.milestone.certificationProgram": "Certification Program", 80 | "capabilities.milestone.mentorshipProgram": "Mentorship Program", 81 | "capabilities.milestone.contributionGuidelines": "Contribution Guidelines", 82 | "capabilities.milestone.projectSelectionFramework": "Project Selection Framework", 83 | "capabilities.milestone.contributionMetrics": "Contribution Metrics", 84 | "capabilities.milestone.communityLeadership": "Community Leadership", 85 | "capabilities.milestone.innersourceGuidelines": "Inner Source Guidelines", 86 | "capabilities.milestone.pilotProjects": "Pilot Projects", 87 | "capabilities.milestone.toolingInfrastructure": "Tooling & Infrastructure", 88 | "capabilities.milestone.organizationRollout": "Organization Rollout", 89 | "capabilities.milestone.securityScanning": "Security Scanning", 90 | "capabilities.milestone.licenseCompliance": "License Compliance", 91 | "capabilities.milestone.vulnerabilityManagement": "Vulnerability Management", 92 | "capabilities.milestone.automatedCompliance": "Automated Compliance", 93 | 94 | // Projects page 95 | "projects.title": "Open Source Projects", 96 | "projects.subtitle": "Our contributions to the open source ecosystem", 97 | "projects.internal": "Internal Projects", 98 | "projects.internal.desc": "Open source projects used internally within the organization, not publicly released.", 99 | "projects.external": "External Contributions", 100 | "projects.external.desc": "Our contributions to external open source projects and communities.", 101 | "projects.public": "Public Projects", 102 | "projects.public.desc": "Open source projects released publicly by our organization for the community.", 103 | "projects.status": "Status", 104 | "projects.active": "Active", 105 | "projects.maintenance": "Maintenance", 106 | "projects.incubating": "Incubating", 107 | "projects.repo": "Repository", 108 | "projects.maintainers": "Maintainers", 109 | "projects.contributors": "Contributors", 110 | "projects.contribution": "Contribution", 111 | "projects.merged": "Merged", 112 | "projects.forks": "Forks", 113 | 114 | // Governance page 115 | "governance.title": "Governance Policies", 116 | "governance.subtitle": "Open source governance framework, policies, and organizational structure", 117 | "governance.tab.policies": "Policies", 118 | "governance.tab.organization": "Organization", 119 | "governance.tab.operations": "Operations", 120 | "governance.policies.desc": "Comprehensive policies governing open source activities across the organization.", 121 | "governance.policy.overall.title": "Overall Open Source Policy", 122 | "governance.policy.overall.desc": 123 | "The foundational policy defining our approach to open source software usage, contribution, and release.", 124 | "governance.policy.contribution.title": "Contribution Policy", 125 | "governance.policy.contribution.desc": 126 | "Guidelines and requirements for contributing to external open source projects.", 127 | "governance.policy.usage.title": "Usage Policy", 128 | "governance.policy.usage.desc": 129 | "Standards for evaluating, approving, and using open source components in products.", 130 | "governance.policy.ip.title": "IP Rights Management", 131 | "governance.policy.ip.desc": 132 | "Intellectual property considerations and CLA requirements for open source activities.", 133 | "governance.updated": "Updated", 134 | "governance.view": "View Policy", 135 | "governance.org.desc": "The organizational structure supporting open source governance and operations.", 136 | "governance.org.committee": "Open Source Steering Committee", 137 | "governance.org.committee.desc": "Executive-level oversight and strategic direction for open source initiatives.", 138 | "governance.org.ospo": "Open Source Program Office", 139 | "governance.org.ospo.desc": "Central team responsible for implementing and managing open source programs.", 140 | "governance.org.ambassadors": "Open Source Ambassadors", 141 | "governance.org.ambassadors.desc": "Representatives across teams promoting open source best practices.", 142 | "governance.org.chart.title": "Organization Chart", 143 | "governance.org.chart.desc": "Hierarchical structure of open source governance", 144 | "governance.org.compliance": "Compliance Team", 145 | "governance.org.community": "Community Team", 146 | "governance.org.engineering": "Engineering Support", 147 | "governance.ops.desc": "Regular operations and workflows for open source governance.", 148 | "governance.ops.review.title": "Monthly Review Meeting", 149 | "governance.ops.review.desc": "Regular review of open source activities, metrics, and issues.", 150 | "governance.ops.review.freq": "Monthly", 151 | "governance.ops.approval.title": "Project Approval Process", 152 | "governance.ops.approval.desc": "Workflow for approving new open source usage or contributions.", 153 | "governance.ops.approval.freq": "On-demand", 154 | "governance.ops.audit.title": "Compliance Audit", 155 | "governance.ops.audit.desc": "Regular audit of open source compliance across all projects.", 156 | "governance.ops.audit.freq": "Quarterly", 157 | "governance.ops.report.title": "Executive Report", 158 | "governance.ops.report.desc": "Summary report on open source activities for leadership.", 159 | "governance.ops.report.freq": "Quarterly", 160 | "governance.details": "View Details", 161 | "governance.ops.workflow.title": "Standard Approval Workflow", 162 | "governance.ops.workflow.desc": "The process for getting open source usage or contribution approved", 163 | "governance.ops.step1": "Submit Request", 164 | "governance.ops.step2": "Initial Review", 165 | "governance.ops.step3": "Legal Review", 166 | "governance.ops.step4": "Security Scan", 167 | "governance.ops.step5": "Final Approval", 168 | 169 | // Resources page 170 | "resources.title": "Resource Center", 171 | "resources.subtitle": "Processes, guides, and success stories", 172 | "resources.processes.title": "Processes & Guides", 173 | "resources.cases.title": "Success Cases", 174 | "resources.processes.section": "Standard Processes", 175 | "resources.processes.desc": "Standard workflows for common open source activities.", 176 | "resources.guides.section": "Guides & Templates", 177 | "resources.guides.desc": "Helpful guides and templates to get you started.", 178 | "resources.process.contribution.title": "Contribution Workflow", 179 | "resources.process.contribution.desc": "Step-by-step process for contributing to open source projects.", 180 | "resources.process.license.title": "License Review Process", 181 | "resources.process.license.desc": "How to get approval for using new open source components.", 182 | "resources.process.release.title": "Project Release Process", 183 | "resources.process.release.desc": "Steps to release an internal project as open source.", 184 | "resources.process.security.title": "Security Review Process", 185 | "resources.process.security.desc": "Security assessment for open source components.", 186 | "resources.process.request.title": "Support Request Process", 187 | "resources.process.request.desc": "How to request OSPO support for your project.", 188 | "resources.process.incident.title": "Incident Response Process", 189 | "resources.process.incident.desc": "Handling compliance or security incidents.", 190 | "resources.guide.quickstart.title": "Quick Start Guide", 191 | "resources.guide.quickstart.desc": "Get started with open source contribution in your team.", 192 | "resources.guide.bestpractice.title": "Best Practices Guide", 193 | "resources.guide.bestpractice.desc": "Recommended practices for open source development.", 194 | "resources.guide.community.title": "Community Engagement Guide", 195 | "resources.guide.community.desc": "How to effectively participate in open source communities.", 196 | "resources.guide.cla.title": "CLA Template", 197 | "resources.guide.cla.desc": "Standard Contributor License Agreement template.", 198 | "resources.steps": "steps", 199 | "resources.view": "View", 200 | "resources.download": "Download", 201 | "resources.type.guide": "Guide", 202 | "resources.type.template": "Template", 203 | "resources.cases.desc": "Real success stories showcasing the impact of open source adoption.", 204 | "resources.case.department": "Department", 205 | "resources.case.impact.high": "High Impact", 206 | "resources.case.impact.medium": "Medium Impact", 207 | "resources.case.dept.cloud": "Cloud Infrastructure", 208 | "resources.case.dept.data": "Data Science", 209 | "resources.case.dept.eng": "Engineering", 210 | "resources.case.dept.support": "Customer Support", 211 | "resources.case.cloud.title": "Cloud Infrastructure Optimization", 212 | "resources.case.cloud.desc": "How our team leveraged open source tools to optimize cloud costs.", 213 | "resources.case.cloud.metric": "Cost Reduction", 214 | "resources.case.ml.title": "Machine Learning Pipeline", 215 | "resources.case.ml.desc": "Building an ML pipeline with open source frameworks.", 216 | "resources.case.ml.metric": "Dev Time Reduced", 217 | "resources.case.devtools.title": "Developer Productivity Tools", 218 | "resources.case.devtools.desc": "Internal tools built on open source that improved productivity.", 219 | "resources.case.devtools.metric": "Productivity Increase", 220 | "resources.case.support.title": "Customer Support Dashboard", 221 | "resources.case.support.desc": "Open source visualization tools that improved response time.", 222 | "resources.case.support.metric": "Response Time Improved", 223 | "resources.case.readmore": "Read Case Study", 224 | 225 | // Compliance page 226 | "compliance.title": "Compliance", 227 | "compliance.subtitle": "Open source license compliance management and governance", 228 | "compliance.tab.policy": "Policy", 229 | "compliance.tab.metrics": "Metrics", 230 | "compliance.tab.knowledge": "Knowledge Base", 231 | "compliance.tab.tools": "SCA Tools", 232 | "compliance.tab.supplyChain": "Supply Chain", 233 | "compliance.policy.overview": "Policy Overview", 234 | "compliance.policy.license.title": "License Compliance", 235 | "compliance.policy.license.desc": 236 | "Detailed organizational requirements for open source software license compliance, approval processes, and guidelines. Including license compatibility matrix and usage restrictions.", 237 | "compliance.policy.review.title": "Compliance Review Process", 238 | "compliance.policy.review.desc": 239 | "Standard process for introducing new open source components and updating existing ones, including necessary review steps and approval chain.", 240 | "compliance.policy.contacts.title": "Compliance Contacts", 241 | "compliance.policy.contacts.desc": "Compliance team contacts and on-call schedule for urgent compliance inquiries.", 242 | "compliance.contacts.title": "Compliance Contacts", 243 | "compliance.contacts.desc": "Contact our compliance team for urgent inquiries", 244 | "compliance.contacts.lead": "Compliance Lead", 245 | "compliance.contacts.leadRole": "Open Source Compliance Manager", 246 | "compliance.contacts.legal": "Legal Counsel", 247 | "compliance.contacts.legalRole": "IP & Open Source Legal Advisor", 248 | "compliance.metrics.scanned": "Components Scanned", 249 | "compliance.metrics.compliant": "Compliant Components", 250 | "compliance.metrics.issues": "Open Issues", 251 | "compliance.metrics.rate": "Compliance Rate", 252 | "compliance.metrics.distribution": "License Distribution", 253 | "compliance.metrics.distributionDesc": "Overview of open source licenses used across projects", 254 | "compliance.metrics.other": "Others", 255 | "compliance.kb.guides": "Compliance Guides", 256 | "compliance.kb.guide1": "Open Source License Guide", 257 | "compliance.kb.guide2": "License Compatibility Matrix", 258 | "compliance.kb.guide3": "SBOM Generation Guide", 259 | "compliance.kb.faqs": "Frequently Asked Questions", 260 | "compliance.kb.faq1": "How to request license review?", 261 | "compliance.kb.faq2": "What licenses are allowed?", 262 | "compliance.kb.faq3": "How to handle GPL dependencies?", 263 | "compliance.kb.training": "Training Materials", 264 | "compliance.kb.training1": "Open Source Compliance 101", 265 | "compliance.kb.training2": "License Identification Workshop", 266 | "compliance.kb.training3": "Advanced Compliance Certification", 267 | "compliance.tools.title": "SCA Tools", 268 | "compliance.tools.desc": "Software Composition Analysis tools for license and vulnerability scanning", 269 | "compliance.tools.blackduck": "Enterprise-grade open source management and compliance solution", 270 | "compliance.tools.snyk": "Developer-first security platform for vulnerability detection", 271 | "compliance.tools.fossa": "Automated open source license compliance and SBOM management", 272 | "compliance.tools.whitesource": "Open source security and license compliance management", 273 | "compliance.tools.active": "Active", 274 | "compliance.tools.evaluation": "Evaluation", 275 | "compliance.tools.integration": "Tool Integration Status", 276 | "compliance.tools.cicd": "CI/CD Pipeline Integration", 277 | "compliance.tools.repo": "Repository Scanning", 278 | "compliance.tools.sbom": "SBOM Auto-generation", 279 | "compliance.tools.configured": "Configured", 280 | "compliance.tools.inProgress": "In Progress", 281 | 282 | // Supply Chain 283 | "compliance.supplyChain.title": "Open Source Software Supply Chain", 284 | "compliance.supplyChain.desc": "Health assessment and risk analysis of open source software supply chain", 285 | "compliance.supplyChain.overallHealth": "Overall Health", 286 | "compliance.supplyChain.security": "Security", 287 | "compliance.supplyChain.securityDesc": "Vulnerability detection and security update status", 288 | "compliance.supplyChain.maintenance": "Maintenance", 289 | "compliance.supplyChain.maintenanceDesc": "Project activity and maintenance frequency", 290 | "compliance.supplyChain.community": "Community", 291 | "compliance.supplyChain.communityDesc": "Community activity and contributor diversity", 292 | "compliance.supplyChain.license": "License Compliance", 293 | "compliance.supplyChain.licenseDesc": "License compliance and risk assessment", 294 | "compliance.supplyChain.quality": "Code Quality", 295 | "compliance.supplyChain.qualityDesc": "Code quality metrics and test coverage", 296 | "compliance.supplyChain.riskTitle": "Risk Distribution", 297 | "compliance.supplyChain.highRisk": "High Risk Components", 298 | "compliance.supplyChain.highRiskDesc": "Critical vulnerabilities or license issues", 299 | "compliance.supplyChain.mediumRisk": "Medium Risk Components", 300 | "compliance.supplyChain.mediumRiskDesc": "Moderate risks requiring attention", 301 | "compliance.supplyChain.lowRisk": "Low Risk Components", 302 | "compliance.supplyChain.lowRiskDesc": "Healthy components with no significant issues", 303 | 304 | // Footer 305 | "footer.copyright": "© 2025 OSPO. All rights reserved.", 306 | "footer.contact": "Contact Us", 307 | "footer.sourceCode": "Source Code", 308 | }, 309 | zh: { 310 | // Navigation 311 | "nav.home": "首页", 312 | "nav.capabilities": "能力建设", 313 | "nav.projects": "项目列表", 314 | "nav.governance": "治理政策", 315 | "nav.resources": "资源中心", 316 | "nav.compliance": "开源合规", 317 | 318 | // Home page 319 | "home.title": "开源项目办公室", 320 | "home.subtitle": "通过开源协作推动创新", 321 | "home.vision.title": "我们的愿景", 322 | "home.vision.content": "建立蓬勃发展的开源文化,推动整个组织的创新、协作和技术卓越。", 323 | "home.mission.title": "我们的使命", 324 | "home.mission.content": "在整个组织中支持开源采用、贡献和合规,同时与更广泛的开源社区建立协作生态系统。", 325 | "home.responsibilities.title": "主要职责", 326 | "home.responsibilities.item1": "开源战略与治理", 327 | "home.responsibilities.item2": "许可证合规与风险管理", 328 | "home.responsibilities.item3": "社区参与与贡献", 329 | "home.responsibilities.item4": "开发者教育与赋能", 330 | "home.responsibilities.item5": "项目孵化与维护", 331 | "home.team.title": "我们的团队", 332 | "home.team.director": "OSPO 主管", 333 | "home.team.manager": "项目经理", 334 | "home.team.engineer": "开源工程师", 335 | "home.team.legal": "法律顾问", 336 | "home.team.developer": "开发者倡导者", 337 | "home.links.title": "重要链接", 338 | "home.links.internal": "内部资源", 339 | "home.links.external": "外部资源", 340 | 341 | // Capabilities page 342 | "capabilities.title": "开源能力建设", 343 | "capabilities.subtitle": "构建开源实践卓越能力", 344 | "capabilities.progress": "进度", 345 | "capabilities.nav.title": "快速导航", 346 | "capabilities.governance.title": "开源治理", 347 | "capabilities.governance.desc": "建立开源使用和贡献的政策、流程和指南", 348 | "capabilities.education.title": "开发者教育", 349 | "capabilities.education.desc": "为开发者提供开源最佳实践的培训和资源", 350 | "capabilities.contribution.title": "贡献策略", 351 | "capabilities.contribution.desc": "对外部开源项目贡献的战略方法", 352 | "capabilities.innersource.title": "内源计划", 353 | "capabilities.innersource.desc": "将开源原则应用于内部开发", 354 | "capabilities.security.title": "安全与合规", 355 | "capabilities.security.desc": "确保开源使用中的安全性和法律合规", 356 | "capabilities.milestones": "里程碑", 357 | "capabilities.status.completed": "已完成", 358 | "capabilities.status.inProgress": "进行中", 359 | "capabilities.status.planned": "计划中", 360 | "capabilities.milestone.policyFramework": "政策框架", 361 | "capabilities.milestone.governanceCommittee": "治理委员会", 362 | "capabilities.milestone.complianceTooling": "合规工具", 363 | "capabilities.milestone.auditProcess": "审计流程", 364 | "capabilities.milestone.basicTraining": "基础培训", 365 | "capabilities.milestone.advancedWorkshops": "高级研讨会", 366 | "capabilities.milestone.certificationProgram": "认证计划", 367 | "capabilities.milestone.mentorshipProgram": "导师计划", 368 | "capabilities.milestone.contributionGuidelines": "贡献指南", 369 | "capabilities.milestone.projectSelectionFramework": "项目选择框架", 370 | "capabilities.milestone.contributionMetrics": "贡献指标", 371 | "capabilities.milestone.communityLeadership": "社区领导力", 372 | "capabilities.milestone.innersourceGuidelines": "内源指南", 373 | "capabilities.milestone.pilotProjects": "试点项目", 374 | "capabilities.milestone.toolingInfrastructure": "工具与基础设施", 375 | "capabilities.milestone.organizationRollout": "全组织推广", 376 | "capabilities.milestone.securityScanning": "安全扫描", 377 | "capabilities.milestone.licenseCompliance": "许可证合规", 378 | "capabilities.milestone.vulnerabilityManagement": "漏洞管理", 379 | "capabilities.milestone.automatedCompliance": "自动化合规", 380 | 381 | // Projects page 382 | "projects.title": "开源项目", 383 | "projects.subtitle": "我们对开源生态系统的贡献", 384 | "projects.internal": "内部开源项目", 385 | "projects.internal.desc": "组织内部使用的开源项目,未对外公开发布。", 386 | "projects.external": "参与外部贡献", 387 | "projects.external.desc": "我们对外部开源项目和社区的贡献。", 388 | "projects.public": "对外开源项目", 389 | "projects.public.desc": "我们组织对外公开发布的开源项目,供社区使用。", 390 | "projects.status": "状态", 391 | "projects.active": "活跃", 392 | "projects.maintenance": "维护中", 393 | "projects.incubating": "孵化中", 394 | "projects.repo": "仓库", 395 | "projects.maintainers": "维护者", 396 | "projects.contributors": "贡献者", 397 | "projects.contribution": "贡献内容", 398 | "projects.merged": "已合并", 399 | "projects.forks": "Fork数", 400 | 401 | // Governance page 402 | "governance.title": "治理政策", 403 | "governance.subtitle": "开源治理框架、政策与组织架构", 404 | "governance.tab.policies": "政策制度", 405 | "governance.tab.organization": "组织架构", 406 | "governance.tab.operations": "运作方式", 407 | "governance.policies.desc": "管理组织内开源活动的综合政策。", 408 | "governance.policy.overall.title": "开源总体政策", 409 | "governance.policy.overall.desc": "定义我们对开源软件使用、贡献和发布方法的基础性政策。", 410 | "governance.policy.contribution.title": "贡献政策", 411 | "governance.policy.contribution.desc": "向外部开源项目贡献代码的指南和要求。", 412 | "governance.policy.usage.title": "使用政策", 413 | "governance.policy.usage.desc": "评估、审批和在产品中使用开源组件的标准。", 414 | "governance.policy.ip.title": "知识产权管理", 415 | "governance.policy.ip.desc": "开源活动相关的知识产权考量和CLA要求。", 416 | "governance.updated": "更新日期", 417 | "governance.view": "查看政策", 418 | "governance.org.desc": "支持开源治理和运营的组织架构。", 419 | "governance.org.committee": "开源治理委员会", 420 | "governance.org.committee.desc": "为开源计划提供高管级别的监督和战略方向。", 421 | "governance.org.ospo": "开源项目办公室", 422 | "governance.org.ospo.desc": "负责实施和管理开源项目的核心团队。", 423 | "governance.org.ambassadors": "开源大使", 424 | "governance.org.ambassadors.desc": "在各团队推广开源最佳实践的代表。", 425 | "governance.org.chart.title": "组织架构图", 426 | "governance.org.chart.desc": "开源治理的层级结构", 427 | "governance.org.compliance": "合规团队", 428 | "governance.org.community": "社区团队", 429 | "governance.org.engineering": "工程支持", 430 | "governance.ops.desc": "开源治理的常规运作和工作流程。", 431 | "governance.ops.review.title": "月度审查会议", 432 | "governance.ops.review.desc": "定期审查开源活动、指标和问题。", 433 | "governance.ops.review.freq": "每月", 434 | "governance.ops.approval.title": "项目审批流程", 435 | "governance.ops.approval.desc": "审批新开源使用或贡献的工作流程。", 436 | "governance.ops.approval.freq": "按需", 437 | "governance.ops.audit.title": "合规审计", 438 | "governance.ops.audit.desc": "定期审计所有项目的开源合规情况。", 439 | "governance.ops.audit.freq": "每季度", 440 | "governance.ops.report.title": "高管报告", 441 | "governance.ops.report.desc": "向领导层汇报开源活动的总结报告。", 442 | "governance.ops.report.freq": "每季度", 443 | "governance.details": "查看详情", 444 | "governance.ops.workflow.title": "标准审批流程", 445 | "governance.ops.workflow.desc": "获得开源使用或贡献批准的流程", 446 | "governance.ops.step1": "提交申请", 447 | "governance.ops.step2": "初步审核", 448 | "governance.ops.step3": "法务审核", 449 | "governance.ops.step4": "安全扫描", 450 | "governance.ops.step5": "最终审批", 451 | 452 | // Resources page 453 | "resources.title": "资源中心", 454 | "resources.subtitle": "流程、指南和成功案例", 455 | "resources.processes.title": "流程与指南", 456 | "resources.cases.title": "成功案例", 457 | "resources.processes.section": "标准流程", 458 | "resources.processes.desc": "常见开源活动的标准工作流程。", 459 | "resources.guides.section": "指南与模板", 460 | "resources.guides.desc": "帮助您快速入门的有用指南和模板。", 461 | "resources.process.contribution.title": "贡献工作流", 462 | "resources.process.contribution.desc": "向开源项目贡献代码的逐步流程。", 463 | "resources.process.license.title": "许可证审查流程", 464 | "resources.process.license.desc": "如何获得使用新开源组件的批准。", 465 | "resources.process.release.title": "项目发布流程", 466 | "resources.process.release.desc": "将内部项目作为开源发布的步骤。", 467 | "resources.process.security.title": "安全审查流程", 468 | "resources.process.security.desc": "开源组件的安全评估流程。", 469 | "resources.process.request.title": "支持请求流程", 470 | "resources.process.request.desc": "如何为您的项目申请OSPO支持。", 471 | "resources.process.incident.title": "事件响应流程", 472 | "resources.process.incident.desc": "处理合规或安全事件的流程。", 473 | "resources.guide.quickstart.title": "快速入门指南", 474 | "resources.guide.quickstart.desc": "在您的团队中开始开源贡献。", 475 | "resources.guide.bestpractice.title": "最佳实践指南", 476 | "resources.guide.bestpractice.desc": "开源开发的推荐实践。", 477 | "resources.guide.community.title": "社区参与指南", 478 | "resources.guide.community.desc": "如何有效参与开源社区。", 479 | "resources.guide.cla.title": "CLA模板", 480 | "resources.guide.cla.desc": "标准贡献者许可协议模板。", 481 | "resources.steps": "步骤", 482 | "resources.view": "查看", 483 | "resources.download": "下载", 484 | "resources.type.guide": "指南", 485 | "resources.type.template": "模板", 486 | "resources.cases.desc": "展示开源采用影响力的真实成功案例。", 487 | "resources.case.department": "部门", 488 | "resources.case.impact.high": "高影响力", 489 | "resources.case.impact.medium": "中等影响力", 490 | "resources.case.dept.cloud": "云基础设施", 491 | "resources.case.dept.data": "数据科学", 492 | "resources.case.dept.eng": "工程团队", 493 | "resources.case.dept.support": "客户支持", 494 | "resources.case.cloud.title": "云基础设施优化", 495 | "resources.case.cloud.desc": "团队如何利用开源工具优化云成本。", 496 | "resources.case.cloud.metric": "成本降低", 497 | "resources.case.ml.title": "机器学习流水线", 498 | "resources.case.ml.desc": "使用开源框架构建ML流水线。", 499 | "resources.case.ml.metric": "开发时间减少", 500 | "resources.case.devtools.title": "开发者生产力工具", 501 | "resources.case.devtools.desc": "基于开源构建的内部工具提升了生产力。", 502 | "resources.case.devtools.metric": "生产力提升", 503 | "resources.case.support.title": "客户支持仪表板", 504 | "resources.case.support.desc": "开源可视化工具提高了响应时间。", 505 | "resources.case.support.metric": "响应时间改善", 506 | "resources.case.readmore": "阅读案例", 507 | 508 | // Compliance page 509 | "compliance.title": "开源合规", 510 | "compliance.subtitle": "开源许可证合规管理与治理", 511 | "compliance.tab.policy": "政策", 512 | "compliance.tab.metrics": "指标", 513 | "compliance.tab.knowledge": "知识库", 514 | "compliance.tab.tools": "SCA工具", 515 | "compliance.tab.supplyChain": "供应链", 516 | "compliance.policy.overview": "政策概览", 517 | "compliance.policy.license.title": "许可证合规", 518 | "compliance.policy.license.desc": 519 | "组织对开源软件许可证合规的详细要求、审批流程和指南,包括许可证兼容性矩阵和使用限制。", 520 | "compliance.policy.review.title": "合规审查流程", 521 | "compliance.policy.review.desc": "引入新开源组件和更新现有组件的标准流程,包括必要的审查步骤和审批链。", 522 | "compliance.policy.contacts.title": "合规联系人", 523 | "compliance.policy.contacts.desc": "合规团队联系方式及紧急合规咨询值班安排。", 524 | "compliance.contacts.title": "合规联系人", 525 | "compliance.contacts.desc": "如有紧急咨询请联系合规团队", 526 | "compliance.contacts.lead": "合规负责人", 527 | "compliance.contacts.leadRole": "开源合规经理", 528 | "compliance.contacts.legal": "法律顾问", 529 | "compliance.contacts.legalRole": "知识产权与开源法律顾问", 530 | "compliance.metrics.scanned": "已扫描组件", 531 | "compliance.metrics.compliant": "合规组件", 532 | "compliance.metrics.issues": "待处理问题", 533 | "compliance.metrics.rate": "合规率", 534 | "compliance.metrics.distribution": "许可证分布", 535 | "compliance.metrics.distributionDesc": "项目中使用的开源许可证概览", 536 | "compliance.metrics.other": "其他", 537 | "compliance.kb.guides": "合规指南", 538 | "compliance.kb.guide1": "开源许可证指南", 539 | "compliance.kb.guide2": "许可证兼容性矩阵", 540 | "compliance.kb.guide3": "SBOM生成指南", 541 | "compliance.kb.faqs": "常见问题", 542 | "compliance.kb.faq1": "如何申请许可证审查?", 543 | "compliance.kb.faq2": "哪些许可证是允许使用的?", 544 | "compliance.kb.faq3": "如何处理GPL依赖?", 545 | "compliance.kb.training": "培训材料", 546 | "compliance.kb.training1": "开源合规入门", 547 | "compliance.kb.training2": "许可证识别工作坊", 548 | "compliance.kb.training3": "高级合规认证", 549 | "compliance.tools.title": "SCA工具", 550 | "compliance.tools.desc": "用于许可证和漏洞扫描的软件成分分析工具", 551 | "compliance.tools.blackduck": "企业级开源管理和合规解决方案", 552 | "compliance.tools.snyk": "面向开发者的安全平台,用于漏洞检测", 553 | "compliance.tools.fossa": "自动化开源许可证合规和SBOM管理", 554 | "compliance.tools.whitesource": "开源安全和许可证合规管理", 555 | "compliance.tools.active": "使用中", 556 | "compliance.tools.evaluation": "评估中", 557 | "compliance.tools.integration": "工具集成状态", 558 | "compliance.tools.cicd": "CI/CD 流水线集成", 559 | "compliance.tools.repo": "代码仓库扫描", 560 | "compliance.tools.sbom": "SBOM 自动生成", 561 | "compliance.tools.configured": "已配置", 562 | "compliance.tools.inProgress": "进行中", 563 | 564 | // Supply Chain 565 | "compliance.supplyChain.title": "开源软件供应链", 566 | "compliance.supplyChain.desc": "开源软件供应链健康度评估和风险分析", 567 | "compliance.supplyChain.overallHealth": "整体健康度", 568 | "compliance.supplyChain.security": "安全性", 569 | "compliance.supplyChain.securityDesc": "漏洞检测和安全更新状态", 570 | "compliance.supplyChain.maintenance": "维护性", 571 | "compliance.supplyChain.maintenanceDesc": "项目活跃度和维护频率", 572 | "compliance.supplyChain.community": "社区活跃度", 573 | "compliance.supplyChain.communityDesc": "社区活跃度和贡献者多样性", 574 | "compliance.supplyChain.license": "许可证合规", 575 | "compliance.supplyChain.licenseDesc": "许可证合规性和风险评估", 576 | "compliance.supplyChain.quality": "代码质量", 577 | "compliance.supplyChain.qualityDesc": "代码质量指标和测试覆盖率", 578 | "compliance.supplyChain.riskTitle": "风险分布", 579 | "compliance.supplyChain.highRisk": "高风险组件", 580 | "compliance.supplyChain.highRiskDesc": "存在严重漏洞或许可证问题", 581 | "compliance.supplyChain.mediumRisk": "中风险组件", 582 | "compliance.supplyChain.mediumRiskDesc": "存在需要关注的中等风险", 583 | "compliance.supplyChain.lowRisk": "低风险组件", 584 | "compliance.supplyChain.lowRiskDesc": "健康组件,无重大问题", 585 | 586 | // Footer 587 | "footer.copyright": "© 2025 OSPO. 保留所有权利。", 588 | "footer.contact": "联系我们", 589 | "footer.sourceCode": "源代码", 590 | }, 591 | } 592 | 593 | export function LanguageProvider({ children }: { children: React.ReactNode }) { 594 | const [language, setLanguage] = useState("zh") 595 | 596 | useEffect(() => { 597 | const savedLanguage = localStorage.getItem("language") as Language 598 | if (savedLanguage && (savedLanguage === "en" || savedLanguage === "zh")) { 599 | setLanguage(savedLanguage) 600 | } else { 601 | const browserLang = navigator.language.split("-")[0] 602 | if (browserLang === "zh") { 603 | setLanguage("zh") 604 | } 605 | } 606 | }, []) 607 | 608 | const handleSetLanguage = (newLanguage: Language) => { 609 | setLanguage(newLanguage) 610 | localStorage.setItem("language", newLanguage) 611 | } 612 | 613 | const t = (key: TranslationKey): string => { 614 | return translations[language][key as keyof (typeof translations)[typeof language]] || key 615 | } 616 | 617 | return ( 618 | 619 | {children} 620 | 621 | ) 622 | } 623 | 624 | export const useLanguage = () => { 625 | const context = useContext(LanguageContext) 626 | if (context === undefined) { 627 | throw new Error("useLanguage must be used within a LanguageProvider") 628 | } 629 | return context 630 | } 631 | --------------------------------------------------------------------------------