GenCN UI

Detect Language

Component that automatically detects the language of text and renders it.

Try out the component below to see how it automatically detects and displays the language of text.

Loading preview...
"use client";

import { useState } from "react";
import { GencnUIDetectLanguage } from "@/registry/new-york/gencn-ui/items/detect-language/gencn-ui-detect-language";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";

export function GencnUIDetectLanguageExample() {
  const [inputText, setInputText] = useState("Bonjour, comment allez-vous?");
  
  const sampleTexts = [
    { text: "Hello, how are you?", label: "English" },
    { text: "Bonjour, comment allez-vous?", label: "French" },
    { text: "Hola, ¿cómo estás?", label: "Spanish" },
    { text: "Guten Tag, wie geht es dir?", label: "German" },
    { text: "Ciao, come stai?", label: "Italian" },
    { text: "こんにちは、元気ですか?", label: "Japanese" },
  ];

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>
          <CardTitle>Detect Language</CardTitle>
          <CardDescription>
            Automatically detect the language of text and display it.
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="detect-text">Enter text to detect language</Label>
            <Textarea
              id="detect-text"
              placeholder="Type text in any language..."
              rows={3}
              value={inputText}
              onChange={(e) => setInputText(e.target.value)}
            />
            <div className="mt-2">
              <GencnUIDetectLanguage
                text={inputText}
                loading={<Badge variant="outline">Detecting...</Badge>}
                error={<Badge variant="destructive">Error</Badge>}
                render={(language, confidence) => (
                  <Badge variant="secondary">
                    {language} ({Math.round(confidence * 100)}%)
                  </Badge>
                )}
              />
            </div>
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Multiple Examples</CardTitle>
          <CardDescription>
            Language detection for different languages
          </CardDescription>
        </CardHeader>
        <CardContent>
          <div className="space-y-4">
            {sampleTexts.map((sample, index) => (
              <div key={index} className="flex items-center gap-4">
                <div className="flex-1">
                  <p className="text-sm font-medium">{sample.label}</p>
                  <p className="text-sm text-muted-foreground">{sample.text}</p>
                </div>
                <GencnUIDetectLanguage
                  text={sample.text}
                  loading={<Badge variant="outline">...</Badge>}
                  error={<Badge variant="destructive">?</Badge>}
                  render={(language, confidence) => (
                    <Badge variant="secondary">
                      {language}
                    </Badge>
                  )}
                />
              </div>
            ))}
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Custom Rendering</CardTitle>
          <CardDescription>
            Customize how the detected language is displayed
          </CardDescription>
        </CardHeader>
        <CardContent>
          <div className="space-y-2">
            <p className="text-sm text-muted-foreground">
              "The quick brown fox jumps over the lazy dog"
            </p>
            <GencnUIDetectLanguage
              text="The quick brown fox jumps over the lazy dog"
              render={(language, confidence) => (
                <div className="flex items-center gap-2">
                  <span className="text-sm">Language:</span>
                  <Badge>{language}</Badge>
                  <span className="text-xs text-muted-foreground">
                    Confidence: {Math.round(confidence * 100)}%
                  </span>
                </div>
              )}
            />
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

Server API

No server API required - this component uses client-side APIs only.

Installation

Setup Required: Make sure you have configured components.json first. See the installation guide for setup instructions.

npx shadcn@latest add @gencn-ui/gencn-ui-detect-language
"use client";

import { useState, useEffect, type ReactNode } from "react";
import { useLanguageDetector } from "@/registry/new-york/gencn-ui/items/shared/hooks/internal/use-gencn-ui-language-detector";
import type { UseLanguageDetectorOptions } from "@/registry/new-york/gencn-ui/items/shared/hooks/internal/use-gencn-ui-language-detector";

export interface GencnUIDetectLanguageProps {
  /**
   * Text string to detect the language of
   */
  text: string;

  /**
   * Language detector options (fallback configuration)
   */
  options?: UseLanguageDetectorOptions;

  /**
   * Component to render while detecting language
   */
  loading?: ReactNode;

  /**
   * Component to render when language detection fails
   */
  error?: ReactNode | ((error: Error) => ReactNode);

  /**
   * Custom render function for the detected language
   * @param language - The detected language code (e.g., "en", "fr", "es")
   * @param confidence - The confidence score (0-1)
   * @returns React node to render
   */
  render?: (language: string, confidence: number) => ReactNode;

  /**
   * Additional className for the container
   */
  className?: string;
}

/**
 * GencnUIDetectLanguage component detects the language of the provided text
 * and renders it using the specified render function or default rendering.
 * 
 * Supports multiple fallback methods: browser API, tinyld, and server API.
 * 
 * @example
 * ```tsx
 * <GencnUIDetectLanguage text="Bonjour, comment allez-vous?" />
 * ```
 * 
 * @example
 * ```tsx
 * <GencnUIDetectLanguage 
 *   text="Hello, world!"
 *   render={(language, confidence) => (
 *     <span>Detected: {language} ({Math.round(confidence * 100)}%)</span>
 *   )}
 * />
 * ```
 */
export function GencnUIDetectLanguage({
  text,
  options,
  loading,
  error,
  render,
  className,
}: GencnUIDetectLanguageProps) {
  const { generate, isLoading, data, error: hookError } = useLanguageDetector(options);
  const [detectedLanguage, setDetectedLanguage] = useState<string | null>(null);
  const [confidence, setConfidence] = useState<number | null>(null);
  const [detectionError, setDetectionError] = useState<Error | null>(null);

  useEffect(() => {
    // Reset state when text changes
    setDetectedLanguage(null);
    setConfidence(null);
    setDetectionError(null);

    // Skip detection if text is empty
    if (!text.trim()) {
      return;
    }

    // Detect language using generate
    generate({ text, fallback: options?.fallback })
      .then((results) => {
        if (results && results.length > 0) {
          setDetectedLanguage(results[0].detectedLanguage);
          setConfidence(results[0].confidence);
        } else {
          setDetectionError(new Error("No language detected"));
        }
      })
      .catch((err) => {
        setDetectionError(err instanceof Error ? err : new Error(String(err)));
      });
  }, [text, generate, options?.fallback]);

  // Use hook's loading and error state
  const isDetecting = isLoading;
  useEffect(() => {
    if (hookError) {
      setDetectionError(new Error(hookError));
    } else if (data && data.length > 0) {
      setDetectedLanguage(data[0].detectedLanguage);
      setConfidence(data[0].confidence);
      setDetectionError(null);
    }
  }, [data, hookError]);

  // Show loading state
  if (isDetecting) {
    return <>{loading || <span className={className}>Detecting language...</span>}</>;
  }

  // Show error state
  if (detectionError) {
    if (typeof error === "function") {
      return <>{error(detectionError)}</>;
    }
    return <>{error || <span className={className}>Failed to detect language</span>}</>;
  }

  // Show detected language
  if (detectedLanguage !== null && confidence !== null) {
    if (render) {
      return <>{render(detectedLanguage, confidence)}</>;
    }
    // Default rendering
    return (
      <span className={className}>
        {detectedLanguage}
      </span>
    );
  }

  // No text provided
  return null;
}

Component API