main c033d7971ec9 cached
83 files
215.1 KB
62.2k tokens
51 symbols
1 requests
Download .txt
Showing preview only (251K chars total). Download the full file or copy to clipboard to get everything.
Repository: LeonZeng919/barcode-generator
Branch: main
Commit: c033d7971ec9
Files: 83
Total size: 215.1 KB

Directory structure:
gitextract_ngu74d31/

├── .eslintrc.json
├── .gitignore
├── .husky/
│   └── pre-commit
├── .prettierrc
├── LICENSE
├── README.md
├── components.json
├── messages/
│   ├── de.json
│   ├── en.json
│   ├── es.json
│   ├── fr.json
│   ├── it.json
│   ├── ja.json
│   ├── ko.json
│   ├── nl.json
│   ├── ru.json
│   ├── sv.json
│   └── zh.json
├── next-sitemap.config.js
├── next.config.mjs
├── package.json
├── postcss.config.js
├── public/
│   ├── ads.txt
│   ├── robots.txt
│   ├── site.webmanifest
│   ├── sitemap-0.xml
│   └── sitemap.xml
├── src/
│   ├── app/
│   │   ├── [locale]/
│   │   │   ├── [barcodeType]/
│   │   │   │   └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   └── terms/
│   │   │       └── page.tsx
│   │   ├── api/
│   │   │   └── barcode/
│   │   │       └── [code]/
│   │   │           └── [data]/
│   │   │               └── route.ts
│   │   ├── error.tsx
│   │   ├── layout.tsx
│   │   └── not-found.tsx
│   ├── components/
│   │   ├── Header.tsx
│   │   ├── MarkdownContent.tsx
│   │   ├── barcode-generator/
│   │   │   ├── BarcodeCarousel.tsx
│   │   │   ├── BarcodeComponents.tsx
│   │   │   ├── BarcodeContext.tsx
│   │   │   ├── DownloadBarcodes.tsx
│   │   │   ├── ImportData.tsx
│   │   │   ├── ScrollControls.tsx
│   │   │   ├── index.tsx
│   │   │   ├── share-button.tsx
│   │   │   └── useBarcodeGenerator.tsx
│   │   ├── footer.tsx
│   │   ├── icons.tsx
│   │   ├── language-toggle.tsx
│   │   ├── tailwind-indicator.tsx
│   │   ├── theme-provider.tsx
│   │   ├── theme-toggle.tsx
│   │   └── ui/
│   │       ├── button.tsx
│   │       ├── card.tsx
│   │       ├── carousel.tsx
│   │       ├── dialog.tsx
│   │       ├── dropdown-menu.tsx
│   │       ├── input.tsx
│   │       ├── label.tsx
│   │       ├── radio-group.tsx
│   │       ├── resizable.tsx
│   │       ├── scroll-area.tsx
│   │       ├── select.tsx
│   │       ├── separator.tsx
│   │       ├── sheet.tsx
│   │       ├── slider.tsx
│   │       ├── switch.tsx
│   │       ├── tabs.tsx
│   │       ├── textarea.tsx
│   │       └── tooltip.tsx
│   ├── config/
│   │   ├── barcode-types.ts
│   │   └── site-i18n.ts
│   ├── i18n.ts
│   ├── lib/
│   │   ├── fonts.ts
│   │   ├── parseLine.ts
│   │   └── utils.ts
│   ├── middleware.ts
│   ├── navigation.ts
│   ├── styles/
│   │   └── globals.css
│   └── types/
│       ├── image.ts
│       └── nav.ts
├── tailwind.config.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintrc.json
================================================
{
  "extends": "next/core-web-vitals"
}


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts


================================================
FILE: .husky/pre-commit
================================================
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0

# Prettify all selected files
echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write --config .prettierrc 
npm run lint --lint-staged --fix 

# Add back the modified/prettified files to staging
echo "$FILES" | xargs git add

exit 0


================================================
FILE: .prettierrc
================================================
{
  "singleQuote": true,
  "semi": false,
  "plugins": ["prettier-plugin-tailwindcss"],
  "tabWidth": 2,
  "printWidth": 80
}


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2024 Leon Zeng

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Barcode Generator

![Barcode Generator Logo](https://barcode-maker.com/apple-touch-icon.png)

Barcode Generator is a free, open-source tool that allows users to easily create various formats of one-dimensional barcodes. It supports multiple encoding types and enables users to generate barcodes in real-time and in bulk, completely free of charge.

This project is based on the [next-shadcn-intl-template](https://github.com/LeonZeng919/next-shadcn-intl-template).

Live demo: [https://barcode-maker.com](https://barcode-maker.com)

## Features

- Support for multiple barcode formats (Code 128, EAN/UPC, Code 39, ITF, MSI Plessey, Pharmacode, Codabar)
- Real-time barcode generation
- Bulk generation capability
- Customizable barcode styles
- Download options (PNG, JPG, GIF, SVG)
- Mobile-friendly design
- Internationalization support

## Getting Started

### Prerequisites

- Node.js (version 12 or higher)
- npm (usually comes with Node.js)

### Installation

1. Clone the repository:

   ```
   git clone https://github.com/LeonZeng919/barcode-generator.git
   ```

2. Navigate to the project directory:

   ```
   cd barcode-generator
   ```

3. Install dependencies:

   ```
   npm install
   ```

4. Start the development server:

   ```
   npm run dev
   ```

5. Open your browser and visit `http://localhost:3000`.

## Usage

1. Enter the content you want to encode in the input box, with each line corresponding to one barcode.
2. Use the tabs to switch between different encoding types.
3. Select the encoding format and barcode style in the options.
4. The system will generate the corresponding barcodes in real-time.

For more detailed usage instructions, please refer to our [FAQ](https://barcode-maker.com).

## Contributing

We welcome contributions from the community! If you'd like to contribute, please follow these steps:

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

Please make sure to update tests as appropriate and adhere to the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Acknowledgments

- [JsBarcode](https://github.com/lindell/JsBarcode) - The barcode generation library used in this project
- [next-shadcn-intl-template](https://github.com/LeonZeng919/next-shadcn-intl-template) - The template used as a base for this project
- All contributors who have helped to improve this project

## Contact

Leon Zeng - [@leonzeng2024](https://x.com/leonzeng2024)

Project Link: [https://github.com/LeonZeng919/barcode-generator](https://github.com/LeonZeng919/barcode-generator)

## Recommended AI Tools

- [AIImageEdit.ai](https://aiimageedit.ai) - World's best AI Image Editor
- [AI Face Swaps](https://aifaceswaps.app) - Free online AI face swap tool
- [Spin the Wheel](https://spin-the-wheel.ai/) - Free online spin the wheel random picker with AI auto-generated wheels


================================================
FILE: components.json
================================================
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "src/app/globals.css",
    "baseColor": "gray",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}


================================================
FILE: messages/de.json
================================================
{
  "Index": {
    "title": "Der kostenlose Barcode-Generator ist ein Online-Tool, mit dem Benutzer einfach verschiedene Formate von Barcodes und QR-Codes erstellen können. Es unterstützt mehrere Codierungstypen und ermöglicht Benutzern, Barcodes in Echtzeit und in großen Mengen völlig kostenlos zu generieren."
  },
  "Barcode": {
    "title": "Kostenloser {type} Barcode-Generator",
    "input": {
      "title": "Barcode-Werte (einer pro Zeile)",
      "placeholder": "Werte eingeben, einen pro Zeile",
      "caption-hint": "Um benutzerdefinierten Text unter dem Barcode anzuzeigen: Drücken Sie nach jedem Wert die Tab-Taste und geben Sie Ihren Text ein. Oder kopieren Sie 2 Spalten aus Excel (Barcode-Wert | Anzeigetext) und fügen Sie sie direkt ein."
    },
    "options": {
      "name": "Optionen",
      "code-format": "Code-Format",
      "show-text": "Text anzeigen",
      "show-yes": "Ja",
      "show-no": "Nein",
      "barcode-length": "Barcode-Länge (mm)",
      "barcode-height": "Barcode-Höhe (mm)",
      "barcode-margin": "Barcode-Rand (mm)",
      "locked-aspect-ratio": "Die Höhe ist für 2D-Barcodes auf die Breite gesperrt."
    },
    "select-format": {
      "name": "Barcode-Format auswählen",
      "search-placeholder": "Barcode-Format eingeben..."
    },
    "output": {
      "title": "Ausgabe"
    },
    "layout": {
      "name": "Drucklayout",
      "1x2": "1 Spalte drucken",
      "2x3": "2 Spalten drucken",
      "3x4": "3 Spalten drucken",
      "4x5": "4 Spalten drucken"
    }
  },
  "scroll": {
    "to-top": "Nach oben",
    "setting": "Scrollgeschwindigkeit einstellen",
    "start-scroll": "Scrollen starten",
    "pause-scroll": "Scrollen pausieren"
  },
  "content": {
    "faq": "# Kostenloser Barcode-Generator FAQ\n\n## 1. Was ist der kostenlose Barcode-Generator?\n\nDer kostenlose Barcode-Generator ist ein Open-Source-Online-Tool, mit dem Benutzer einfach verschiedene Formate von eindimensionalen Barcodes erstellen können. Es unterstützt mehrere Codierungstypen und ermöglicht Benutzern, Barcodes in Echtzeit und in großen Mengen völlig kostenlos zu generieren.\n\n## 2. Wie benutze ich diesen Barcode-Generator?\n\nDie Verwendung ist sehr einfach:\n- Geben Sie den zu codierenden Inhalt in das Eingabefeld ein, wobei jede Zeile einem Barcode entspricht.\n- Verwenden Sie die Registerkarten, um zwischen verschiedenen Codierungstypen zu wechseln (wie Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Wählen Sie in den Optionen das Codierungsformat und den Barcode-Stil aus.\n- Das System generiert den entsprechenden Barcode in Echtzeit.\n\n## 3. Welche Arten von Barcodes unterstützt dieses Tool?\n\nUnser Tool unterstützt verschiedene gängige Barcode-Formate, darunter:\n- Code128 (einschließlich Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (einschließlich EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (einschließlich Code39, Code39 Extended)\n- ITF (einschließlich ITF-14)\n- MSI Plessey (einschließlich Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (einschließlich Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (einschließlich ISBN, ISMN, ISSN)\n\n2D-Barcode-Formate, darunter:\n- QR Code\n- Data Matrix\n- PDF417\n- Aztec Code\n\n## 4. Kann ich mehrere Barcodes auf einmal generieren?\n\nJa, dieses Tool unterstützt die Massengenerierung. Sie müssen nur einen Barcode-Inhalt pro Zeile in das Eingabefeld eingeben, und das System generiert für jede Zeile einen entsprechenden Barcode. Für massenweise generierte Barcodes können Sie auf die Schaltfläche \"Scrollen starten\" in der unteren rechten Ecke klicken, und die Seite scrollt automatisch, um alle generierten Barcodes anzuzeigen. Sie können auch die Einstellungsschaltfläche unten verwenden, um die Scrollgeschwindigkeit anzupassen.\n\n## 5. Kann ich den Stil der generierten Barcodes anpassen?\n\nJa. Im Optionsbereich können Sie die folgenden Parameter anpassen:\n- Codierungsformat\n- Ob Text angezeigt werden soll (Ja/Nein)\n- Barcode-Länge (mm)\n- Barcode-Höhe (mm)\n- Benutzerdefinierter Anzeigetext: Wenn „Text anzeigen\" aktiviert ist, können Sie für jeden Barcode einen eigenen Anzeigetext festlegen. Drücken Sie nach dem Barcode-Wert die **Tab-Taste** und geben Sie Ihren Text ein (z.B. `1234567890\\t1234 567 890`). Im Massenmodus kann jede Zeile einen eigenen Text haben. Sie können auch zwei Spalten direkt aus Excel einfügen – sie werden automatisch als Tab-getrennt erkannt.\n\n## 6. Wie kann ich die generierten Barcodes herunterladen oder speichern?\n\nSie können Barcodes auf folgende Weise herunterladen oder speichern:\n- Klicken Sie auf die Download-Schaltfläche über dem Ausgabefeld, um das Format PNG, JPG, GIF oder SVG zum Herunterladen auszuwählen.\n- Wenn nur ein Barcode-Bild generiert wurde, wird es direkt heruntergeladen.\n- Wenn mehrere Barcode-Bilder generiert wurden, packt das System alle Bilder in eine ZIP-Datei zum Herunterladen.\n\n## 7. Kann ich Links zu den Barcodes erhalten?\n\nJa, Sie können zwei Arten von Links erhalten:\n1. Barcode-Bildlink: Klicken Sie auf die Schaltfläche \"Barcode-Link kopieren\", um zu kopieren. Das Format sieht so aus:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Link zur aktuellen Seite: Klicken Sie auf die Schaltfläche \"Link zu dieser Seite\", um zu kopieren. Das Format sieht so aus:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nDiese Links können einfach geteilt oder in andere Anwendungen eingebettet werden.\n\n## 8. Sind die von diesem Tool generierten Barcodes rechtlich gültig?\n\nDie von unserem Tool generierten Barcodes sind technisch korrekt, aber ob sie rechtlich gültig sind, hängt von Ihrem beabsichtigten Verwendungszweck und den relevanten Vorschriften ab. Wenn Sie sie für kommerzielle Zwecke verwenden möchten, empfehlen wir, die relevanten Branchenstandards und rechtlichen Anforderungen zu konsultieren.\n\n## 9. Wie ist die Qualität der generierten Barcodes? Sind sie für den Druck geeignet?\n\nDie von unserem Tool generierten Barcodes haben eine hochwertige Auflösung und sind vollständig für den Druck geeignet. Wir empfehlen jedoch, vor dem formellen großflächigen Einsatz kleine Tests durchzuführen, um sicherzustellen, dass sie in Ihren spezifischen Anwendungsszenarien normal gescannt und erkannt werden können.\n\n## 10. Kann ich dieses Tool auf mobilen Geräten verwenden?\n\nJa, unser Barcode-Generator ist webbasiert und mit verschiedenen Geräten kompatibel. Ob Sie einen Computer, ein Tablet oder ein Smartphone verwenden, Sie können einfach auf dieses Tool zugreifen und es nutzen."
  }
}


================================================
FILE: messages/en.json
================================================
{
  "Index": {
    "title": "Free Barcode Generator is an online tool that allows users to easily create various formats of barcodes and QR codes. It supports multiple encoding types and enables users to generate barcodes in real-time and in bulk, completely free of charge."
  },
  "Barcode": {
    "title": "Free {type} Barcode Generator",
    "input": {
      "title": "Barcode Values (one per line)",
      "placeholder": "Enter values here, one per line",
      "caption-hint": "To show custom text below the barcode: press the Tab key after each value and type your caption. Or copy 2 columns from Excel (barcode value | display text) and paste directly."
    },
    "options": {
      "name": "Options",
      "code-format": "Code Format",
      "show-text": "Show Text",
      "show-yes": "Yes",
      "show-no": "No",
      "barcode-length": "Barcode Length (mm)",
      "barcode-height": "Barcode Height (mm)",
      "barcode-margin": "Barcode margin (mm)",
      "locked-aspect-ratio": "Height is locked to width for 2D barcodes."
    },
    "select-format": {
      "name": "Select barcode format",
      "search-placeholder": "Enter barcode format..."
    },
    "output": {
      "title": "Output"
    },
    "layout": {
      "name": "Print Layout",
      "1x2": "Print 1 Column",
      "2x3": "Print 2 Columns",
      "3x4": "Print 3 Columns",
      "4x5": "Print 4 Columns"
    }
  },
  "scroll": {
    "to-top": "Back to top",
    "setting": "Set scroll speed",
    "start-scroll": "Start scrolling",
    "pause-scroll": "Pause scrolling"
  },
  "content": {
    "faq": "# Free Barcode Generator FAQ\n\n## 1. What is the Free Barcode Generator?\n\nThe Free Barcode Generator is an open-source online tool that allows users to easily create various formats of one-dimensional barcodes. It supports multiple encoding types and enables users to generate barcodes in real-time and in bulk, completely free of charge.\n\n## 2. How do I use this barcode generator?\n\nUsing it is very simple:\n- Enter the content you want to encode in the input box, with each line corresponding to one barcode.\n- Use the tabs to switch between different encoding types (such as Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Select the encoding format and barcode style in the options.\n- The system will generate the corresponding barcode in real-time.\n\n## 3. What types of barcodes does this tool support?\n\nOur tool supports various common barcode formats, including:\n- Code128 (including Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (including EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (including Code39, Code39 Extended)\n- ITF (including ITF-14)\n- MSI Plessey (including Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (including Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (including ISBN, ISMN, ISSN)\n\n2D barcode formats, including:\n- QR Code\n- Data Matrix\n- PDF417\n- Aztec Code\n\n## 4. Can I generate multiple barcodes at once?\n\nYes, this tool supports bulk generation. You just need to enter one barcode content per line in the input box, and the system will generate a corresponding barcode for each line. For bulk-generated barcodes, you can click the \"Start Scrolling\" button in the bottom right corner, and the page will automatically scroll to display all generated barcodes. You can also use the settings button below to adjust the scrolling rate.\n\n## 5. Can I customize the style of the generated barcodes?\n\nYes. In the options section, you can adjust the following parameters:\n- Encoding format\n- Whether to display text (Yes/No)\n- Barcode length (mm)\n- Barcode height (mm)\n- Custom display text: when \"Show Text\" is enabled, you can set custom text shown below each barcode. After the barcode value, press the **Tab key** and type your caption (e.g. `1234567890\\t1234 567 890`). Each line in bulk mode can have its own caption. You can also paste two columns directly from Excel — they are automatically Tab-separated.\n\n## 6. How do I download or save the generated barcodes?\n\nYou can download or save barcodes in the following ways:\n- Click the download button above the output box to choose to download as PNG, JPG, GIF, or SVG format.\n- If only one barcode image is generated, it will be downloaded directly.\n- If multiple barcode images are generated, the system will package all images into a ZIP file for download.\n\n## 7. Can I get links to the barcodes?\n\nYes, you can get two types of links:\n1. Barcode image link: Click the \"Copy Barcode Link\" button to copy, in the format:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Current page link: Click the \"Link to This Page\" button to copy, in the format:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nThese links can be easily shared or embedded in other applications.\n\n## 8. Are the barcodes generated by this tool legally valid?\n\nThe barcodes generated by our tool are technically accurate, but whether they have legal validity depends on your intended use and relevant regulations. If you need to use them for commercial purposes, we recommend consulting relevant industry standards and legal requirements.\n\n## 9. What's the quality of the generated barcodes? Are they suitable for printing?\n\nThe barcodes generated by our tool have high-quality resolution and are fully suitable for printing. However, we recommend conducting small-scale tests before formal large-scale use to ensure they can be scanned and recognized normally in your specific application scenarios.\n\n## 10. Can I use this tool on mobile devices?\n\nYes, our barcode generator is web-based and compatible with various devices. Whether you're using a computer, tablet, or smartphone, you can easily access and use this tool."
  }
}


================================================
FILE: messages/es.json
================================================
{
  "Index": {
    "title": "El generador de códigos de barras gratuito es una herramienta en línea que permite a los usuarios crear fácilmente diferentes formatos de códigos de barras y códigos QR. Admite múltiples tipos de codificación y permite a los usuarios generar códigos de barras en tiempo real y en lotes, completamente gratis."
  },
  "Barcode": {
    "title": "Generador de Código de Barras {type} Gratis",
    "input": {
      "title": "Valores de código de barras (uno por línea)",
      "placeholder": "Ingrese valores, uno por línea",
      "caption-hint": "Para mostrar texto personalizado bajo el código de barras: pulse la tecla Tab después de cada valor e introduzca su texto. O copie 2 columnas de Excel (valor | texto de visualización) y péguelas directamente."
    },
    "options": {
      "name": "Opciones",
      "code-format": "Formato del código",
      "show-text": "Mostrar texto",
      "show-yes": "Sí",
      "show-no": "No",
      "barcode-length": "Longitud del código de barras (mm)",
      "barcode-height": "Altura del código de barras (mm)",
      "barcode-margin": "Margen del código de barras (mm)",
      "locked-aspect-ratio": "La altura está bloqueada al ancho para códigos 2D."
    },
    "select-format": {
      "name": "Seleccionar formato de código de barras",
      "search-placeholder": "Ingrese el formato de código de barras..."
    },
    "output": {
      "title": "Salida"
    },
    "layout": {
      "name": "Diseño de impresión",
      "1x2": "Imprimir 1 columna",
      "2x3": "Imprimir 2 columnas",
      "3x4": "Imprimir 3 columnas",
      "4x5": "Imprimir 4 columnas"
    }
  },
  "scroll": {
    "to-top": "Volver arriba",
    "setting": "Ajustar velocidad de desplazamiento",
    "start-scroll": "Iniciar desplazamiento",
    "pause-scroll": "Pausar desplazamiento"
  },
  "content": {
    "faq": "# Preguntas Frecuentes del Generador de Códigos de Barras Gratuito\n\n## 1. ¿Qué es el Generador de Códigos de Barras Gratuito?\n\nEl Generador de Códigos de Barras Gratuito es una herramienta en línea de código abierto que permite a los usuarios crear fácilmente varios formatos de códigos de barras unidimensionales. Admite múltiples tipos de codificación y permite a los usuarios generar códigos de barras en tiempo real y en masa, de forma totalmente gratuita.\n\n## 2. ¿Cómo se usa este generador de códigos de barras?\n\nEl uso es muy sencillo:\n- Ingrese el contenido que desea codificar en el cuadro de entrada, con cada línea correspondiente a un código de barras.\n- Use las pestañas para cambiar entre diferentes tipos de codificación (como Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Seleccione el formato de codificación y el estilo del código de barras en las opciones.\n- El sistema generará el código de barras correspondiente en tiempo real.\n\n## 3. ¿Qué tipos de códigos de barras admite esta herramienta?\n\nNuestra herramienta admite varios formatos comunes de códigos de barras, incluyendo:\n- Code128 (incluyendo Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (incluyendo EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (incluyendo Code39, Code39 Extended)\n- ITF (incluyendo ITF-14)\n- MSI Plessey (incluyendo Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (incluyendo Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (incluyendo ISBN, ISMN, ISSN)\n\nFormatos de códigos de barras 2D, incluyendo:\n- Código QR\n- Data Matrix\n- PDF417\n- Código Aztec\n\n## 4. ¿Puedo generar múltiples códigos de barras a la vez?\n\nSí, esta herramienta admite la generación en masa. Solo necesita ingresar un contenido de código de barras por línea en el cuadro de entrada, y el sistema generará un código de barras correspondiente para cada línea. Para los códigos de barras generados en masa, puede hacer clic en el botón \"Iniciar desplazamiento\" en la esquina inferior derecha, y la página se desplazará automáticamente para mostrar todos los códigos de barras generados. También puede usar el botón de configuración debajo para ajustar la velocidad de desplazamiento.\n\n## 5. ¿Puedo personalizar el estilo de los códigos de barras generados?\n\nSí. En la sección de opciones, puede ajustar los siguientes parámetros:\n- Formato de codificación\n- Si mostrar texto (Sí/No)\n- Longitud del código de barras (mm)\n- Altura del código de barras (mm)\n- Texto de visualización personalizado: cuando \"Mostrar texto\" está activado, puede establecer un texto personalizado para cada código de barras. Después del valor, pulse **Tab** y escriba su texto (p.ej. `1234567890\\t1234 567 890`). En modo masivo, cada línea puede tener su propio texto. También puede pegar dos columnas directamente desde Excel — se reconocen automáticamente como separadas por tabulación.\n\n## 6. ¿Cómo puedo descargar o guardar los códigos de barras generados?\n\nPuede descargar o guardar los códigos de barras de las siguientes maneras:\n- Haga clic en el botón de descarga sobre el cuadro de salida para elegir descargar en formato PNG, JPG, GIF o SVG.\n- Si solo se genera una imagen de código de barras, se descargará directamente.\n- Si se generan múltiples imágenes de códigos de barras, el sistema empaquetará todas las imágenes en un archivo ZIP para su descarga.\n\n## 7. ¿Puedo obtener enlaces a los códigos de barras?\n\nSí, puede obtener dos tipos de enlaces:\n1. Enlace de imagen del código de barras: Haga clic en el botón \"Copiar enlace del código de barras\" para copiar, en el formato:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Enlace de la página actual: Haga clic en el botón \"Enlace a esta página\" para copiar, en el formato:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nEstos enlaces se pueden compartir o incrustar fácilmente en otras aplicaciones.\n\n## 8. ¿Son legalmente válidos los códigos de barras generados por esta herramienta?\n\nLos códigos de barras generados por nuestra herramienta son técnicamente precisos, pero su validez legal depende de su uso previsto y las regulaciones relevantes. Si necesita usarlos para fines comerciales, recomendamos consultar los estándares de la industria y los requisitos legales pertinentes.\n\n## 9. ¿Cuál es la calidad de los códigos de barras generados? ¿Son adecuados para imprimir?\n\nLos códigos de barras generados por nuestra herramienta tienen una resolución de alta calidad y son completamente adecuados para la impresión. Sin embargo, recomendamos realizar pruebas a pequeña escala antes del uso formal a gran escala para asegurarse de que se puedan escanear y reconocer normalmente en sus escenarios de aplicación específicos.\n\n## 10. ¿Puedo usar esta herramienta en dispositivos móviles?\n\nSí, nuestro generador de códigos de barras está basado en la web y es compatible con varios dispositivos. Ya sea que esté usando una computadora, una tableta o un teléfono inteligente, puede acceder y usar fácilmente esta herramienta."
  }
}


================================================
FILE: messages/fr.json
================================================
{
  "Index": {
    "title": "Le générateur de codes-barres gratuit est un outil en ligne qui permet aux utilisateurs de créer facilement différents formats de codes-barres et de QR codes. Il prend en charge plusieurs types d'encodage et permet aux utilisateurs de générer des codes-barres en temps réel et en masse, totalement gratuitement."
  },
  "Barcode": {
    "title": "Générateur de Code-Barres {type} Gratuit",
    "input": {
      "title": "Valeurs de code-barres (une par ligne)",
      "placeholder": "Entrez les valeurs, une par ligne",
      "caption-hint": "Pour afficher un texte personnalisé sous le code-barres : appuyez sur la touche Tab après chaque valeur et saisissez votre texte. Ou copiez 2 colonnes depuis Excel (valeur | texte d'affichage) et collez-les directement."
    },
    "options": {
      "name": "Options",
      "code-format": "Format du code",
      "show-text": "Afficher le texte",
      "show-yes": "Oui",
      "show-no": "Non",
      "barcode-length": "Longueur du code-barres (mm)",
      "barcode-height": "Hauteur du code-barres (mm)",
      "barcode-margin": "Marge du code-barres (mm)",
      "locked-aspect-ratio": "La hauteur est bloquée à la largeur pour les codes 2D."
    },
    "select-format": {
      "name": "Sélectionner le format de code-barres",
      "search-placeholder": "Entrez le format de code-barres..."
    },
    "output": {
      "title": "Sortie"
    },
    "layout": {
      "name": "Mise en page d'impression",
      "1x2": "Imprimer 1 colonne",
      "2x3": "Imprimer 2 colonnes",
      "3x4": "Imprimer 3 colonnes",
      "4x5": "Imprimer 4 colonnes"
    }
  },
  "scroll": {
    "to-top": "Retour en haut",
    "setting": "Régler la vitesse de défilement",
    "start-scroll": "Commencer le défilement",
    "pause-scroll": "Mettre en pause le défilement"
  },
  "content": {
    "faq": "# FAQ du Générateur de Codes-barres Gratuit\n\n## 1. Qu'est-ce que le Générateur de Codes-barres Gratuit ?\n\nLe Générateur de Codes-barres Gratuit est un outil en ligne open-source qui permet aux utilisateurs de créer facilement divers formats de codes-barres unidimensionnels. Il prend en charge plusieurs types d'encodage et permet aux utilisateurs de générer des codes-barres en temps réel et en masse, totalement gratuitement.\n\n## 2. Comment utiliser ce générateur de codes-barres ?\n\nL'utilisation est très simple :\n- Entrez le contenu que vous souhaitez encoder dans la zone de saisie, chaque ligne correspondant à un code-barres.\n- Utilisez les onglets pour basculer entre les différents types d'encodage (comme Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Sélectionnez le format d'encodage et le style du code-barres dans les options.\n- Le système générera le code-barres correspondant en temps réel.\n\n## 3. Quels types de codes-barres cet outil prend-il en charge ?\n\nNotre outil prend en charge divers formats de codes-barres courants, notamment :\n- Code128 (y compris Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (y compris EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (y compris Code39, Code39 Extended)\n- ITF (y compris ITF-14)\n- MSI Plessey (y compris Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (y compris Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (y compris ISBN, ISMN, ISSN)\n\nFormats de codes-barres 2D, notamment :\n- Code QR\n- Data Matrix\n- PDF417\n- Code Aztec\n\n## 4. Puis-je générer plusieurs codes-barres à la fois ?\n\nOui, cet outil prend en charge la génération en masse. Il vous suffit d'entrer un contenu de code-barres par ligne dans la zone de saisie, et le système générera un code-barres correspondant pour chaque ligne. Pour les codes-barres générés en masse, vous pouvez cliquer sur le bouton \"Commencer le défilement\" dans le coin inférieur droit, et la page défilera automatiquement pour afficher tous les codes-barres générés. Vous pouvez également utiliser le bouton de paramètres ci-dessous pour ajuster la vitesse de défilement.\n\n## 5. Puis-je personnaliser le style des codes-barres générés ?\n\nOui. Dans la section des options, vous pouvez ajuster les paramètres suivants :\n- Format d'encodage\n- Affichage du texte (Oui/Non)\n- Longueur du code-barres (mm)\n- Hauteur du code-barres (mm)\n- Texte d'affichage personnalisé : lorsque « Afficher le texte » est activé, vous pouvez définir un texte d'affichage différent pour chaque code-barres. Après la valeur, appuyez sur la touche **Tab** et saisissez votre texte (ex. `1234567890\\t1234 567 890`). En mode masse, chaque ligne peut avoir son propre texte. Vous pouvez également coller deux colonnes directement depuis Excel — elles sont automatiquement reconnues comme séparées par une tabulation.\n\n## 6. Comment télécharger ou enregistrer les codes-barres générés ?\n\nVous pouvez télécharger ou enregistrer les codes-barres de la manière suivante :\n- Cliquez sur le bouton de téléchargement au-dessus de la zone de sortie pour choisir de télécharger au format PNG, JPG, GIF ou SVG.\n- Si une seule image de code-barres est générée, elle sera téléchargée directement.\n- Si plusieurs images de codes-barres sont générées, le système les regroupera dans un fichier ZIP pour le téléchargement.\n\n## 7. Puis-je obtenir des liens vers les codes-barres ?\n\nOui, vous pouvez obtenir deux types de liens :\n1. Lien de l'image du code-barres : Cliquez sur le bouton \"Copier le lien du code-barres\" pour copier, au format :\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Lien de la page actuelle : Cliquez sur le bouton \"Lien vers cette page\" pour copier, au format :\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nCes liens peuvent être facilement partagés ou intégrés dans d'autres applications.\n\n## 8. Les codes-barres générés par cet outil sont-ils légalement valides ?\n\nLes codes-barres générés par notre outil sont techniquement précis, mais leur validité légale dépend de votre utilisation prévue et des réglementations pertinentes. Si vous avez besoin de les utiliser à des fins commerciales, nous vous recommandons de consulter les normes de l'industrie et les exigences légales pertinentes.\n\n## 9. Quelle est la qualité des codes-barres générés ? Conviennent-ils à l'impression ?\n\nLes codes-barres générés par notre outil ont une résolution de haute qualité et conviennent parfaitement à l'impression. Cependant, nous recommandons d'effectuer des tests à petite échelle avant une utilisation formelle à grande échelle pour s'assurer qu'ils peuvent être scannés et reconnus normalement dans vos scénarios d'application spécifiques.\n\n## 10. Puis-je utiliser cet outil sur des appareils mobiles ?\n\nOui, notre générateur de codes-barres est basé sur le web et compatible avec divers appareils. Que vous utilisiez un ordinateur, une tablette ou un smartphone, vous pouvez facilement accéder et utiliser cet outil."
  }
}


================================================
FILE: messages/it.json
================================================
{
  "Index": {
    "title": "Il generatore di codici a barre gratuito è uno strumento online che consente agli utenti di creare facilmente diversi formati di codici a barre e codici QR. Supporta molteplici tipi di codifica e permette agli utenti di generare codici a barre in tempo reale e in batch, completamente gratis."
  },
  "Barcode": {
    "title": "Generatore Gratuito di Codici a Barre {type}",
    "input": {
      "title": "Valori del codice a barre (uno per riga)",
      "placeholder": "Inserisci valori, uno per riga",
      "caption-hint": "Per mostrare testo personalizzato sotto il codice a barre: premi il tasto Tab dopo ogni valore e digita il testo. Oppure copia 2 colonne da Excel (valore | testo) e incolla direttamente."
    },
    "options": {
      "name": "Opzioni",
      "code-format": "Formato del codice",
      "show-text": "Mostra testo",
      "show-yes": "Sì",
      "show-no": "No",
      "barcode-length": "Lunghezza del codice a barre (mm)",
      "barcode-height": "Altezza del codice a barre (mm)",
      "barcode-margin": "Margine del codice a barre (mm)",
      "locked-aspect-ratio": "L'altezza è bloccata alla larghezza per i codici 2D."
    },
    "select-format": {
      "name": "Seleziona formato codice a barre",
      "search-placeholder": "Inserisci il formato del codice a barre..."
    },
    "output": {
      "title": "Output"
    },
    "layout": {
      "name": "Layout di stampa",
      "1x2": "Stampa 1 colonna",
      "2x3": "Stampa 2 colonne",
      "3x4": "Stampa 3 colonne",
      "4x5": "Stampa 4 colonne"
    }
  },
  "scroll": {
    "to-top": "Torna in cima",
    "setting": "Imposta velocità di scorrimento",
    "start-scroll": "Inizia lo scorrimento",
    "pause-scroll": "Pausa scorrimento"
  },
  "content": {
    "faq": "# FAQ del Generatore di Codici a Barre Gratuito\n\n## 1. Cos'è il Generatore di Codici a Barre Gratuito?\n\nIl Generatore di Codici a Barre Gratuito è uno strumento online open-source che permette agli utenti di creare facilmente vari formati di codici a barre unidimensionali. Supporta diversi tipi di codifica e consente agli utenti di generare codici a barre in tempo reale e in massa, completamente gratis.\n\n## 2. Come si usa questo generatore di codici a barre?\n\nL'uso è molto semplice:\n- Inserisci il contenuto che vuoi codificare nella casella di input, con ogni riga corrispondente a un codice a barre.\n- Usa le schede per passare tra i diversi tipi di codifica (come Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Seleziona il formato di codifica e lo stile del codice a barre nelle opzioni.\n- Il sistema genererà il codice a barre corrispondente in tempo reale.\n\n## 3. Quali tipi di codici a barre supporta questo strumento?\n\nIl nostro strumento supporta vari formati comuni di codici a barre, tra cui:\n- Code128 (inclusi Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (inclusi EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (inclusi Code39, Code39 Extended)\n- ITF (incluso ITF-14)\n- MSI Plessey (inclusi Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (inclusi Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (inclusi ISBN, ISMN, ISSN)\n\nFormati di codici a barre 2D, tra cui:\n- Codice QR\n- Data Matrix\n- PDF417\n- Codice Aztec\n\n## 4. Posso generare più codici a barre contemporaneamente?\n\nSì, questo strumento supporta la generazione in massa. Basta inserire un contenuto di codice a barre per riga nella casella di input, e il sistema genererà un codice a barre corrispondente per ogni riga. Per i codici a barre generati in massa, puoi cliccare sul pulsante \"Avvia scorrimento\" nell'angolo in basso a destra, e la pagina scorrerà automaticamente per mostrare tutti i codici a barre generati. Puoi anche usare il pulsante delle impostazioni sotto per regolare la velocità di scorrimento.\n\n## 5. Posso personalizzare lo stile dei codici a barre generati?\n\nSì. Nella sezione delle opzioni, puoi regolare i seguenti parametri:\n- Formato di codifica\n- Se mostrare il testo (Sì/No)\n- Lunghezza del codice a barre (mm)\n- Altezza del codice a barre (mm)\n- Testo di visualizzazione personalizzato: quando \"Mostra testo\" è attivato, è possibile impostare un testo personalizzato per ogni codice a barre. Dopo il valore, premere il tasto **Tab** e digitare il testo (es. `1234567890\\t1234 567 890`). In modalità bulk, ogni riga può avere il proprio testo. È anche possibile incollare due colonne direttamente da Excel — vengono riconosciute automaticamente come separate da tabulazione.\n\n## 6. Come posso scaricare o salvare i codici a barre generati?\n\nPuoi scaricare o salvare i codici a barre nei seguenti modi:\n- Clicca sul pulsante di download sopra la casella di output per scegliere di scaricare in formato PNG, JPG, GIF o SVG.\n- Se viene generata una sola immagine di codice a barre, verrà scaricata direttamente.\n- Se vengono generate più immagini di codici a barre, il sistema impacchetterà tutte le immagini in un file ZIP per il download.\n\n## 7. Posso ottenere link ai codici a barre?\n\nSì, puoi ottenere due tipi di link:\n1. Link all'immagine del codice a barre: Clicca sul pulsante \"Copia link del codice a barre\" per copiare, nel formato:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Link alla pagina corrente: Clicca sul pulsante \"Link a questa pagina\" per copiare, nel formato:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nQuesti link possono essere facilmente condivisi o incorporati in altre applicazioni.\n\n## 8. I codici a barre generati da questo strumento sono legalmente validi?\n\nI codici a barre generati dal nostro strumento sono tecnicamente accurati, ma la loro validità legale dipende dall'uso previsto e dalle normative pertinenti. Se hai bisogno di usarli per scopi commerciali, ti consigliamo di consultare gli standard del settore e i requisiti legali pertinenti.\n\n## 9. Qual è la qualità dei codici a barre generati? Sono adatti per la stampa?\n\nI codici a barre generati dal nostro strumento hanno una risoluzione di alta qualità e sono completamente adatti per la stampa. Tuttavia, consigliamo di eseguire test su piccola scala prima dell'uso formale su larga scala per assicurarsi che possano essere scansionati e riconosciuti normalmente nei tuoi scenari di applicazione specifici.\n\n## 10. Posso usare questo strumento su dispositivi mobili?\n\nSì, il nostro generatore di codici a barre è basato sul web ed è compatibile con vari dispositivi. Che tu stia usando un computer, un tablet o uno smartphone, puoi accedere e utilizzare facilmente questo strumento."
  }
}


================================================
FILE: messages/ja.json
================================================
{
  "Index": {
    "title": "無料バーコードジェネレーターは、ユーザーが様々な形式のバーコードやQRコードを簡単に作成できるオンラインツールです。複数のエンコーディングタイプをサポートし、リアルタイムで一括してバーコードを生成することができ、完全に無料で使用できます。"
  },
  "Barcode": {
    "title": "無料 {type} バーコード生成ツール",
    "input": {
      "title": "バーコード値(1行に1つ)",
      "placeholder": "値を入力してください、1行に1つ",
      "caption-hint": "条码の下にカスタムテキストを表示するには:各値の後にTabキーを押してテキストを入力します。またはExcelから2列(バーコード値 | 表示テキスト)をコピーして直接貼り付けることもできます。"
    },
    "options": {
      "name": "オプション",
      "code-format": "コード形式",
      "show-text": "テキスト表示",
      "show-yes": "はい",
      "show-no": "いいえ",
      "barcode-length": "バーコードの長さ(mm)",
      "barcode-height": "バーコードの高さ(mm)",
      "barcode-margin": "バーコード余白 (mm)",
      "locked-aspect-ratio": "2Dバーコードの高さは宽にロックされています。"
    },
    "select-format": {
      "name": "バーコード形式を選択",
      "search-placeholder": "バーコード形式を入力..."
    },
    "output": {
      "title": "出力"
    },
    "layout": {
      "name": "印刷レイアウト",
      "1x2": "1列で印刷",
      "2x3": "2列で印刷",
      "3x4": "3列で印刷",
      "4x5": "4列で印刷"
    }
  },
  "scroll": {
    "to-top": "トップに戻る",
    "setting": "スクロール速度を設定",
    "start-scroll": "スクロール開始",
    "pause-scroll": "スクロール停止"
  },
  "content": {
    "faq": "# 無料バーコードジェネレーター FAQ\n\n## 1. 無料バーコードジェネレーターとは何ですか?\n\n無料バーコードジェネレーターは、ユーザーが様々な形式の一次元バーコードを簡単に作成できるオープンソースのオンラインツールです。複数のエンコーディングタイプをサポートし、ユーザーがリアルタイムで一括してバーコードを生成することができ、完全に無料で使用できます。\n\n## 2. このバーコードジェネレーターの使い方は?\n\n使用方法は非常に簡単です:\n- 入力ボックスにエンコードしたい内容を入力し、各行が1つのバーコードに対応します。\n- タブを使用して異なるエンコーディングタイプ(Code128、EAN / UPC、Code39、ITF、MSI Plessey、Pharmacode、Codabarなど)を切り替えます。\n- オプションでエンコーディング形式とバーコードスタイルを選択します。\n- システムがリアルタイムで対応するバーコードを生成します。\n\n## 3. このツールはどのタイプのバーコードをサポートしていますか?\n\n私たちのツールは、以下を含む様々な一般的なバーコード形式をサポートしています:\n- Code128(Code128A、Code128B、Code128C、GS1-128を含む)\n- EAN / UPC(EAN-13、EAN-8、EAN-5、EAN-2、UPC-A、UPC-Eを含む)\n- Code39(Code39、Code39 Extendedを含む)\n- ITF(ITF-14を含む)\n- MSI Plessey(Mod 10、Mod 11、Mod 1010、Mod 1110を含む)\n- Pharmacode\n- Codabar\n- GS1 DataBar(Omnidirectional、Limited、Expanded、Stackedを含む)\n- Publishing(ISBN、ISMN、ISSNを含む)\n\n2Dバーコード形式:\n- QRコード\n- データマトリックス\n- PDF417\n- Aztecコード\n\n## 4. 一度に複数のバーコードを生成できますか?\n\nはい、このツールは一括生成をサポートしています。入力ボックスに1行につき1つのバーコード内容を入力するだけで、システムが各行に対応するバーコードを生成します。一括生成されたバーコードについては、右下の「スクロール開始」ボタンをクリックすると、ページが自動的にスクロールして生成されたすべてのバーコードを表示します。また、下部の設定ボタンを使用してスクロール速度を調整することもできます。\n\n## 5. 生成されたバーコードのスタイルをカスタマイズできますか?\n\nはい、できます。オプションセクションで以下のパラメータを調整できます:\n- エンコーディング形式\n- テキストを表示するかどうか(はい/いいえ)\n- バーコードの長さ(mm)\n- バーコードの高さ(mm)\n- カスタム表示テキスト:「テキスト表示」が有効の場合、各バーコードに個別の表示テキストを設定できます。バーコード値の後に **Tab キー** を押してテキストを入力します(例:`1234567890\\t1234 567 890`)。一括生成時は各行に独自のキャプションを設定できます。Excelの2列から直接貼り付けることもでき、列間は自動的にTabとして認識されます。\n\n## 6. 生成されたバーコードをダウンロードまたは保存するにはどうすればいいですか?\n\n以下の方法でバーコードをダウンロードまたは保存できます:\n- 出力ボックスの上にあるダウンロードボタンをクリックし、PNG、JPG、GIF、SVG形式でダウンロードを選択します。\n- バーコード画像が1つだけ生成された場合は、その画像が直接ダウンロードされます。\n- 複数のバーコード画像が生成された場合、システムはすべての画像をZIPファイルにパッケージ化してダウンロードできるようにします。\n\n## 7. バーコードのリンクを取得できますか?\n\nはい、2種類のリンクを取得できます:\n1. バーコード画像リンク:「バーコードリンクをコピー」ボタンをクリックしてコピーします。形式は次のようになります:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. 現在のページリンク:「このページへのリンク」ボタンをクリックしてコピーします。形式は次のようになります:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nこれらのリンクは他のアプリケーションで簡単に共有または埋め込むことができます。\n\n## 8. このツールで生成されたバーコードは法的に有効ですか?\n\n私たちのツールで生成されたバーコードは技術的に正確ですが、法的な有効性は使用目的と関連規制によって異なります。商業目的で使用する場合は、関連業界の基準と法的要件を確認することをお勧めします。\n\n## 9. 生成されたバーコードの品質はどうですか?印刷に適していますか?\n\n私たちのツールで生成されたバーコードは高品質の解像度を持ち、印刷に完全に適しています。ただし、正式な大規模使用の前に、小規模なテストを行い、特定の応用シナリオで正常にスキャンおよび認識できることを確認することをお勧めします。\n\n## 10. モバイルデバイスでこのツールを使用できますか?\n\nはい、私たちのバーコードジェネレーターはウェブベースで、様々なデバイスと互換性があります。コンピューター、タブレット、スマートフォンのいずれを使用しても、このツールに簡単にアクセスして使用できます。"
  }
}


================================================
FILE: messages/ko.json
================================================
{
  "Index": {
    "title": "무료 바코드 생성기는 사용자가 쉽게 다양한 형식의 바코드와 QR 코드를 만들 수 있는 온라인 도구입니다. 여러 가지 인코딩 유형을 지원하며 사용자가 실시간으로 그리고 일괄적으로 바코드를 생성할 수 있게 해주며, 완전히 무료입니다."
  },
  "Barcode": {
    "title": "무료 {type} 바코드 생성기",
    "input": {
      "title": "바코드 값 (한 줄에 하나씩)",
      "placeholder": "값을 입력하세요, 한 줄에 하나씩",
      "caption-hint": "바코드 아래에 사용자 정의 텍스트를 표시하려면: 각 값 뒤에 Tab 키를 누르고 텍스트를 입력하세요. 또는 Excel에서 2열(바코드 값 | 표시 텍스트)을 복사하여 직접 붙여넣을 수 있습니다."
    },
    "options": {
      "name": "옵션",
      "code-format": "코드 형식",
      "show-text": "텍스트 표시",
      "show-yes": "예",
      "show-no": "아니오",
      "barcode-length": "바코드 길이 (mm)",
      "barcode-height": "바코드 높이 (mm)",
      "barcode-margin": "바코드 여백 (mm)",
      "locked-aspect-ratio": "2D 바코드의 높이는 폭에 잠깁니다."
    },
    "select-format": {
      "name": "바코드 형식 선택",
      "search-placeholder": "바코드 형식 입력..."
    },
    "output": {
      "title": "출력"
    },
    "layout": {
      "name": "인쇄 레이아웃",
      "1x2": "1열 인쇄",
      "2x3": "2열 인쇄",
      "3x4": "3열 인쇄",
      "4x5": "4열 인쇄"
    }
  },
  "scroll": {
    "to-top": "맨 위로",
    "setting": "스크롤 속도 설정",
    "start-scroll": "스크롤 시작",
    "pause-scroll": "스크롤 일시 정지"
  },
  "content": {
    "faq": "# 무료 바코드 생성기 FAQ\n\n## 1. 무료 바코드 생성기란 무엇인가요?\n\n무료 바코드 생성기는 사용자가 다양한 형식의 1차원 바코드를 쉽게 만들 수 있는 오픈 소스 온라인 도구입니다. 여러 인코딩 유형을 지원하며 사용자가 실시간으로 대량의 바코드를 생성할 수 있으며 완전히 무료로 사용할 수 있습니다.\n\n## 2. 이 바코드 생성기는 어떻게 사용하나요?\n\n사용 방법은 매우 간단합니다:\n- 입력 상자에 인코딩하려는 내용을 입력하세요. 각 줄이 하나의 바코드에 해당합니다.\n- 탭을 사용하여 다양한 인코딩 유형(예: Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar) 사이를 전환합니다.\n- 옵션에서 인코딩 형식과 바코드 스타일을 선택하세요.\n- 시스템이 실시간으로 해당 바코드를 생성합니다.\n\n## 3. 이 도구는 어떤 종류의 바코드를 지원하나요?\n\n우리 도구는 다음을 포함한 다양한 일반적인 바코드 형식을 지원합니다:\n- Code128 (Code128A, Code128B, Code128C, GS1-128 포함)\n- EAN / UPC (EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E 포함)\n- Code39 (Code39, Code39 Extended 포함)\n- ITF (ITF-14 포함)\n- MSI Plessey (Mod 10, Mod 11, Mod 1010, Mod 1110 포함)\n- Pharmacode\n- Codabar\n- GS1 DataBar (Omnidirectional, Limited, Expanded, Stacked 포함)\n- Publishing (ISBN, ISMN, ISSN 포함)\n\n2D 바코드 형식:\n- QR 코드\n- Data Matrix\n- PDF417\n- Aztec 코드\n\n## 4. 여러 개의 바코드를 한 번에 생성할 수 있나요?\n\n네, 이 도구는 대량 생성을 지원합니다. 입력 상자에 한 줄당 하나의 바코드 내용을 입력하기만 하면 시스템이 각 줄에 대해 해당 바코드를 생성합니다. 대량으로 생성된 바코드의 경우, 오른쪽 하단의 \"스크롤 시작\" 버튼을 클릭하면 페이지가 자동으로 스크롤되어 생성된 모든 바코드를 표시합니다. 아래의 설정 버튼을 사용하여 스크롤 속도를 조정할 수도 있습니다.\n\n## 5. 생성된 바코드의 스타일을 사용자 정의할 수 있나요?\n\n네. 옵션 섹션에서 다음 매개변수를 조정할 수 있습니다:\n- 인코딩 형식\n- 텍스트 표시 여부 (예/아니오)\n- 바코드 길이 (mm)\n- 바코드 높이 (mm)\n- 사용자 정의 표시 텍스트: \"텍스트 표시\"가 활성화되면 각 바코드에 개별 표시 텍스트를 설정할 수 있습니다. 값 뒤에 **Tab 키**를 누르고 텍스트를 입력하세요 (예: `1234567890\\t1234 567 890`). 대량 생성 시 각 줄에 별도의 텍스트를 설정할 수 있습니다. Excel에서 두 열을 직접 붙여넣을 수도 있으며 — 열 구분자는 자동으로 탭으로 인식됩니다.\n\n## 6. 생성된 바코드를 어떻게 다운로드하거나 저장할 수 있나요?\n\n다음과 같은 방법으로 바코드를 다운로드하거나 저장할 수 있습니다:\n- 출력 상자 위의 다운로드 버튼을 클릭하여 PNG, JPG, GIF 또는 SVG 형식으로 다운로드를 선택합니다.\n- 단일 바코드 이미지만 생성된 경우 직접 다운로드됩니다.\n- 여러 바코드 이미지가 생성된 경우 시스템이 모든 이미지를 ZIP 파일로 패키징하여 다운로드합니다.\n\n## 7. 바코드에 대한 링크를 얻을 수 있나요?\n\n네, 두 가지 유형의 링크를 얻을 수 있습니다:\n1. 바코드 이미지 링크: \"바코드 링크 복사\" 버튼을 클릭하여 복사합니다. 형식은 다음과 같습니다:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. 현재 페이지 링크: \"이 페이지 링크\" 버튼을 클릭하여 복사합니다. 형식은 다음과 같습니다:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\n이러한 링크는 다른 애플리케이션에서 쉽게 공유하거나 임베드할 수 있습니다.\n\n## 8. 이 도구로 생성된 바코드는 법적으로 유효한가요?\n\n우리 도구로 생성된 바코드는 기술적으로 정확하지만, 법적 유효성은 의도된 사용 목적과 관련 규정에 따라 다릅니다. 상업적 목적으로 사용해야 하는 경우 관련 산업 표준과 법적 요구 사항을 확인하는 것이 좋습니다.\n\n## 9. 생성된 바코드의 품질은 어떤가요? 인쇄에 적합한가요?\n\n우리 도구로 생성된 바코드는 고품질 해상도를 가지며 인쇄에 완전히 적합합니다. 그러나 정식 대규모 사용 전에 소규모 테스트를 수행하여 특정 응용 시나리오에서 정상적으로 스캔되고 인식되는지 확인하는 것이 좋습니다.\n\n## 10. 모바일 기기에서 이 도구를 사용할 수 있나요?\n\n네, 우리 바코드 생성기는 웹 기반이며 다양한 기기와 호환됩니다. 컴퓨터, 태블릿 또는 스마트폰을 사용하든 이 도구에 쉽게 접근하고 사용할 수 있습니다."
  }
}


================================================
FILE: messages/nl.json
================================================
{
  "Index": {
    "title": "De gratis barcodegenerator is een online tool waarmee gebruikers eenvoudig verschillende formaten barcodes en QR-codes kunnen maken. Het ondersteunt meerdere coderingstypes en stelt gebruikers in staat om realtime en in bulk barcodes te genereren, volledig gratis."
  },
  "Barcode": {
    "title": "Gratis {type} Barcode Generator",
    "input": {
      "title": "Barcode-waarden (één per regel)",
      "placeholder": "Voer waarden in, één per regel",
      "caption-hint": "Om aangepaste tekst onder de barcode te tonen: druk na elke waarde op de Tab-toets en typ uw tekst. Of kopieer 2 kolommen uit Excel (barcodewaarde | weergavetekst) en plak ze direct."
    },
    "options": {
      "name": "Opties",
      "code-format": "Codeformaat",
      "show-text": "Tekst weergeven",
      "show-yes": "Ja",
      "show-no": "Nee",
      "barcode-length": "Barcode lengte (mm)",
      "barcode-height": "Barcode hoogte (mm)",
      "barcode-margin": "Barcode marge (mm)",
      "locked-aspect-ratio": "De hoogte is vergrendeld op de breedte voor 2D-barcodes."
    },
    "select-format": {
      "name": "Selecteer barcode-formaat",
      "search-placeholder": "Voer barcode-formaat in..."
    },
    "output": {
      "title": "Uitvoer"
    },
    "layout": {
      "name": "Afdrukindeling",
      "1x2": "1 kolom afdrukken",
      "2x3": "2 kolommen afdrukken",
      "3x4": "3 kolommen afdrukken",
      "4x5": "4 kolommen afdrukken"
    }
  },
  "scroll": {
    "to-top": "Terug naar boven",
    "setting": "Scrollsnelheid instellen",
    "start-scroll": "Begin met scrollen",
    "pause-scroll": "Pauzeer scrollen"
  },
  "content": {
    "faq": "# Veelgestelde vragen over de Gratis Barcodegenerator\n\n## 1. Wat is de Gratis Barcodegenerator?\n\nDe Gratis Barcodegenerator is een open-source online tool waarmee gebruikers eenvoudig verschillende formaten eendimensionale barcodes kunnen maken. Het ondersteunt meerdere coderingstypes en stelt gebruikers in staat om in realtime en in bulk barcodes te genereren, volledig gratis.\n\n## 2. Hoe gebruik ik deze barcodegenerator?\n\nHet gebruik is zeer eenvoudig:\n- Voer de inhoud die u wilt coderen in het invoervak in, waarbij elke regel overeenkomt met één barcode.\n- Gebruik de tabbladen om te schakelen tussen verschillende coderingstypes (zoals Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Selecteer het coderingsformaat en de barcodestijl in de opties.\n- Het systeem genereert de corresponderende barcode in realtime.\n\n## 3. Welke soorten barcodes ondersteunt deze tool?\n\nOnze tool ondersteunt verschillende eendimensionale barcodeformaten, waaronder:\n- Code128 (inclusief Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (inclusief EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (inclusief Code39, Code39 Extended)\n- ITF (inclusief ITF-14)\n- MSI Plessey (inclusief Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (inclusief Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (inclusief ISBN, ISMN, ISSN)\n\nTweedimensionale barcodeformaten, waaronder:\n- QR Code\n- Data Matrix\n- PDF417\n- Aztec Code\n\n## 4. Kan ik meerdere barcodes tegelijk genereren?\n\nJa, deze tool ondersteunt bulkgeneratie. U hoeft alleen maar één barcode-inhoud per regel in het invoervak in te voeren, en het systeem genereert een corresponderende barcode voor elke regel. Voor in bulk gegenereerde barcodes kunt u op de knop \"Start scrollen\" in de rechterbenedenhoek klikken, en de pagina scrollt automatisch om alle gegenereerde barcodes weer te geven. U kunt ook de instellingenknop eronder gebruiken om de scrollsnelheid aan te passen.\n\n## 5. Kan ik de stijl van de gegenereerde barcodes aanpassen?\n\nJa. In het optiegedeelte kunt u de volgende parameters aanpassen:\n- Coderingsformaat\n- Of tekst moet worden weergegeven (Ja/Nee)\n- Lengte van de barcode (mm)\n- Hoogte van de barcode (mm)\n- Aangepaste weergavetekst: wanneer \"Tekst weergeven\" is ingeschakeld, kunt u voor elke barcode een eigen weergavetekst instellen. Na de barcodewaarde drukt u op de **Tab-toets** en typt u uw tekst (bijv. `1234567890\\t1234 567 890`). In bulkmodus kan elke regel zijn eigen tekst hebben. U kunt ook twee kolommen rechtstreeks uit Excel plakken — de kolomscheiding wordt automatisch herkend als Tab.\n\n## 6. Hoe kan ik de gegenereerde barcodes downloaden of opslaan?\n\nU kunt barcodes op de volgende manieren downloaden of opslaan:\n- Klik op de downloadknop boven het uitvoervak om te kiezen voor downloaden in PNG-, JPG-, GIF- of SVG-formaat.\n- Als er slechts één barcodeafbeelding is gegenereerd, wordt deze direct gedownload.\n- Als er meerdere barcodeafbeeldingen zijn gegenereerd, zal het systeem alle afbeeldingen in een ZIP-bestand verpakken voor download.\n\n## 7. Kan ik links naar de barcodes krijgen?\n\nJa, u kunt twee soorten links krijgen:\n1. Link naar de barcodeafbeelding: Klik op de knop \"Kopieer barcodelink\" om te kopiëren, in het formaat:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Link naar de huidige pagina: Klik op de knop \"Link naar deze pagina\" om te kopiëren, in het formaat:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nDeze links kunnen eenvoudig worden gedeeld of ingebed in andere applicaties.\n\n## 8. Zijn de door deze tool gegenereerde barcodes wettelijk geldig?\n\nDe door onze tool gegenereerde barcodes zijn technisch nauwkeurig, maar hun wettelijke geldigheid hangt af van uw beoogde gebruik en relevante voorschriften. Als u ze voor commerciële doeleinden nodig heeft, raden we aan om de relevante industriestandaarden en wettelijke vereisten te raadplegen.\n\n## 9. Wat is de kwaliteit van de gegenereerde barcodes? Zijn ze geschikt voor afdrukken?\n\nDe door onze tool gegenereerde barcodes hebben een hoge resolutiekwaliteit en zijn volledig geschikt voor afdrukken. We raden echter aan om kleinschalige tests uit te voeren voordat u ze formeel op grote schaal gebruikt, om er zeker van te zijn dat ze normaal kunnen worden gescand en herkend in uw specifieke toepassingsscenario's.\n\n## 10. Kan ik deze tool op mobiele apparaten gebruiken?\n\nJa, onze barcodegenerator is webgebaseerd en compatibel met verschillende apparaten. Of u nu een computer, tablet of smartphone gebruikt, u kunt eenvoudig toegang krijgen tot en gebruik maken van deze tool."
  }
}


================================================
FILE: messages/ru.json
================================================
{
  "Index": {
    "title": "Бесплатный генератор штрих-кодов - это онлайн-инструмент, который позволяет пользователям легко создавать различные форматы штрих-кодов и QR-кодов. Он поддерживает несколько типов кодирования и позволяет пользователям генерировать штрих-коды в режиме реального времени и пакетно, совершенно бесплатно."
  },
  "Barcode": {
    "title": "Бесплатный Генератор Штрих-кода {type}",
    "input": {
      "title": "Значения штрих-кода (по одному на строку)",
      "placeholder": "Введите значения, одно в строке",
      "caption-hint": "Чтобы отобразить пользовательский текст под штрих-кодом: нажмите Tab после каждого значения и введите текст. Или скопируйте 2 столбца из Excel (значение | текст) и вставьте напрямую."
    },
    "options": {
      "name": "Опции",
      "code-format": "Формат кода",
      "show-text": "Показать текст",
      "show-yes": "Да",
      "show-no": "Нет",
      "barcode-length": "Длина штрих-кода (мм)",
      "barcode-height": "Высота штрих-кода (мм)",
      "barcode-margin": "Поле штрих-кода (мм)",
      "locked-aspect-ratio": "Высота заблокирована на ширину для 2D-кодов."
    },
    "select-format": {
      "name": "Выберите формат штрих-кода",
      "search-placeholder": "Введите формат штрих-кода..."
    },
    "output": {
      "title": "Вывод"
    },
    "layout": {
      "name": "인쇄 레이아웃",
      "1x2": "1열 인쇄",
      "2x3": "2열 인쇄",
      "3x4": "3열 인쇄",
      "4x5": "4열 인쇄"
    }
  },
  "scroll": {
    "to-top": "Наверх",
    "setting": "Установить скорость прокрутки",
    "start-scroll": "Начать прокрутку",
    "pause-scroll": "Приостановить прокрутку"
  },
  "content": {
    "faq": "# Часто задаваемые вопросы о Бесплатном Генераторе Штрих-кодов\n\n## 1. Что такое Бесплатный Генератор Штрих-кодов?\n\nБесплатный Генератор Штрих-кодов - это онлайн-инструмент с открытым исходным кодом, который позволяет пользователям легко создавать различные форматы одномерных штрих-кодов. Он поддерживает несколько типов кодирования и позволяет пользователям генерировать штрих-коды в реальном времени и в массовом порядке, совершенно бесплатно.\n\n## 2. Как использовать этот генератор штрих-кодов?\n\nИспользование очень простое:\n- Введите содержимое, которое вы хотите закодировать, в поле ввода, где каждая строка соответствует одному штрих-коду.\n- Используйте вкладки для переключения между различными типами кодирования (такими как Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Выберите формат кодирования и стиль штрих-кода в опциях.\n- Система сгенерирует соответствующий штрих-код в реальном времени.\n\n## 3. Какие типы штрих-кодов поддерживает этот инструмент?\n\nНаш инструмент поддерживает различные форматы одномерных штрих-кодов, включая:\n- Code128 (включая Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (включая EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (включая Code39, Code39 Extended)\n- ITF (включая ITF-14)\n- MSI Plessey (включая Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (включая Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (включая ISBN, ISMN, ISSN)\n\nФорматы двумерных штрих-кодов, включая:\n- QR Code\n- Data Matrix\n- PDF417\n- Aztec Code\n\n## 4. Могу ли я генерировать несколько штрих-кодов одновременно?\n\nДа, этот инструмент поддерживает массовую генерацию. Просто введите одно содержимое штрих-кода на строку в поле ввода, и система сгенерирует соответствующий штрих-код для каждой строки. Для массово сгенерированных штрих-кодов вы можете нажать кнопку \"Начать прокрутку\" в правом нижнем углу, и страница будет автоматически прокручиваться, показывая все сгенерированные штрих-коды. Вы также можете использовать кнопку настроек ниже, чтобы настроить скорость прокрутки.\n\n## 5. Могу ли я настроить стиль сгенерированных штрих-кодов?\n\nДа. В разделе опций вы можете настроить следующие параметры:\n- Формат кодирования\n- Отображение текста (Да/Нет)\n- Длина штрих-кода (мм)\n- Высота штрих-кода (мм)\n- Пользовательский отображаемый текст: когда включено «Показывать текст», для каждого штрих-кода можно задать отдельный текст. После значения нажмите **Tab** и введите текст (напр. `1234567890\\t1234 567 890`). В пакетном режиме каждая строка может иметь свой текст. Можно также вставить два столбца напрямую из Excel — разделитель столбцов автоматически распознаётся как Tab.\n\n## 6. Как я могу скачать или сохранить сгенерированные штрих-коды?\n\nВы можете скачать или сохранить штрих-коды следующими способами:\n- Нажмите кнопку загрузки над полем вывода, чтобы выбрать загрузку в формате PNG, JPG, GIF или SVG.\n- Если сгенерировано только одно изображение штрих-кода, оно будет загружено напрямую.\n- Если сгенерировано несколько изображений штрих-кодов, система упакует все изображения в ZIP-файл для загрузки.\n\n## 7. Могу ли я получить ссылки на штрих-коды?\n\nДа, вы можете получить два типа ссылок:\n1. Ссылка на изображение штрих-кода: Нажмите кнопку \"Копировать ссылку на штрих-код\", чтобы скопировать в формате:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Ссылка на текущую страницу: Нажмите кнопку \"Ссылка на эту страницу\", чтобы скопировать в формате:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nЭти ссылки можно легко поделиться или встроить в другие приложения.\n\n## 8. Являются ли штрих-коды, сгенерированные этим инструментом, юридически действительными?\n\nШтрих-коды, сгенерированные нашим инструментом, технически точны, но их юридическая действительность зависит от вашего предполагаемого использования и соответствующих правил. Если вам нужно использовать их в коммерческих целях, мы рекомендуем проконсультироваться с соответствующими отраслевыми стандартами и юридическими требованиями.\n\n## 9. Какое качество у сгенерированных штрих-кодов? Подходят ли они для печати?\n\nШтрих-коды, сгенерированные нашим инструментом, имеют высокое разрешение и полностью подходят для печати. Однако мы рекомендуем провести небольшие тесты перед официальным крупномасштабным использованием, чтобы убедиться, что они могут нормально сканироваться и распознаваться в ваших конкретных сценариях применения.\n\n## 10. Могу ли я использовать этот инструмент на мобильных устройствах?\n\nДа, наш генератор штрих-кодов основан на веб-технологиях и совместим с различными устройствами. Независимо от того, используете ли вы компьютер, планшет или смартфон, вы можете легко получить доступ и использовать этот инструмент."
  }
}


================================================
FILE: messages/sv.json
================================================
{
  "Index": {
    "title": "Den kostnadsfria streckkodsgeneratorn är ett onlineverktyg som gör det enkelt för användare att skapa olika format av streckkoder och QR-koder. Den stöder flera kodningstyper och låter användare generera streckkoder i realtid och i bulk, helt gratis."
  },
  "Barcode": {
    "title": "Gratis {type} Streckkodsgenerator",
    "input": {
      "title": "Streckkodsvärden (en per rad)",
      "placeholder": "Ange värden, ett per rad",
      "caption-hint": "För att visa anpassad text under streckkoden: tryck på Tab-tangenten efter varje värde och skriv din text. Eller kopiera 2 kolumner från Excel (streckkodsvärde | visningstext) och klistra in direkt."
    },
    "options": {
      "name": "Alternativ",
      "code-format": "Kodformat",
      "show-text": "Visa text",
      "show-yes": "Ja",
      "show-no": "Nej",
      "barcode-length": "Streckkodens längd (mm)",
      "barcode-height": "Streckkodens höjd (mm)",
      "barcode-margin": "Streckkodsmarginal (mm)",
      "locked-aspect-ratio": "Höjden är låst till bredden för 2D-koder."
    },
    "select-format": {
      "name": "Välj streckkodformat",
      "search-placeholder": "Ange streckkodformat..."
    },
    "output": {
      "title": "Utdata"
    },
    "layout": {
      "name": "Utskriftslayout",
      "1x2": "Skriv ut 1 kolumn",
      "2x3": "Skriv ut 2 kolumner",
      "3x4": "Skriv ut 3 kolumner",
      "4x5": "Skriv ut 4 kolumner"
    }
  },
  "scroll": {
    "to-top": "Tillbaka till toppen",
    "setting": "Ställ in rullningshastighet",
    "start-scroll": "Börja rulla",
    "pause-scroll": "Pausa rullning"
  },
  "content": {
    "faq": "# Vanliga frågor om den Gratis Streckkodsgeneratorn\n\n## 1. Vad är den Gratis Streckkodsgeneratorn?\n\nDen Gratis Streckkodsgeneratorn är ett open-source onlineverktyg som låter användare enkelt skapa olika format av endimensionella streckkoder. Den stöder flera kodningstyper och låter användare generera streckkoder i realtid och i bulk, helt gratis.\n\n## 2. Hur använder jag denna streckkodsgenerator?\n\nAnvändningen är mycket enkel:\n- Ange innehållet du vill koda i inmatningsrutan, där varje rad motsvarar en streckkod.\n- Använd flikarna för att växla mellan olika kodningstyper (som Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar).\n- Välj kodningsformat och streckkodsstil i alternativen.\n- Systemet kommer att generera motsvarande streckkod i realtid.\n\n## 3. Vilka typer av streckkoder stöder detta verktyg?\n\nVårt verktyg stöder olika vanliga endimensionella streckkodformat, inklusive:\n- Code128 (inklusive Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (inklusive EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (inklusive Code39, Code39 Extended)\n- ITF (inklusive ITF-14)\n- MSI Plessey (inklusive Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (inklusive Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (inklusive ISBN, ISMN, ISSN)\n\nTvådimensionella streckkodformat, inklusive:\n- QR Code\n- Data Matrix\n- PDF417\n- Aztec Code\n\n## 4. Kan jag generera flera streckkoder samtidigt?\n\nJa, detta verktyg stöder massgeneration. Du behöver bara ange ett streckkodinnehåll per rad i inmatningsrutan, och systemet kommer att generera en motsvarande streckkod för varje rad. För massgenererade streckkoder kan du klicka på knappen \"Börja rulla\" i det nedre högra hörnet, och sidan kommer automatiskt att rulla för att visa alla genererade streckkoder. Du kan också använda inställningsknappen nedan för att justera rullningshastigheten.\n\n## 5. Kan jag anpassa stilen på de genererade streckkoderna?\n\nJa. I alternativavsnittet kan du justera följande parametrar:\n- Kodningsformat\n- Om text ska visas (Ja/Nej)\n- Streckkodslängd (mm)\n- Streckkodhöjd (mm)\n- Anpassad visningstext: när \"Visa text\" är aktiverat kan du ange en individuell visningstext för varje streckkod. Efter streckkodsvärdet trycker du på **Tab-tangenten** och skriver din text (t.ex. `1234567890\\t1234 567 890`). I bulkläge kan varje rad ha sin egen text. Du kan också klistra in två kolumner direkt från Excel — kolumnavgränsaren känns automatiskt igen som Tab.\n\n## 6. Hur laddar jag ner eller sparar de genererade streckkoderna?\n\nDu kan ladda ner eller spara streckkoderna på följande sätt:\n- Klicka på nedladdningsknappen ovanför utdatarutan för att välja att ladda ner i PNG-, JPG-, GIF- eller SVG-format.\n- Om endast en streckkodsbild genereras kommer den att laddas ner direkt.\n- Om flera streckkodbilder genereras kommer systemet att paketera alla bilder i en ZIP-fil för nedladdning.\n\n## 7. Kan jag få länkar till streckkoderna?\n\nJa, du kan få två typer av länkar:\n1. Länk till streckkodbilden: Klicka på knappen \"Kopiera streckkodlänk\" för att kopiera, i formatet:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. Länk till den aktuella sidan: Klicka på knappen \"Länk till denna sida\" för att kopiera, i formatet:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\nDessa länkar kan enkelt delas eller bäddas in i andra applikationer.\n\n## 8. Är streckkoderna som genereras av detta verktyg lagligt giltiga?\n\nStreckkoderna som genereras av vårt verktyg är tekniskt korrekta, men deras juridiska giltighet beror på din avsedda användning och relevanta föreskrifter. Om du behöver använda dem för kommersiella ändamål rekommenderar vi att du konsulterar relevanta branschstandarder och juridiska krav.\n\n## 9. Vilken kvalitet har de genererade streckkoderna? Är de lämpliga för utskrift?\n\nStreckkoderna som genereras av vårt verktyg har en högupplöst kvalitet och är helt lämpliga för utskrift. Vi rekommenderar dock att du utför småskaliga tester innan formell storskalig användning för att säkerställa att de kan skannas och kännas igen normalt i dina specifika applikationsscenarier.\n\n## 10. Kan jag använda detta verktyg på mobila enheter?\n\nJa, vår streckkodsgenerator är webbaserad och kompatibel med olika enheter. Oavsett om du använder en dator, surfplatta eller smartphone kan du enkelt komma åt och använda detta verktyg."
  }
}


================================================
FILE: messages/zh.json
================================================
{
  "Index": {
    "title": "免费条码生成器是一个在线工具,可以让用户轻松创建各种格式的条码和二维码。它支持多种编码类型,并允许用户实时批量生成条码,完全免费使用"
  },
  "Barcode": {
    "title": "免费 {type} 条码生成器",
    "input": {
      "title": "条形码值(每行一个)",
      "placeholder": "输入内容,每行一个",
      "caption-hint": "如需自定义条码下方显示文字:在每个值后按 Tab 键,然后输入显示文字。也可以直接从 Excel 中复制两列(条码内容 | 显示文字)粘贴进来。"
    },
    "options": {
      "name": "选项",
      "code-format": "编码格式",
      "show-text": "显示文本",
      "show-yes": "是",
      "show-no": "否",
      "barcode-length": "条码长度(mm)",
      "barcode-height": "条码高度(mm)",
      "barcode-margin": "条码间距(mm)",
      "locked-aspect-ratio": "二维码的高度已锁定为宽度。"
    },
    "select-format": {
      "name": "选择条码格式",
      "search-placeholder": "输入条码格式..."
    },
    "output": {
      "title": "输出"
    },
    "layout": {
      "name": "打印布局",
      "1x2": "打印1列",
      "2x3": "打印2列",
      "3x4": "打印3列",
      "4x5": "打印4列"
    }
  },
  "scroll": {
    "to-top": "返回顶部",
    "setting": "设置滚动速度",
    "start-scroll": "开始滚动",
    "pause-scroll": "暂停滚动"
  },
  "content": {
    "faq": "# 免费条码生成器 FAQ\n\n## 1. 什么是免费条码生成器?\n\n免费条码生成器是一个开源的在线工具,可以让用户轻松创建各种格式的一维条码。它支持多种编码类型,并允许用户实时批量生成条码,完全免费使用。\n\n## 2. 如何使用这个条码生成器?\n\n使用方法非常简单:\n- 在输入框中输入您想要编码的内容,每行对应一个条码。\n- 使用页签切换不同的编码类型(如Code128, EAN / UPC, Code39, ITF, MSI Plessey, Pharmacode, Codabar)。\n- 在options中选择编码格式和条码样式。\n- 系统会实时生成对应的条码。\n\n## 3. 这个工具支持哪些类型的条码?\n\n我们的工具支持多种常见的一维条码格式,包括:\n- Code128 (包括Code128A, Code128B, Code128C, GS1-128)\n- EAN / UPC (包括EAN-13, EAN-8, EAN-5, EAN-2, UPC-A, UPC-E)\n- Code39 (包括Code39, Code39 Extended)\n- ITF (包括ITF-14)\n- MSI Plessey (包括Mod 10, Mod 11, Mod 1010, Mod 1110)\n- Pharmacode\n- Codabar\n- GS1 DataBar (包括Omnidirectional, Limited, Expanded, Stacked)\n- Publishing (包括ISBN, ISMN, ISSN)\n\n二维码格式,包括:\n- QR Code\n- Data Matrix\n- PDF417\n- Aztec Code\n\n## 4. 我可以一次生成多个条码吗?\n\n是的,这个工具支持批量生成。您只需要在输入框中每行输入一个条码内容,系统就会为每行内容生成对应的条码。对于批量生成的条码,您可以点击右下角的\"开始滚动\"按钮,页面会自动滚动显示所有生成的条码。您还可以使用下方的设置按钮调节滚动速率。\n\n## 5. 生成的条码可以自定义样式吗?\n\n可以。在options选项中,您可以调整以下参数:\n- 编码格式\n- 是否显示文本(是/否)\n- 条码长度(mm)\n- 条码高度(mm)\n- 自定义显示文字:开启\"显示文字\"后,可以为每个条码单独设置显示文字。在条码内容后按 **Tab 键**,然后输入希望显示在条码下方的文字(例如 `1234567890\\t1234 567 890`)。批量生成时每行可以有各自不同的显示文字。也可以直接从 Excel 复制两列粘贴,列间自动识别为 Tab 分隔。\n\n## 6. 如何下载或保存生成的条码?\n\n您可以通过以下方式下载或保存条码:\n- 点击输出框上方的下载按钮,可以选择下载为PNG、JPG、GIF或SVG格式。\n- 如果只生成了一张条码图片,会直接下载该图片。\n- 如果生成了多张条码图片,系统会将所有图片打包成ZIP文件供下载。\n\n## 7. 我可以获取条码的链接吗?\n\n是的,您可以获取以下两种链接:\n1. 条码图片链接:点击\"Copy Barcode Link\"按钮复制,格式如:\n   https://barcode-maker.com/api/barcode/Code128/ABC-abc-1234\n2. 当前页面链接:点击\"Link to This Page\"按钮复制,格式如:\n   https://barcode-maker.com/en/Code128?data=ABC-abc-1234\n\n这些链接可以方便地分享或嵌入到其他应用中。\n\n## 8. 这个工具生成的条码是否有法律效力?\n\n我们的工具生成的条码在技术上是准确的,但是否具有法律效力取决于您的使用目的和相关法规。如果您需要用于商业用途,建议咨询相关行业标准和法律要求。\n\n## 9. 生成的条码质量如何?适合打印使用吗?\n\n我们的工具生成的条码具有高质量的分辨率,完全适合打印使用。不过,我们建议在正式大规模使用前,先进行小规模测试,确保在您的具体应用场景中可以正常扫描识别。\n\n## 10. 我可以在移动设备上使用这个工具吗?\n\n是的,我们的条码生成器是基于网页的,兼容各种设备。无论您使用电脑、平板还是智能手机,都可以方便地访问和使用这个工具。"
  }
}


================================================
FILE: next-sitemap.config.js
================================================
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL || 'https://barcode-maker.com',
  generateRobotsTxt: true, // (optional)
  // ...other options
}


================================================
FILE: next.config.mjs
================================================
import createNextIntlPlugin from 'next-intl/plugin'

const withNextIntl = createNextIntlPlugin()

/** @type {import('next').NextConfig} */
const nextConfig = {}

export default withNextIntl(nextConfig)


================================================
FILE: package.json
================================================
{
  "name": "barcode-maker",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "postbuild": "next-sitemap",
    "dev": "next dev",
    "build": "next build",
    "format": "prettier --write --config .prettierrc \"./**/*.{js,jsx,ts,tsx,json,scss,css}\"",
    "start": "next start",
    "lint": "next lint",
    "prepare": "is-ci || husky install && chmod ug+x .husky/*"
  },
  "dependencies": {
    "@next/third-parties": "^14.2.25",
    "@radix-ui/react-dialog": "^1.1.6",
    "@radix-ui/react-dropdown-menu": "^2.1.6",
    "@radix-ui/react-icons": "^1.3.2",
    "@radix-ui/react-label": "^2.1.2",
    "@radix-ui/react-radio-group": "^1.2.3",
    "@radix-ui/react-scroll-area": "^1.2.3",
    "@radix-ui/react-select": "^2.1.6",
    "@radix-ui/react-separator": "^1.1.2",
    "@radix-ui/react-slider": "^1.2.3",
    "@radix-ui/react-slot": "^1.1.2",
    "@radix-ui/react-switch": "^1.1.3",
    "@radix-ui/react-tabs": "^1.1.3",
    "@radix-ui/react-tooltip": "^1.1.8",
    "@tailwindcss/typography": "^0.5.16",
    "bwip-js": "^4.5.2",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "embla-carousel-react": "^8.5.2",
    "file-saver": "^2.0.5",
    "husky": "^9.1.7",
    "is-ci": "^3.0.1",
    "jsbarcode": "^3.11.6",
    "jszip": "^3.10.1",
    "lucide-react": "^0.424.0",
    "next": "14.1.0",
    "next-intl": "^3.26.5",
    "next-sitemap": "^4.2.3",
    "next-themes": "^0.3.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-markdown": "^9.1.0",
    "react-papaparse": "^4.4.0",
    "react-resizable-panels": "^2.1.7",
    "remark-gfm": "^4.0.1",
    "tailwind-merge": "^2.6.0",
    "tailwindcss-animate": "^1.0.7",
    "xlsx": "^0.18.5",
    "xmldom": "^0.6.0"
  },
  "devDependencies": {
    "@types/file-saver": "^2.0.7",
    "@types/node": "^20.17.24",
    "@types/react": "^18.3.18",
    "@types/react-dom": "^18.3.5",
    "@types/xmldom": "^0.1.34",
    "autoprefixer": "^10.4.21",
    "eslint": "^8.57.1",
    "eslint-config-next": "14.1.0",
    "postcss": "^8.5.3",
    "prettier": "^3.5.3",
    "prettier-plugin-tailwindcss": "^0.5.14",
    "tailwindcss": "^3.4.17",
    "typescript": "^5.8.2"
  }
}


================================================
FILE: postcss.config.js
================================================
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}


================================================
FILE: public/ads.txt
================================================
google.com, pub-1038944396101874, DIRECT, f08c47fec0942fa0

================================================
FILE: public/robots.txt
================================================
# *
User-agent: *
Allow: /

# Host
Host: https://barcode-maker.com

# Sitemaps
Sitemap: https://barcode-maker.com/sitemap.xml


================================================
FILE: public/site.webmanifest
================================================
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

================================================
FILE: public/sitemap-0.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>https://barcode-maker.com/en</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/zh</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/ja</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/de</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/fr</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/es</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/it</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/nl</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/sv</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/ko</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/ru</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/en/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/zh/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/ja/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/de/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/fr/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/es/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/it/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/nl/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/sv/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/ko/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://barcode-maker.com/ru/terms</loc><lastmod>2026-02-26T03:26:29.535Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
</urlset>

================================================
FILE: public/sitemap.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://barcode-maker.com/sitemap-0.xml</loc></sitemap>
</sitemapindex>

================================================
FILE: src/app/[locale]/[barcodeType]/page.tsx
================================================
import { useTranslations } from 'next-intl'
import { unstable_setRequestLocale } from 'next-intl/server'
import BarcodeGenerator from '@/components/barcode-generator'
import { notFound } from 'next/navigation'
import { locales } from '@/i18n'
import { barcodeTypes } from '@/config/barcode-types'
import MarkdownContent from '@/components/MarkdownContent'
import { SiteHeader } from '@/components/Header'
import Footer from '@/components/footer'

export default function BarcodePage({
  params: { locale, barcodeType },
  searchParams,
}: {
  params: { locale: string; barcodeType: string }
  searchParams: { [key: string]: string | string[] | undefined }
}) {
  unstable_setRequestLocale(locale)

  const t = useTranslations('content')

  // Validate barcodeType
  if (
    !barcodeTypes
      .flatMap((barcodeType) => barcodeType.types)
      .map((barcode) => barcode.value.toUpperCase())
      .includes(barcodeType.toUpperCase())
  ) {
    notFound()
  }

  const initialData =
    typeof searchParams.data === 'string' ? searchParams.data : ''

  return (
    <>
      <SiteHeader locale={locale} codeFormat={barcodeType} />
      <div className="flex justify-center">
        <div className="mx-4 w-full">
          <section className="grid items-center pb-8 ">
            <div className="mx-2">
              <BarcodeGenerator
                codeFormat={barcodeType}
                initialData={initialData}
                locale={locale}
              />
            </div>
          </section>
          <section className="container grid items-center gap-6 pb-8 pt-6 md:py-10">
            <MarkdownContent content={t('faq')} />
          </section>
        </div>
      </div>
      <Footer />
    </>
  )
}

export function generateStaticParams() {
  return locales.flatMap((locale) =>
    barcodeTypes
      .flatMap((barcodeType) => barcodeType.types)
      .map((barcode) => ({ locale, barcodeType: barcode.value })),
  )
}


================================================
FILE: src/app/[locale]/layout.tsx
================================================
import '@/styles/globals.css'
import { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { Locale, locales } from '@/i18n'
import { unstable_setRequestLocale } from 'next-intl/server'

import { getSiteConfig } from '@/config/site-i18n'
import { fontSans } from '@/lib/fonts'
import { cn } from '@/lib/utils'
import { TailwindIndicator } from '@/components/tailwind-indicator'
import { ThemeProvider } from '@/components/theme-provider'
import { NextIntlClientProvider } from 'next-intl'
import { notFound } from 'next/navigation'

const inter = Inter({ subsets: ['latin'] })

export function generateStaticParams() {
  return locales.map((locale) => ({ locale }))
}

export async function generateMetadata({
  params: { locale },
}: PageProps): Promise<Metadata> {
  const siteConfig = getSiteConfig(locale)
  return {
    title: {
      default: siteConfig.name,
      template: `%s - ${siteConfig.name}`,
    },
    description: siteConfig.description,
  }
}

export type PageProps = Readonly<{
  children: React.ReactNode
  params: { locale: Locale }
}>

export default async function RootLayout({
  children,
  params: { locale },
}: PageProps) {
  unstable_setRequestLocale(locale)
  let messages
  try {
    messages = (await import(`../../../messages/${locale}.json`)).default
  } catch (error) {
    notFound()
  }
  return (
    <html lang={locale} suppressHydrationWarning className="dark">
      <head>
        <script
          async
          src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1038944396101874"
          crossOrigin="anonymous"
        ></script>
      </head>
      <body
        className={cn(
          'min-h-screen bg-background font-sans antialiased',
          fontSans.variable,
          inter.className,
        )}
      >
        <ThemeProvider attribute="class" forcedTheme="dark">
          <NextIntlClientProvider locale={locale} messages={messages}>
            <div className="relative flex min-h-screen flex-col">
              {children}
            </div>
          </NextIntlClientProvider>
          <TailwindIndicator />
        </ThemeProvider>
      </body>
    </html>
  )
}


================================================
FILE: src/app/[locale]/page.tsx
================================================
import { unstable_setRequestLocale } from 'next-intl/server'
import { redirect } from 'next/navigation'

export default function IndexPage({
  params: { locale },
}: {
  params: { locale: string }
}) {
  unstable_setRequestLocale(locale)
  const defaultBarcodeType = 'Code128'
  redirect(`/${locale}/${defaultBarcodeType}`)
}


================================================
FILE: src/app/[locale]/terms/page.tsx
================================================
import { Metadata } from 'next'
import { getSiteConfig } from '@/config/site-i18n'

export async function generateMetadata({
  params,
}: {
  params: { locale: string }
}): Promise<Metadata> {
  const siteConfig = getSiteConfig(params.locale)
  return {
    title: `Terms and Privacy - ${siteConfig.name}`,
    description: 'Terms of Use and Privacy Policy',
  }
}

export default function TermsPage() {
  return (
    <main className="container mx-auto max-w-4xl px-4 py-8">
      <article className="prose prose-invert">
        <h1>Terms of Use</h1>
        <p className="text-muted-foreground">
          Last Updated: {new Date().toLocaleDateString()}
        </p>
        <p>
          Welcome to https://barcode-maker.com (the &ldquo;Website&rdquo;). By
          accessing or using this Website, you agree to comply with and be bound
          by the following Terms of Use. If you do not agree to these terms,
          please do not use the Website.
        </p>

        <section>
          <h2>1. Acceptance of Terms</h2>
          <p>
            By using the Website, you confirm that you are at least 18 years old
            or have the consent of a legal guardian. You agree to use the
            Website in accordance with these Terms of Use and all applicable
            laws and regulations.
          </p>
        </section>

        <section>
          <h2>2. Use of the Website</h2>
          <p>
            The Website provides a barcode generation service for personal,
            educational, or commercial use. You agree not to:
          </p>
          <ul>
            <li>Use the Website for any illegal or unauthorized purpose.</li>
            <li>
              Attempt to disrupt or interfere with the Website&apos;s
              functionality.
            </li>
            <li>
              Reverse engineer, decompile, or otherwise exploit the
              Website&apos;s code or content.
            </li>
          </ul>
        </section>

        <section>
          <h2>3. Intellectual Property</h2>
          <p>
            All content, including but not limited to text, graphics, logos, and
            software, is the property of barcode-maker.com or its licensors and
            is protected by intellectual property laws. You may not reproduce,
            distribute, or create derivative works without prior written
            consent.
          </p>
        </section>

        <section>
          <h2>4. User-Generated Content</h2>
          <p>
            If you upload or submit any content to the Website, you grant
            barcode-maker.com a non-exclusive, royalty-free, worldwide license
            to use, modify, and display such content for the purpose of
            providing the service.
          </p>
        </section>

        <section>
          <h2>5. Disclaimer of Warranties</h2>
          <p>
            The Website is provided &quot;as is&quot; without any warranties,
            express or implied. barcode-maker.com does not guarantee the
            accuracy, reliability, or completeness of the barcodes generated or
            the Website&apos;s functionality.
          </p>
        </section>

        <section>
          <h2>6. Limitation of Liability</h2>
          <p>
            barcode-maker.com shall not be liable for any direct, indirect,
            incidental, or consequential damages arising from the use or
            inability to use the Website, including but not limited to errors in
            barcode generation.
          </p>
        </section>

        <section>
          <h2>7. Changes to Terms</h2>
          <p>
            We reserve the right to modify these Terms of Use at any time.
            Continued use of the Website after changes constitutes your
            acceptance of the revised terms.
          </p>
        </section>

        <h1 className="mt-16">Privacy Policy</h1>
        <p className="text-muted-foreground">
          Last Updated: {new Date().toLocaleDateString()}
        </p>
        <p>
          At barcode-maker.com, we are committed to protecting your privacy.
          This Privacy Policy explains how we collect, use, and safeguard your
          information when you use our Website.
        </p>

        <section>
          <h2>1. Information We Collect</h2>
          <p>We may collect the following information:</p>
          <ul>
            <li>
              Personal Information: Name, email address, and other contact
              details if you voluntarily provide them.
            </li>
            <li>
              Usage Data: IP address, browser type, device information, and
              pages visited on the Website.
            </li>
            <li>
              Barcode Data: Information inputted to generate barcodes, which is
              not stored unless explicitly saved by you.
            </li>
          </ul>
        </section>

        <section>
          <h2>2. How We Use Your Information</h2>
          <p>We use your information to:</p>
          <ul>
            <li>Provide and improve the barcode generation service.</li>
            <li>Respond to your inquiries or requests.</li>
            <li>Analyze Website usage and trends.</li>
            <li>Send promotional emails (if you opt-in).</li>
          </ul>
        </section>

        <section>
          <h2>3. Sharing of Information</h2>
          <p>
            We do not sell, trade, or rent your personal information to third
            parties. We may share information with:
          </p>
          <ul>
            <li>Service providers who assist in operating the Website.</li>
            <li>Law enforcement or government agencies if required by law.</li>
          </ul>
        </section>

        <section>
          <h2>4. Cookies and Tracking Technologies</h2>
          <p>
            We use cookies and similar technologies to enhance your experience
            on the Website. You can disable cookies in your browser settings,
            but this may affect Website functionality.
          </p>
        </section>

        <section>
          <h2>5. Data Security</h2>
          <p>
            We implement reasonable security measures to protect your
            information. However, no method of transmission over the internet is
            100% secure, and we cannot guarantee absolute security.
          </p>
        </section>

        <section>
          <h2>6. Third-Party Links</h2>
          <p>
            The Website may contain links to third-party websites. We are not
            responsible for the privacy practices or content of these sites.
          </p>
        </section>
        <section>
          <h2>7. Children&apos;s Privacy</h2>
          <p>
            The Website is not intended for children under 13. We do not
            knowingly collect personal information from children.
          </p>
        </section>

        <section>
          <h2>8. Your Rights</h2>
          <p>Depending on your jurisdiction, you may have the right to:</p>
          <ul>
            <li>Access, update, or delete your personal information.</li>
            <li>Opt-out of receiving promotional emails.</li>
            <li>Object to the processing of your data.</li>
          </ul>
          <p>
            To exercise these rights, contact us at support@barcode-maker.com.
          </p>
        </section>

        <section>
          <h2>9. Changes to This Policy</h2>
          <p>
            We may update this Privacy Policy from time to time. Any changes
            will be posted on this page with an updated effective date.
          </p>
        </section>

        <section>
          <h2>10. Contact Us</h2>
          <p>
            If you have questions about this Privacy Policy, please contact us
            at:
          </p>
          <p>support@barcode-maker.com</p>
        </section>
      </article>
    </main>
  )
}


================================================
FILE: src/app/api/barcode/[code]/[data]/route.ts
================================================
import { NextRequest, NextResponse } from 'next/server'
import JsBarcode from 'jsbarcode'
import { DOMImplementation, XMLSerializer } from 'xmldom'
const bwipjs = require('bwip-js') as any
import { jsBarcodeSupportedFormats, checkQRCode } from '@/config/barcode-types'

export async function GET(
  request: NextRequest,
  { params }: { params: { code: string; data: string } },
) {
  console.log('API route hit:', request.url)
  console.log('Received parameters:', params)

  const { code, data } = params

  if (!code || !data) {
    return NextResponse.json({ error: 'Invalid parameters' }, { status: 400 })
  }

  try {
    let svgString = ''

    // Check if the format is supported by JsBarcode
    if (jsBarcodeSupportedFormats.includes(code.toUpperCase())) {
      // Use JsBarcode for supported formats
      const document = new DOMImplementation().createDocument(
        'http://www.w3.org/1999/xhtml',
        'html',
        null,
      )
      const svgNode = document.createElementNS(
        'http://www.w3.org/2000/svg',
        'svg',
      )

      JsBarcode(svgNode, data, {
        xmlDocument: document,
        format: code.toLowerCase(),
        width: 2,
        height: 100,
        displayValue: true,
      })

      svgString = new XMLSerializer().serializeToString(svgNode)
    } else {
      // Use BWIP-JS for other formats
      const scale = 2
      const bwipConfig = {
        bcid: code.toLowerCase(),
        text: data,
        scale: scale,
        height: 100 / (2.835 * scale), // Convert px to mm
        includetext: true,
        padding: 5 / scale,
        backgroundcolor: 'ffffff',
        barcolor: '000000',
      }

      try {
        svgString = bwipjs.toSVG(bwipConfig)
      } catch (error) {
        console.error('BWIP-JS generation error:', error)
        return NextResponse.json(
          { error: `Invalid barcode value for ${code}: ${data}` },
          { status: 400 },
        )
      }
    }

    console.log('Barcode generated successfully')

    return new NextResponse(svgString, {
      headers: {
        'Content-Type': 'image/svg+xml',
        'Cache-Control': 'public, max-age=31536000, immutable',
      },
    })
  } catch (error) {
    console.error('Error generating barcode:', error)
    return NextResponse.json(
      { error: 'Barcode generation failed' },
      { status: 500 },
    )
  }
}


================================================
FILE: src/app/error.tsx
================================================
'use client'

import { useEffect } from 'react'

type Props = {
  error: Error
  reset(): void
}

export default function Error({ error, reset }: Props) {
  useEffect(() => {
    console.error('Error details:', error)
    console.error('Error name:', error.name)
    console.error('Error message:', error.message)
    console.error('Error stack:', error.stack)
  }, [error])

  return (
    <html>
      <body>
        <div>
          <h1>An error occurred</h1>
          <button onClick={reset}>Try again</button>
        </div>
      </body>
    </html>
  )
}


================================================
FILE: src/app/layout.tsx
================================================
import '@/styles/globals.css'
import type { Metadata } from 'next'

export const metadata: Metadata = {
  icons: {
    icon: [
      { url: '/favicon.ico', sizes: 'any' },
      { url: '/favicon-16x16.png', sizes: '16x16' },
      { url: '/favicon-32x32.png', sizes: '32x32' },
    ],
    apple: [{ url: '/apple-touch-icon.png' }],
  },
  manifest: '/site.webmanifest',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <>{children}</>
}


================================================
FILE: src/app/not-found.tsx
================================================
import { buttonVariants } from '@/components/ui/button'

// Render the default Next.js 404 page when a route
// is requested that doesn't match the middleware and
// therefore doesn't have a locale associated with it.

export default function NotFound() {
  return (
    <html lang="en">
      <body>
        <main className="grid min-h-full place-items-center bg-white px-6 py-24 sm:py-32 lg:px-8">
          <div className="text-center">
            <p className="text-base font-semibold ">404</p>
            <h1 className="mt-4 text-3xl font-bold tracking-tight text-gray-900 sm:text-5xl">
              Page not found
            </h1>
            <p className="mt-6 text-base leading-7 text-gray-600">
              Sorry, we couldn’t find the page you’re looking for.
            </p>
            <div className="mt-10 flex items-center justify-center gap-x-6">
              <a
                href="/"
                className={buttonVariants({
                  variant: 'outline',
                })}
              >
                Go back home
              </a>
            </div>
          </div>
        </main>
      </body>
    </html>
  )
}


================================================
FILE: src/components/Header.tsx
================================================
import Link from 'next/link'

import { getSiteConfig } from '@/config/site-i18n'
import { ThemeToggle } from '@/components/theme-toggle'
import { Locale } from '@/i18n'
import { LanguageToggle } from './language-toggle'
import { Icons } from '@/components/icons'
import { useTranslations } from 'next-intl'

interface SiteHeaderProps {
  locale: Locale
  codeFormat: string
}

export function SiteHeader({ locale, codeFormat }: SiteHeaderProps) {
  const t = useTranslations('Barcode')
  return (
    <header className="w-full bg-background">
      <div className="container flex h-16 items-center justify-between space-x-4">
        <div className="flex items-center">
          <Link href={`/${locale}`} className="flex items-center space-x-2">
            <h1 className="max-w-[66vw] truncate text-2xl font-bold normal-case sm:max-w-full sm:text-3xl">
              {t('title', { type: codeFormat })}
            </h1>
          </Link>
        </div>
        <div className="flex items-center space-x-4">
          <Link
            href="https://github.com/LeonZeng919/barcode-generator"
            target="_blank"
            rel="noopener noreferrer"
            className="text-foreground hover:text-primary"
          >
            <Icons.gitHub className="h-5 w-5" />
            <span className="sr-only">GitHub</span>
          </Link>
          {/* <ThemeToggle /> */}
          <LanguageToggle locale={locale} />
        </div>
      </div>
    </header>
  )
}


================================================
FILE: src/components/MarkdownContent.tsx
================================================
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'

const MarkdownContent = ({ content }: { content: string }) => {
  return (
    <div className="prose prose-sm dark:prose-invert sm:prose lg:prose-lg xl:prose-xl prose-headings:text-gray-800 prose-p:text-gray-600 prose-a:text-blue-600 prose-strong:text-gray-900 prose-code:text-gray-800 prose-pre:bg-gray-100 dark:prose-headings:text-gray-100 dark:prose-p:text-gray-300 dark:prose-a:text-blue-400 dark:prose-strong:text-gray-100 dark:prose-code:text-gray-200 dark:prose-pre:bg-gray-800">
      <ReactMarkdown remarkPlugins={[remarkGfm]}>{content}</ReactMarkdown>
    </div>
  )
}

export default MarkdownContent


================================================
FILE: src/components/barcode-generator/BarcodeCarousel.tsx
================================================
'use client'

import React, { useState, useMemo } from 'react'
import Link from 'next/link'
import Image from 'next/image'
import { usePathname } from 'next/navigation'
import { barcodeTypes } from '@/config/barcode-types'
import { cn } from '@/lib/utils'
import { ScrollArea } from '@/components/ui/scroll-area'
import { Input } from '@/components/ui/input'
import { Card } from '@/components/ui/card'
import { Separator } from '../ui/separator'
import { useTranslations } from 'next-intl'
import { Search } from 'lucide-react' // Added this line for the search icon

interface BarcodeCarouselProps {
  isCollapsed: boolean
}

export function BarcodeCarousel({ isCollapsed }: BarcodeCarouselProps) {
  const pathname = usePathname()
  const locale = pathname.split('/')[1]
  const currentCodeFormat = pathname.split('/')[2]

  const [searchTerm, setSearchTerm] = useState('')

  const { initialIndex, flattenedTypes } = useMemo(() => {
    const flattenedTypes = barcodeTypes.flatMap((category, index) =>
      category.types.map((type) => ({ ...type, categoryIndex: index })),
    )
    const typeIndex = flattenedTypes.findIndex(
      (type) => type.value?.toUpperCase() === currentCodeFormat?.toUpperCase(),
    )
    const initialIndex =
      typeIndex !== -1 ? flattenedTypes[typeIndex].categoryIndex : 0
    return { initialIndex, flattenedTypes }
  }, [currentCodeFormat])

  const [selectedIndex, setSelectedIndex] = useState(initialIndex)

  const filteredTypes = useMemo(() => {
    return barcodeTypes
      .map((category) => ({
        ...category,
        types: category.types.filter(
          (type) =>
            (type.name?.toLowerCase() || '').includes(
              searchTerm.toLowerCase(),
            ) ||
            (type.value?.toLowerCase() || '').includes(
              searchTerm.toLowerCase(),
            ),
        ),
      }))
      .filter((category) => category.types.length > 0)
  }, [searchTerm])

  const t = useTranslations('Barcode')

  return (
    <div className={cn('flex-1 ', isCollapsed && 'hidden')}>
      <span className="label-text text-lg font-semibold">
        {t('select-format.name')}
      </span>
      <Separator className="my-2" />
      <div className="relative my-4">
        <Input
          type="text"
          placeholder={t('select-format.search-placeholder')}
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          className="bg-white pl-10"
        />
        <Search className="absolute left-2 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400" />
      </div>
      <ScrollArea className=" h-[calc(82vh-6rem)] pr-3">
        <nav>
          {filteredTypes.map((category, index) => (
            <div key={category.name} className="mb-4">
              <h3 className="px-3 py-2 text-sm font-medium text-gray-500">
                {category.name}
              </h3>
              <ul className="grid grid-cols-1 gap-2">
                {category.types.map((type) => (
                  <li key={type.value}>
                    <Link href={`/${locale}/${type.value}`}>
                      <Card
                        className={cn(
                          'flex flex-col items-center justify-center bg-gray-100 p-1 text-gray-700 transition-colors',
                          currentCodeFormat?.toUpperCase() ===
                            type.value.toUpperCase()
                            ? 'bg-indigo-600 text-white' // Changed to blue-purple background and white text
                            : 'hover:bg-indigo-600 hover:text-white',
                        )}
                      >
                        <div className="relative flex h-12 w-full items-center justify-center">
                          <Image
                            src={`/barcode/barcode-${type.value}.svg`}
                            alt="Barcode icon"
                            fill
                            className="mt-1 h-12 w-12"
                          />
                        </div>
                        <h4 className="text-center text-sm font-medium">
                          {type.name}
                        </h4>
                      </Card>
                    </Link>
                  </li>
                ))}
              </ul>
            </div>
          ))}
        </nav>
      </ScrollArea>
    </div>
  )
}


================================================
FILE: src/components/barcode-generator/BarcodeComponents.tsx
================================================
import React from 'react'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { Button } from '@/components/ui/button'
import { Label } from '@/components/ui/label'
import { Copy, Lock, Printer } from 'lucide-react'
import { useBarcodeContext } from './BarcodeContext'

import { useTranslations } from 'next-intl'
import { ShareButton } from './share-button'
import { Switch } from '@/components/ui/switch'
import ScrollControls from './ScrollControls'
import ImportData from './ImportData'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { lockHeight } from '@/config/barcode-types'

const LayoutSelector: React.FC<{
  onLayoutChange: (layout: string) => void
}> = ({ onLayoutChange }) => {
  const t = useTranslations('Barcode')
  return (
    <Select onValueChange={onLayoutChange}>
      <SelectTrigger className="w-[180px]">
        <SelectValue placeholder={t('layout.name')} defaultValue={'3x4'} />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="1x2">{t('layout.1x2')}</SelectItem>
        <SelectItem value="2x3">{t('layout.2x3')}</SelectItem>
        <SelectItem value="3x4">{t('layout.3x4')}</SelectItem>
        <SelectItem value="4x5">{t('layout.4x5')}</SelectItem>
      </SelectContent>
    </Select>
  )
}

export const InputComponent: React.FC = () => {
  const t = useTranslations('Barcode')
  const { input, setInput, showText } = useBarcodeContext()
  return (
    <div className="form-control">
      <label htmlFor="input" className="label">
        <div className="flex justify-between">
          <span className="label-text text-lg font-semibold">
            {t('input.title')}
          </span>
          <span className="label-text-alt flex gap-4">
            <ImportData setInput={setInput} />
            <Button
              size="icon"
              variant="ghost"
              onClick={() => navigator.clipboard.writeText(input)}
            >
              <Copy className="h-5 w-5" />
            </Button>
          </span>
        </div>
      </label>
      <Textarea
        id="input"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        className="h-28 bg-white font-mono text-sm"
        placeholder={t('input.placeholder')}
        onKeyDown={(e) => {
          if (e.key === 'Tab') {
            e.preventDefault()
            const el = e.currentTarget
            const start = el.selectionStart ?? 0
            const end = el.selectionEnd ?? 0
            const newValue = input.slice(0, start) + '\t' + input.slice(end)
            setInput(newValue)
            // Restore cursor position after React re-renders
            requestAnimationFrame(() => {
              el.selectionStart = start + 1
              el.selectionEnd = start + 1
            })
          }
        }}
      />
      {showText && (
        <p className="mt-1 text-xs text-gray-500">{t('input.caption-hint')}</p>
      )}
    </div>
  )
}

interface PrintButtonProps {
  output: string[]
  layout: string
}

export const PrintButton: React.FC<PrintButtonProps> = ({ output, layout }) => {
  const handlePrint = () => {
    const [cols] = layout.split('x').map(Number)
    const printContent = `
      <html>
        <head>
          <title>Barcode Print</title>
          <style>
            body { font-family: Arial, sans-serif; }
            .barcode-container { 
              display: grid;
              grid-template-columns: repeat(${cols}, 1fr);
              gap: 10px;
              page-break-inside: avoid;
            }
            .barcode-item { text-align: center; }
            @media print {
              @page { size: A4; margin: 0; }
              body { margin: 1cm; }
            }
          </style>
        </head>
        <body>
          <div class="barcode-container">${output.join('')}</div>
        </body>
      </html>
    `

    const iframe = document.createElement('iframe')
    iframe.style.display = 'none'
    document.body.appendChild(iframe)

    const iframeDoc = iframe.contentWindow?.document
    if (iframeDoc) {
      iframeDoc.open()
      iframeDoc.write(printContent)
      iframeDoc.close()

      iframe.onload = () => {
        iframe.contentWindow?.print()
        setTimeout(() => {
          document.body.removeChild(iframe)
        }, 100)
      }
    }
  }

  return (
    <Button size="icon" variant="ghost" onClick={handlePrint}>
      <Printer className="h-5 w-5" />
    </Button>
  )
}

export const OutputComponent: React.FC = () => {
  const { output } = useBarcodeContext()
  const outputRef = React.useRef<HTMLDivElement>(null)
  const t = useTranslations('Barcode')
  const [layout, setLayout] = React.useState('3x4')

  // Create a numbered output
  const numberedOutput = output
    .map((svg, index) => {
      const numberSpan =
        output.length > 1
          ? `<span class="barcode-number mr-2">${index + 1}.</span>`
          : ''

      return `<div class="barcode-item flex items-center mb-2">
      ${numberSpan}
      <div class="barcode-svg">${svg}</div>
    </div>`
    })
    .join('')

  return (
    <div className="form-control flex flex-col">
      <label htmlFor="output" className="label">
        <div className="flex justify-between">
          <span className="label-text text-lg font-semibold">
            {t('output.title')}
          </span>
          <span className="label-text-alt flex items-center justify-between gap-4">
            <ShareButton size="icon" variant="ghost" />
            <PrintButton output={output} layout={layout} />
            <LayoutSelector onLayoutChange={setLayout} />
            <ScrollControls outputRef={outputRef} />
          </span>
        </div>
      </label>
      <div
        ref={outputRef}
        id="output"
        className="flex aspect-square max-h-[480px] flex-col items-center overflow-auto rounded-md border bg-blue-100 bg-opacity-30 p-3 text-sm shadow-sm"
        dangerouslySetInnerHTML={{ __html: numberedOutput }}
      />
    </div>
  )
}

export const OptionsComponent: React.FC = () => {
  const {
    barcodeLength,
    setBarcodeLength,
    barcodeHeight,
    setBarcodeHeight,
    showText,
    setShowText,
    barcodeMargin,
    setBarcodeMargin,
    codeFormat,
  } = useBarcodeContext()
  const t = useTranslations('Barcode')

  // 检查是否是二维码类型
  const isLockHeight = lockHeight(codeFormat)

  // 当条形码宽度改变且是二维码时,自动设置高度等于宽度
  React.useEffect(() => {
    if (isLockHeight) {
      setBarcodeHeight(barcodeLength)
    }
  }, [barcodeLength, isLockHeight, setBarcodeHeight])

  // 处理宽度变化
  const handleLengthChange = (value: number) => {
    setBarcodeLength(value)
    if (isLockHeight) {
      setBarcodeHeight(value)
    }
  }

  return (
    <div>
      <div className="flex justify-between">
        <span className="label-text text-lg font-semibold">
          {t('options.name')}
        </span>
      </div>

      <div className="xs:text-sm rounded-md bg-transparent p-3 text-xs shadow-sm">
        <div className="grid grid-cols-1 gap-2">
          <div className="md:col-span-1">
            <div className="flex items-center justify-between">
              <Label htmlFor="showText" className="text-sm font-medium">
                {t('options.show-text')}
              </Label>
              <Switch
                id="showText"
                checked={showText}
                onCheckedChange={setShowText}
                className="border-gray-400"
              />
            </div>
          </div>
          <div className="md:col-span-1">
            <Label htmlFor="barcodeLength">{t('options.barcode-length')}</Label>
            <Input
              id="barcodeLength"
              type="number"
              value={barcodeLength}
              onChange={(e) => handleLengthChange(Number(e.target.value))}
              className="bg-white"
            />
          </div>
          <div className="relative md:col-span-1">
            <Label htmlFor="barcodeHeight">{t('options.barcode-height')}</Label>
            <div className="relative">
              <Input
                id="barcodeHeight"
                type="number"
                value={barcodeHeight}
                className={`bg-white ${isLockHeight ? 'pr-10' : ''}`}
                onChange={(e) => setBarcodeHeight(Number(e.target.value))}
                disabled={isLockHeight}
              />
              {isLockHeight && (
                <div className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500">
                  <Lock className="h-4 w-4" />
                </div>
              )}
            </div>
            {isLockHeight && (
              <p className="mt-1 text-xs text-gray-500">
                {t('options.locked-aspect-ratio')}
              </p>
            )}
          </div>
          <div className="md:col-span-1">
            <Label htmlFor="barcodeMargin">{t('options.barcode-margin')}</Label>
            <Input
              id="barcodeMargin"
              type="number"
              value={barcodeMargin}
              className="bg-white"
              onChange={(e) => setBarcodeMargin(Number(e.target.value))}
            />
          </div>
        </div>
      </div>
    </div>
  )
}


================================================
FILE: src/components/barcode-generator/BarcodeContext.tsx
================================================
'use client'
import { barcodeTypes, checkQRCode } from '@/config/barcode-types'
import { ImageFormat } from '@/types/image'
import React, {
  createContext,
  useState,
  useContext,
  useMemo,
  useEffect,
} from 'react'

interface BarcodeContextType {
  input: string
  setInput: (input: string) => void
  output: string[]
  setOutput: (output: string[]) => void
  barcodeLength: number
  setBarcodeLength: (length: number) => void
  barcodeHeight: number
  setBarcodeHeight: (height: number) => void
  showText: boolean
  setShowText: (show: boolean) => void
  showOptions: boolean
  setShowOptions: (show: boolean) => void
  codeFormat: string
  setCodeFormat: (format: string) => void
  imageFormat: ImageFormat
  setImageFormat: (format: ImageFormat) => void
  barcodeMargin: number
  setBarcodeMargin: (margin: number) => void
}

interface FormatSettings {
  barcodeLength: number
  barcodeHeight: number
  showText: boolean
  barcodeMargin: number
}

interface SavedState {
  // 旧版本的全局配置
  barcodeLength?: number
  barcodeHeight?: number
  showText?: boolean
  imageFormat?: ImageFormat
  barcodeMargin?: number

  // 新版本的按格式配置
  formatSettings?: {
    [format: string]: FormatSettings
  }

  // 全局配置
  globalSettings?: {
    imageFormat: ImageFormat
  }
}

const BarcodeContext = createContext<BarcodeContextType | undefined>(undefined)

const LOCAL_STORAGE_KEY = 'barcodeSettings'

const saveStateToLocalStorage = (state: SavedState) => {
  localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(state))
}

const getStateFromLocalStorage = (): SavedState | null => {
  if (typeof window !== 'undefined') {
    const savedState = localStorage.getItem(LOCAL_STORAGE_KEY)
    return savedState ? JSON.parse(savedState) : null
  }
  return null
}

// 默认配置
const DEFAULT_SETTINGS: FormatSettings = {
  barcodeLength: 260,
  barcodeHeight: 80,
  showText: true,
  barcodeMargin: 10,
}

// 获取指定格式的默认设置
const getDefaultSettingsForFormat = (format: string): FormatSettings => {
  const isQRCode = checkQRCode(format)

  return {
    ...DEFAULT_SETTINGS,
    // 如果是二维码,默认高度等于宽度
    barcodeHeight: isQRCode
      ? DEFAULT_SETTINGS.barcodeLength
      : DEFAULT_SETTINGS.barcodeHeight,
  }
}

export const BarcodeProvider: React.FC<{
  children: React.ReactNode
  value: {
    initCodeFormat: string
    initialData: string
  }
}> = ({ children, value: { initCodeFormat, initialData } }) => {
  const savedState = getStateFromLocalStorage()

  // 初始化格式设置存储
  const [formatSettings, setFormatSettings] = useState<{
    [format: string]: FormatSettings
  }>(() => {
    // 如果有新版本的按格式配置,则使用它
    if (savedState?.formatSettings) {
      return savedState.formatSettings
    }

    // 否则,创建一个新的配置对象,并将旧版本的全局配置作为默认值
    const newFormatSettings: { [format: string]: FormatSettings } = {}

    // 如果有旧版本的全局配置,将其作为默认值
    if (savedState?.barcodeLength !== undefined) {
      const oldGlobalSettings: FormatSettings = {
        barcodeLength:
          savedState.barcodeLength || DEFAULT_SETTINGS.barcodeLength,
        barcodeHeight:
          savedState.barcodeHeight || DEFAULT_SETTINGS.barcodeHeight,
        showText: savedState.showText ?? DEFAULT_SETTINGS.showText,
        barcodeMargin:
          savedState.barcodeMargin || DEFAULT_SETTINGS.barcodeMargin,
      }

      // 为初始格式设置旧版本的全局配置
      newFormatSettings[initCodeFormat] = oldGlobalSettings
    } else {
      // 否则,使用默认配置
      newFormatSettings[initCodeFormat] =
        getDefaultSettingsForFormat(initCodeFormat)
    }

    return newFormatSettings
  })

  const initData =
    initialData ||
    barcodeTypes
      .flatMap((barcode) => barcode.types)
      .findLast((barcode) => barcode.value === initCodeFormat)?.initData ||
    ''

  const [input, setInput] = useState<string>(initData)
  const [output, setOutput] = useState<string[]>([])
  const [showOptions, setShowOptions] = useState<boolean>(false)
  const [codeFormat, setCodeFormat] = useState(initCodeFormat)
  const [imageFormat, setImageFormat] = useState<ImageFormat>(
    savedState?.globalSettings?.imageFormat || savedState?.imageFormat || 'svg',
  )

  // 获取当前格式的设置
  const getCurrentFormatSettings = (): FormatSettings => {
    // 如果当前格式没有配置,则创建一个默认配置
    if (!formatSettings[codeFormat]) {
      return getDefaultSettingsForFormat(codeFormat)
    }
    return formatSettings[codeFormat]
  }

  // 当前格式的设置
  const currentSettings = getCurrentFormatSettings()

  // 单独的状态,从当前格式设置中获取
  const [barcodeLength, setBarcodeLength] = useState<number>(
    currentSettings.barcodeLength,
  )
  const [barcodeHeight, setBarcodeHeight] = useState<number>(
    currentSettings.barcodeHeight,
  )
  const [showText, setShowText] = useState<boolean>(currentSettings.showText)
  const [barcodeMargin, setBarcodeMargin] = useState<number>(
    currentSettings.barcodeMargin,
  )

  // 当编码格式改变时,更新设置
  useEffect(() => {
    const settings =
      formatSettings[codeFormat] || getDefaultSettingsForFormat(codeFormat)
    setBarcodeLength(settings.barcodeLength)
    setBarcodeHeight(settings.barcodeHeight)
    setShowText(settings.showText)
    setBarcodeMargin(settings.barcodeMargin)
  }, [codeFormat, formatSettings])

  // 当设置改变时,更新格式设置
  useEffect(() => {
    setFormatSettings((prev) => ({
      ...prev,
      [codeFormat]: {
        barcodeLength,
        barcodeHeight,
        showText,
        barcodeMargin,
      },
    }))
  }, [codeFormat, barcodeLength, barcodeHeight, showText, barcodeMargin])

  // 保存设置到本地存储
  useEffect(() => {
    // 创建新的保存状态,包含格式设置和全局设置
    const newSavedState: SavedState = {
      formatSettings,
      globalSettings: {
        imageFormat,
      },
    }

    saveStateToLocalStorage(newSavedState)
  }, [formatSettings, imageFormat])

  const value = useMemo(
    () => ({
      input,
      setInput,
      output,
      setOutput,
      barcodeLength,
      setBarcodeLength,
      barcodeHeight,
      setBarcodeHeight,
      showText,
      setShowText,
      showOptions,
      setShowOptions,
      codeFormat,
      setCodeFormat,
      imageFormat,
      setImageFormat,
      barcodeMargin,
      setBarcodeMargin,
    }),
    [
      input,
      output,
      barcodeLength,
      barcodeHeight,
      showText,
      showOptions,
      codeFormat,
      imageFormat,
      barcodeMargin,
    ],
  )

  return (
    <BarcodeContext.Provider value={value}>{children}</BarcodeContext.Provider>
  )
}

export const useBarcodeContext = () => {
  const context = useContext(BarcodeContext)
  if (context === undefined) {
    throw new Error('useBarcodeContext must be used within a BarcodeProvider')
  }
  return context
}


================================================
FILE: src/components/barcode-generator/DownloadBarcodes.tsx
================================================
import React, { useCallback } from 'react'
import { Button } from '@/components/ui/button'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { useBarcodeContext } from './BarcodeContext'
import JsBarcode from 'jsbarcode'
import JSZip from 'jszip'
import FileSaver from 'file-saver'
import { Download } from 'lucide-react'
import { ImageFormat } from '@/types/image'
import { checkQRCode, jsBarcodeSupportedFormats } from '@/config/barcode-types'
import { parseLine } from '@/lib/parseLine'
const bwipjs = require('bwip-js') as any

export const DownloadBarcodes: React.FC = () => {
  const {
    input,
    barcodeLength,
    barcodeHeight,
    showText,
    codeFormat,
    imageFormat,
    setImageFormat,
    barcodeMargin,
  } = useBarcodeContext()

  const generateBarcode = useCallback(
    (parsed: {
      barcodeValue: string
      displayText: string | undefined
    }): Promise<Blob | string> =>
      new Promise((resolve, reject) => {
        const { barcodeValue: value, displayText } = parsed
        const scaleFactor = 1

        try {
          if (jsBarcodeSupportedFormats.includes(codeFormat.toUpperCase())) {
            // JsBarcode 配置
            const jsBarcodeConfig: Record<string, unknown> = {
              format: codeFormat.toUpperCase(),
              width: 2,
              height: barcodeHeight,
              displayValue: showText,
              font: 'Arial',
              fontSize: 20,
              textMargin: 2,
              margin: barcodeMargin,
              background: '#ffffff',
              lineColor: '#000000',
              textAlign: 'center',
              textPosition: 'bottom',
            }

            // Override display text when a custom caption is provided
            if (showText && displayText !== undefined) {
              jsBarcodeConfig.text = displayText
            }

            if (imageFormat === 'svg') {
              const svg = document.createElementNS(
                'http://www.w3.org/2000/svg',
                'svg',
              )

              try {
                JsBarcode(svg, value, jsBarcodeConfig)
                svg.setAttribute('width', `${barcodeLength}`)
                svg.setAttribute('height', `${barcodeHeight}`)
                resolve(new XMLSerializer().serializeToString(svg))
              } catch (error) {
                console.error('JsBarcode generation error:', error)
                reject(
                  new Error(
                    `Invalid barcode value for ${codeFormat}: ${value}`,
                  ),
                )
              }
            } else {
              const canvas = document.createElement('canvas')
              canvas.width = barcodeLength * scaleFactor
              canvas.height = barcodeHeight * scaleFactor

              try {
                JsBarcode(canvas, value, {
                  ...jsBarcodeConfig,
                  width: 2 * scaleFactor,
                  height: barcodeHeight * scaleFactor,
                  fontSize: 20 * scaleFactor,
                  textMargin: 2 * scaleFactor,
                  margin: barcodeMargin * scaleFactor,
                })

                canvas.toBlob(
                  (blob) => {
                    if (blob) {
                      resolve(blob)
                    } else {
                      reject(new Error('Failed to generate barcode image'))
                    }
                  },
                  `image/${imageFormat}`,
                  imageFormat === 'jpg' ? 0.9 : 1,
                )
              } catch (error) {
                console.error('JsBarcode generation error:', error)
                reject(
                  new Error(
                    `Invalid barcode value for ${codeFormat}: ${value}`,
                  ),
                )
              }
            }
          } else {
            // BWIP-JS 配置
            const scale = 2
            const MM_TO_PX = 2.835 * scale // 72 dpi / 25.4 mm/in
            const heightInMM = barcodeHeight / MM_TO_PX
            const widthInMM = barcodeLength / MM_TO_PX
            const marginInMM = barcodeMargin / scale

            // 检查是否是二维码类型
            const isQRCode = checkQRCode(codeFormat)

            const fontSize = 15 // 固定字体大小为15px
            const textMargin = 2 // 文本与条码之间的间距

            const bwipConfig: Record<string, unknown> = {
              bcid: codeFormat.toLowerCase(),
              text: value,
              scale: scale,
              height: heightInMM,
              width: widthInMM,
              includetext: showText,
              padding: marginInMM,
              paddingbottom:
                isQRCode && showText
                  ? marginInMM + fontSize + textMargin
                  : marginInMM,
              backgroundcolor: 'ffffff',
              barcolor: '000000',
            }

            // Override display text for bwip-js (alttext)
            if (showText && displayText !== undefined) {
              bwipConfig.alttext = displayText
            }

            try {
              if (imageFormat === 'svg') {
                const svgString = bwipjs.toSVG(bwipConfig)
                const parser = new DOMParser()
                const doc = parser.parseFromString(svgString, 'image/svg+xml')
                const svg = doc.documentElement

                svg.setAttribute('width', `${barcodeLength}`)
                svg.setAttribute(
                  'height',
                  `${isQRCode && showText ? barcodeHeight + fontSize + textMargin : barcodeHeight}`,
                )

                if (isQRCode && showText) {
                  // 使用 Canvas 测量文本宽度
                  const canvas = document.createElement('canvas')
                  const ctx = canvas.getContext('2d')

                  if (ctx === null) {
                    console.warn('Canvas 2D context not supported')
                    return `<div class="barcode-item">${svg.outerHTML}</div>`
                  }

                  ctx.font = `${fontSize}px Arial`
                  const labelText =
                    displayText !== undefined ? displayText : value
                  const textWidth = ctx.measureText(labelText).width

                  // 计算缩放比例
                  const availableWidth = barcodeLength - marginInMM * 2
                  const scaleRatio = Math.min(1, availableWidth / textWidth)

                  // 创建text元素
                  const text = document.createElementNS(
                    'http://www.w3.org/2000/svg',
                    'text',
                  )
                  text.setAttribute('x', `${marginInMM + barcodeLength / 2}`)
                  text.setAttribute(
                    'y',
                    `${barcodeHeight + marginInMM * 2 + fontSize + textMargin}`,
                  )
                  text.setAttribute('text-anchor', 'middle')
                  text.setAttribute('font-family', 'Arial')
                  text.setAttribute('font-size', `${fontSize}`)
                  text.setAttribute('transform', `scale(${scaleRatio})`)
                  text.setAttribute(
                    'transform-origin',
                    `${marginInMM + barcodeLength / 2} ${barcodeHeight + marginInMM * 2 + fontSize / 2 + textMargin}`,
                  )
                  text.setAttribute('fill', '#000000')

                  text.textContent = labelText
                  svg.appendChild(text)

                  svg.setAttribute(
                    'height',
                    `${barcodeHeight + fontSize + textMargin + marginInMM * 2}`,
                  )
                }
                resolve(new XMLSerializer().serializeToString(svg))
              } else {
                if (isQRCode && showText) {
                  // 创建临时canvas来测量文本宽度
                  const tempCanvas = document.createElement('canvas')
                  const tempCtx = tempCanvas.getContext('2d')

                  if (!tempCtx) {
                    console.warn('Canvas 2D context not supported')
                    reject(new Error('Canvas 2D context not supported'))
                    return
                  }

                  // 测量文本宽度
                  const labelText =
                    displayText !== undefined ? displayText : value
                  tempCtx.font = `${fontSize}px Arial`
                  const textWidth = tempCtx.measureText(labelText).width
                  const requiredWidth = textWidth + barcodeMargin * 2 // 文本需要的宽度(包含边距)

                  // 计算缩放比例 - 如果文本宽度大于原始宽度,需要放大整体尺寸
                  const scaleRatio = Math.max(
                    1,
                    Math.ceil(requiredWidth / barcodeLength),
                  )

                  // 创建最终的canvas,尺寸根据缩放比例调整
                  const finalCanvas = document.createElement('canvas')
                  const ctx = finalCanvas.getContext('2d')

                  if (!ctx) {
                    console.warn('Canvas 2D context not supported')
                    reject(new Error('Canvas 2D context not supported'))
                    return
                  }

                  bwipConfig.scale = scale * scaleRatio
                  bwipConfig.paddingbottom = marginInMM + fontSize / scaleRatio
                  bwipjs.toCanvas(finalCanvas, bwipConfig)

                  // 设置最终canvas的尺寸
                  const finalWidth = finalCanvas.width
                  const finalHeight = finalCanvas.height

                  // 绘制文本
                  ctx.fillStyle = '#000000'
                  ctx.font = `${fontSize}px Arial`
                  ctx.textAlign = 'center'
                  ctx.fillText(
                    labelText,
                    finalWidth / 2,
                    finalHeight - fontSize - textMargin,
                  )

                  // 转换为blob
                  finalCanvas.toBlob(
                    (blob) => {
                      if (blob) {
                        resolve(blob)
                      } else {
                        reject(new Error('Failed to generate barcode image'))
                      }
                    },
                    `image/${imageFormat}`,
                    imageFormat === 'jpg' ? 0.9 : 1,
                  )
                } else {
                  // 如果不需要显示文本,直接使用原始尺寸
                  const canvas = document.createElement('canvas')
                  bwipjs.toCanvas(canvas, bwipConfig)

                  canvas.toBlob(
                    (blob) => {
                      if (blob) {
                        resolve(blob)
                      } else {
                        reject(new Error('Failed to generate barcode image'))
                      }
                    },
                    `image/${imageFormat}`,
                    imageFormat === 'jpg' ? 0.9 : 1,
                  )
                }
              }
            } catch (error) {
              console.error('BWIP-JS generation error:', error)
              reject(
                new Error(`Invalid barcode value for ${codeFormat}: ${value}`),
              )
            }
          }
        } catch (error) {
          console.error('Error generating barcode:', error)
          reject(new Error(`Failed to generate barcode: ${error}`))
        }
      }),
    [
      barcodeLength,
      barcodeHeight,
      barcodeMargin,
      showText,
      codeFormat,
      imageFormat,
    ],
  )

  const downloadBarcodes = useCallback(async () => {
    const lines = input.split('\n').filter((line) => line.trim() !== '')
    const parsed = lines.map(parseLine)

    if (parsed.length === 1) {
      const barcodeData = await generateBarcode(parsed[0])
      if (imageFormat === 'svg') {
        const blob = new Blob([barcodeData as string], {
          type: 'image/svg+xml;charset=utf-8',
        })
        FileSaver.saveAs(blob, `barcode-${codeFormat}.${imageFormat}`)
      } else {
        FileSaver.saveAs(
          barcodeData as Blob,
          `barcode-${codeFormat}.${imageFormat}`,
        )
      }
    } else {
      const zip = new JSZip()

      for (let i = 0; i < parsed.length; i++) {
        const barcodeData = await generateBarcode(parsed[i])
        if (imageFormat === 'svg') {
          zip.file(
            `barcode-${codeFormat}_${i + 1}.${imageFormat}`,
            barcodeData as string,
          )
        } else {
          zip.file(
            `barcode-${codeFormat}_${i + 1}.${imageFormat}`,
            barcodeData as Blob,
          )
        }
      }

      zip.generateAsync({ type: 'blob' }).then((content) => {
        FileSaver.saveAs(content, 'barcodes(barcode-maker).zip')
      })
    }
  }, [input, generateBarcode, imageFormat, codeFormat])

  return (
    <div className="flex flex-wrap items-center justify-center space-x-2 space-y-2">
      <Button
        size="lg"
        variant="outline"
        onClick={downloadBarcodes}
        title="download barcodes"
        className="h-10 border-none bg-gradient-to-r from-blue-600 via-purple-600 to-red-600 px-6 text-white hover:from-blue-700 hover:via-purple-700 hover:to-red-700"
      >
        <Download className="mr-2 h-4 w-4" />
        <span className="text-sm">Download</span>
      </Button>
      <span className="text-sm"> as</span>
      <Select
        value={imageFormat}
        onValueChange={(value: ImageFormat) => setImageFormat(value)}
      >
        <SelectTrigger className="h-8 w-[70px] bg-white">
          <SelectValue placeholder="Format" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="png">PNG</SelectItem>
          <SelectItem value="jpg">JPG</SelectItem>
          <SelectItem value="gif">GIF</SelectItem>
          <SelectItem value="svg">SVG</SelectItem>
        </SelectContent>
      </Select>
    </div>
  )
}


================================================
FILE: src/components/barcode-generator/ImportData.tsx
================================================
import React from 'react'
import { Button } from '@/components/ui/button'
import { Upload } from 'lucide-react'
import { useCSVReader } from 'react-papaparse'
// import * as XLSX from 'xlsx'

interface ImportDataProps {
  setInput: (input: string) => void
}

const ImportData: React.FC<ImportDataProps> = ({ setInput }) => {
  const { CSVReader } = useCSVReader()

  const handleCSVImport = (data: any) => {
    const importedData = data.data
      .map((row: string[]) => row.join('\t'))
      .join('\n')
    setInput(importedData)
  }

  //   const handleExcelImport = (e: React.ChangeEvent<HTMLInputElement>) => {
  //     const file = e.target.files?.[0]
  //     if (file) {
  //       const reader = new FileReader()
  //       reader.onload = (evt) => {
  //         const bstr = evt.target?.result
  //         const wb = XLSX.read(bstr, { type: 'binary' })
  //         const wsname = wb.SheetNames[0]
  //         const ws = wb.Sheets[wsname]
  //         const data = XLSX.utils.sheet_to_json(ws, { header: 1 }) as unknown[][]
  //         const importedData = data
  //           .map((row) => (row as any[]).join('\t'))
  //           .join('\n')
  //         setInput(importedData)
  //       }
  //       reader.readAsBinaryString(file)
  //     }
  //   }

  return (
    <div className="flex gap-2">
      <CSVReader onUploadAccepted={handleCSVImport}>
        {({ getRootProps }: any) => (
          <div className="flex  items-center ">
            <span className="text-xs">Import CSV</span>
            <Button
              {...getRootProps()}
              size="icon"
              variant="ghost"
              title="Import CSV"
            >
              <Upload className="h-5 w-5" />
            </Button>
          </div>
        )}
      </CSVReader>
      {/* <Button
        size="icon"
        variant="ghost"
        title="Import Excel"
        onClick={() => document.getElementById('excel-upload')?.click()}
      >
        <Upload className="h-5 w-5" />
        <input
          id="excel-upload"
          type="file"
          accept=".xlsx, .xls"
          onChange={handleExcelImport}
          style={{ display: 'none' }}
        />
      </Button> */}
    </div>
  )
}

export default ImportData


================================================
FILE: src/components/barcode-generator/ScrollControls.tsx
================================================
'use client'
import React, { useState, useEffect, useCallback, useRef } from 'react'
import { Button } from '@/components/ui/button'
import { Slider } from '@/components/ui/slider'
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip'
import { Play, Pause, ArrowUp, Settings } from 'lucide-react'
import { useTranslations } from 'next-intl'
import { useBarcodeContext } from './BarcodeContext'

const ScrollControls = ({
  outputRef,
}: {
  outputRef: React.RefObject<HTMLElement>
}) => {
  const [isScrolling, setIsScrolling] = useState(false)
  const [scrollSpeed, setScrollSpeed] = useState(2)
  const [showSettings, setShowSettings] = useState(false)
  const [showControls, setShowControls] = useState(false)
  const lastScrollTime = useRef(0)
  const animationFrameId = useRef<number | null>(null)
  const { output } = useBarcodeContext()

  useEffect(() => {
    const checkScrollable = () => {
      if (outputRef.current) {
        const isScrollable =
          outputRef.current.scrollHeight > outputRef.current.clientHeight
        setShowControls(isScrollable)
      }
    }

    checkScrollable()
    window.addEventListener('resize', checkScrollable)

    return () => {
      window.removeEventListener('resize', checkScrollable)
    }
  }, [outputRef, output])

  useEffect(() => {
    const scrollStep = (timestamp: number) => {
      if (!lastScrollTime.current) lastScrollTime.current = timestamp
      const deltaTime = timestamp - lastScrollTime.current
      const scrollAmount = (scrollSpeed * deltaTime) / 16 // 16ms is roughly one frame at 60fps

      if (outputRef.current) {
        outputRef.current.scrollTop += scrollAmount
        const { scrollTop, scrollHeight, clientHeight } = outputRef.current

        if (scrollTop + clientHeight >= scrollHeight) {
          setIsScrolling(false)
        } else if (isScrolling) {
          animationFrameId.current = requestAnimationFrame(scrollStep)
        }
      }

      lastScrollTime.current = timestamp
    }

    if (isScrolling) {
      lastScrollTime.current = 0
      animationFrameId.current = requestAnimationFrame(scrollStep)
    }

    return () => {
      if (animationFrameId.current) {
        cancelAnimationFrame(animationFrameId.current)
      }
    }
  }, [isScrolling, scrollSpeed, outputRef])

  const toggleScrolling = () => setIsScrolling(!isScrolling)

  const handleSpeedChange = (value: number[]) => setScrollSpeed(value[0])

  const scrollToTop = () => {
    setIsScrolling(false)
    if (outputRef.current) {
      outputRef.current.scrollTo({
        top: 0,
        behavior: 'smooth',
      })
    }
  }

  const t = useTranslations('scroll')

  if (!showControls) return null

  return (
    <TooltipProvider>
      <div className="relative flex items-center space-x-2">
        <Tooltip>
          <TooltipTrigger asChild>
            <Button size="icon" onClick={toggleScrolling} variant="ghost">
              {isScrolling ? (
                <Pause className="h-4 w-4" />
              ) : (
                <Play className="h-4 w-4" />
              )}
            </Button>
          </TooltipTrigger>
          <TooltipContent side="bottom">
            <p>{isScrolling ? t('pause-scroll') : t('start-scroll')}</p>
          </TooltipContent>
        </Tooltip>
        <Tooltip>
          <TooltipTrigger asChild>
            <Button size="icon" onClick={scrollToTop} variant="ghost">
              <ArrowUp className="h-4 w-4" />
            </Button>
          </TooltipTrigger>
          <TooltipContent side="bottom">
            <p>{t('to-top')}</p>
          </TooltipContent>
        </Tooltip>
        <Tooltip>
          <TooltipTrigger asChild>
            <Button
              size="icon"
              onClick={() => setShowSettings(!showSettings)}
              variant="ghost"
            >
              <Settings className="h-4 w-4" />
            </Button>
          </TooltipTrigger>
          <TooltipContent side="bottom">
            <p>{t('setting')}</p>
          </TooltipContent>
        </Tooltip>
        {showSettings && (
          <div className="absolute bottom-full right-0">
            <Slider
              orientation="horizontal"
              value={[scrollSpeed]}
              onValueChange={handleSpeedChange}
              max={10}
              step={1}
              className="h-4 w-24 rounded-lg border"
            />
          </div>
        )}
      </div>
    </TooltipProvider>
  )
}

export default ScrollControls


================================================
FILE: src/components/barcode-generator/index.tsx
================================================
'use client'
import React, { useState } from 'react'
import { BarcodeProvider } from './BarcodeContext'
import { BarcodeCarousel } from './BarcodeCarousel'
import {
  InputComponent,
  OptionsComponent,
  OutputComponent,
} from './BarcodeComponents'
import { useBarcodeGenerator } from './useBarcodeGenerator'
import { Locale } from '@/i18n'
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from '../ui/resizable'
import { DownloadBarcodes } from './DownloadBarcodes'
import { Separator } from '../ui/separator'
import { Button } from '../ui/button'
import { Menu, Sliders } from 'lucide-react'

const BarcodeGeneratorContent: React.FC = () => {
  useBarcodeGenerator()

  const [activePanel, setActivePanel] = useState<
    'main' | 'carousel' | 'options'
  >('main')
  const [isLeftPanelCollapsed, setIsLeftPanelCollapsed] = useState(false)
  const defaultLayout = [20, 50, 30]
  const navCollapsedSize = 4
  const togglePanel = (panel: 'carousel' | 'options') => {
    setActivePanel(activePanel === panel ? 'main' : panel)
  }

  return (
    <div className="barcode-generator-content">
      <div className="small-screen-layout">
        <div className="flex items-center justify-between p-2">
          <Button
            onClick={() => togglePanel('carousel')}
            variant="ghost"
            size="icon"
          >
            <Menu className="h-6 w-6" />
          </Button>
          <Button
            onClick={() => togglePanel('options')}
            variant="ghost"
            size="icon"
          >
            <Sliders className="h-6 w-6" />
          </Button>
        </div>
        <div className="flex-grow overflow-auto">
          <div className={`panel ${activePanel === 'main' ? 'active' : ''}`}>
            <div className="flex flex-col gap-4 p-4">
              <InputComponent />
              <OutputComponent />
              <DownloadBarcodes />
            </div>
          </div>
          <div
            className={`panel ${activePanel === 'carousel' ? 'active' : ''}`}
          >
            <div className="p-4">
              <BarcodeCarousel isCollapsed={false} />
            </div>
          </div>
          <div className={`panel ${activePanel === 'options' ? 'active' : ''}`}>
            <div className="p-4">
              <OptionsComponent />
            </div>
          </div>
        </div>
      </div>

      <div className="large-screen-layout">
        <ResizablePanelGroup
          direction="horizontal"
          className="h-full max-h-[800px] items-stretch"
        >
          <ResizablePanel
            defaultSize={defaultLayout[0]}
            collapsedSize={navCollapsedSize}
            collapsible={true}
            minSize={5}
            maxSize={22}
            onCollapse={() => setIsLeftPanelCollapsed(true)}
            onExpand={() => setIsLeftPanelCollapsed(false)}
          >
            <div className="p-4">
              <BarcodeCarousel isCollapsed={isLeftPanelCollapsed} />
            </div>
          </ResizablePanel>
          <ResizableHandle withHandle />
          <ResizablePanel defaultSize={defaultLayout[1]} minSize={30}>
            <div className="flex flex-col gap-4 p-4">
              <div>
                <InputComponent />
              </div>
              <div>
                <OutputComponent />
              </div>
            </div>
          </ResizablePanel>
          <ResizableHandle withHandle />
          <ResizablePanel defaultSize={defaultLayout[2]} minSize={30}>
            <div className="flex h-full flex-col p-4">
              <div className="">
                <OptionsComponent />
              </div>
              <div className="">
                <Separator className="my-4" />
                <DownloadBarcodes />
              </div>
            </div>
          </ResizablePanel>
        </ResizablePanelGroup>
      </div>
    </div>
  )
}

const BarcodeGenerator: React.FC<{
  codeFormat: string
  initialData: string
  locale: Locale
}> = ({ codeFormat, initialData, locale }) => {
  return (
    <BarcodeProvider value={{ initCodeFormat: codeFormat, initialData }}>
      <div className="container overflow-hidden rounded-[0.5rem] border shadow dark:bg-slate-100 dark:text-slate-900">
        <BarcodeGeneratorContent />
      </div>
    </BarcodeProvider>
  )
}

export default BarcodeGenerator


================================================
FILE: src/components/barcode-generator/share-button.tsx
================================================
import React, { useState } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Copy, Share2 } from 'lucide-react'
import { usePathname } from 'next/navigation'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog'
import { useBarcodeContext } from './BarcodeContext'

interface ShareButtonProps {
  variant?:
    | 'default'
    | 'destructive'
    | 'outline'
    | 'secondary'
    | 'ghost'
    | 'link'
  className?: string
  size?: 'default' | 'sm' | 'lg' | 'icon' | null | undefined
}

export const ShareButton: React.FC<ShareButtonProps> = ({
  variant,
  className,
  size,
}) => {
  const { input, codeFormat } = useBarcodeContext()
  const [open, setOpen] = useState(false)
  const pathname = usePathname()

  const generateShareLink = () => {
    const currentData = input
    const baseUrl = process.env.NEXT_PUBLIC_SITE_URL + pathname
    const shareUrl = `${baseUrl}?data=${encodeURIComponent(currentData)}`
    return shareUrl
  }

  const generateBarcodeLink = () => {
    const currentData = input
    const baseUrl = process.env.NEXT_PUBLIC_SITE_URL
    return `${baseUrl}/api/barcode/${codeFormat}/${encodeURIComponent(currentData)}`
  }

  const handleCopy = (text: string) => {
    navigator.clipboard.writeText(text)
    setOpen(false)
  }

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button variant={variant} className={className} size={size}>
          <Copy className="h-5 w-5" />
        </Button>
      </DialogTrigger>
      <DialogContent className="bg-white text-slate-900 sm:max-w-md">
        <DialogHeader>
          <DialogTitle>Copy Barcode Link</DialogTitle>
        </DialogHeader>
        <div className="flex flex-col space-y-4">
          <div>
            <p className="mb-2 text-sm font-medium">
              Link to This Barcode Image
            </p>
            <div className="flex items-center space-x-2">
              <Input
                className="flex-1"
                value={generateBarcodeLink()}
                readOnly
              />
              <Button
                onClick={() => handleCopy(generateBarcodeLink())}
                className="bg-slate-900 text-white"
              >
                Copy
              </Button>
            </div>
          </div>
          <div>
            <p className="mb-2 text-sm font-medium">Link to This Page</p>
            <div className="flex items-center space-x-2">
              <Input className="flex-1" value={generateShareLink()} readOnly />
              <Button
                onClick={() => handleCopy(generateShareLink())}
                className="bg-slate-900 text-white"
              >
                Copy
              </Button>
            </div>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  )
}


================================================
FILE: src/components/barcode-generator/useBarcodeGenerator.tsx
================================================
import { useCallback, useEffect } from 'react'
import JsBarcode from 'jsbarcode'
const bwipjs = require('bwip-js') as any
import { useBarcodeContext } from './BarcodeContext'
import { checkQRCode, jsBarcodeSupportedFormats } from '@/config/barcode-types'
import { parseLine } from '@/lib/parseLine'

export const useBarcodeGenerator = () => {
  const {
    input,
    setOutput,
    barcodeLength,
    barcodeHeight,
    showText,
    codeFormat,
    barcodeMargin,
  } = useBarcodeContext()

  const generateBarcodes = useCallback(() => {
    const lines = input.split('\n').filter((line) => line.trim() !== '')

    try {
      const barcodes = lines.map((line) => {
        const { barcodeValue: value, displayText } = parseLine(line)

        if (jsBarcodeSupportedFormats.includes(codeFormat.toUpperCase())) {
          // JsBarcode 配置
          const jsBarcodeConfig: Record<string, unknown> = {
            format: codeFormat.toUpperCase(),
            width: 2,
            height: barcodeHeight,
            displayValue: showText,
            font: 'Arial',
            fontSize: 15,
            margin: barcodeMargin,
            background: '#ffffff',
            lineColor: '#000000',
            textAlign: 'center',
            textPosition: 'bottom',
            textMargin: 2,
          }

          // When showText is on and user provided a custom caption, override
          // the rendered text (JsBarcode accepts a `text` option for this).
          if (showText && displayText !== undefined) {
            jsBarcodeConfig.text = displayText
          }

          const svg = document.createElementNS(
            'http://www.w3.org/2000/svg',
            'svg',
          )

          try {
            JsBarcode(svg, value, jsBarcodeConfig)
          } catch (error) {
            console.error('JsBarcode generation error:', error)
            throw new Error(`Invalid barcode value for ${codeFormat}: ${value}`)
          }

          svg.setAttribute('width', `${barcodeLength}`)
          return `<div class="barcode-item">${svg.outerHTML}</div>`
        } else {
          // BWIP-JS 配置
          const scale = 2
          const MM_TO_PX = 2.835 * scale // 72 dpi / 25.4 mm/in
          const heightInMM = barcodeHeight / MM_TO_PX
          const widthInMM = barcodeLength / MM_TO_PX
          const marginInMM = barcodeMargin / scale

          // 检查是否是二维码类型
          const isQRCode = checkQRCode(codeFormat)

          const fontSize = 15 // 假设字体大小为15px
          const textMargin = 2 // 假设文本与条码之间的间距为2px

          const bwipConfig: Record<string, unknown> = {
            bcid: codeFormat.toLowerCase(),
            text: value,
            scale: scale,
            height: heightInMM,
            width: widthInMM,
            includetext: showText,
            padding: marginInMM,
            paddingbottom:
              isQRCode && showText
                ? marginInMM + fontSize / +textMargin
                : marginInMM,
            backgroundcolor: 'ffffff',
            barcolor: '000000',
          }

          // bwip-js: use `alttext` to override the human-readable text below bars
          if (showText && displayText !== undefined) {
            bwipConfig.alttext = displayText
          }

          let svgString
          try {
            svgString = bwipjs.toSVG(bwipConfig)
          } catch (error) {
            console.error('BWIP-JS generation error:', error)
            throw new Error(`Invalid barcode value for ${codeFormat}: ${value}`)
          }

          // Parse SVG and set dimensions
          const parser = new DOMParser()
          const doc = parser.parseFromString(svgString, 'image/svg+xml')
          const svg = doc.documentElement

          svg.setAttribute('width', `${barcodeLength}`)
          svg.setAttribute(
            'height',
            `${isQRCode && showText ? barcodeHeight + fontSize + textMargin : barcodeHeight}`,
          )

          if (isQRCode && showText) {
            // 使用 Canvas 测量文本宽度
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')

            if (ctx === null) {
              console.warn('Canvas 2D context not supported')
              return `<div class="barcode-item">${svg.outerHTML}</div>`
            }

            // Measure the caption text (or fall back to the barcode value)
            const labelText = displayText !== undefined ? displayText : value
            ctx.font = `${fontSize}px Arial`
            const textWidth = ctx.measureText(labelText).width

            // 计算缩放比例
            const availableWidth = barcodeLength - marginInMM * 2
            const scaleRatio = Math.min(1, availableWidth / textWidth)

            // 创建text元素
            const text = document.createElementNS(
              'http://www.w3.org/2000/svg',
              'text',
            )
            text.setAttribute('x', `${(marginInMM * 2 + barcodeLength) / 2}`)
            text.setAttribute(
              'y',
              `${barcodeHeight + marginInMM * 2 + fontSize + textMargin}`,
            )
            text.setAttribute('text-anchor', 'middle')
            text.setAttribute('font-family', 'Arial')
            text.setAttribute('font-size', `${fontSize}`)
            text.setAttribute('transform', `scale(${scaleRatio})`)
            text.setAttribute(
              'transform-origin',
              `${marginInMM + barcodeLength / 2} ${barcodeHeight + marginInMM * 2 + fontSize + textMargin}`,
            )
            text.setAttribute('fill', '#000000')

            text.textContent = labelText
            svg.appendChild(text)

            svg.setAttribute(
              'height',
              `${barcodeHeight + fontSize + textMargin + marginInMM * 2}`,
            )
          }
          return `<div class="barcode-item">${svg.outerHTML}</div>`
        }
      })

      setOutput(barcodes)
    } catch (error) {
      console.error('Error generating barcodes:', error)
      setOutput([
        `<p class="error-message">Error generating barcodes: ${error}</p>`,
      ])
    }
  }, [
    input,
    setOutput,
    codeFormat,
    barcodeHeight,
    showText,
    barcodeMargin,
    barcodeLength,
  ])

  useEffect(() => {
    generateBarcodes()
  }, [generateBarcodes])

  return { generateBarcodes }
}


================================================
FILE: src/components/footer.tsx
================================================
import { GoogleAnalytics } from '@next/third-parties/google'
import Link from 'next/link'

export default function Footer() {
  return (
    <footer className="flex justify-center gap-4 py-8 text-sm">
      <span>&copy; {new Date().getFullYear()}</span>
      <Link href="/terms" className="hover:underline">
        Terms & Privacy
      </Link>
      <>
        {process.env.NEXT_PUBLIC_GOOGLE_TAG_ID ? (
          <>
            <GoogleAnalytics gaId={process.env.NEXT_PUBLIC_GOOGLE_TAG_ID} />
          </>
        ) : null}
      </>
    </footer>
  )
}


================================================
FILE: src/components/icons.tsx
================================================
import {
  LucideProps,
  Moon,
  SunMedium,
  Twitter,
  Languages,
  type Icon as LucideIcon,
} from 'lucide-react'

export type Icon = typeof LucideIcon

export const Icons = {
  sun: SunMedium,
  moon: Moon,
  twitter: Twitter,
  logo: (props: LucideProps) => (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}>
      <path
        fill="currentColor"
        d="M11.572 0c-.176 0-.31.001-.358.007a19.76 19.76 0 0 1-.364.033C7.443.346 4.25 2.185 2.228 5.012a11.875 11.875 0 0 0-2.119 5.243c-.096.659-.108.854-.108 1.747s.012 1.089.108 1.748c.652 4.506 3.86 8.292 8.209 9.695.779.25 1.6.422 2.534.525.363.04 1.935.04 2.299 0 1.611-.178 2.977-.577 4.323-1.264.207-.106.247-.134.219-.158-.02-.013-.9-1.193-1.955-2.62l-1.919-2.592-2.404-3.558a338.739 338.739 0 0 0-2.422-3.556c-.009-.002-.018 1.579-.023 3.51-.007 3.38-.01 3.515-.052 3.595a.426.426 0 0 1-.206.214c-.075.037-.14.044-.495.044H7.81l-.108-.068a.438.438 0 0 1-.157-.171l-.05-.106.006-4.703.007-4.705.072-.092a.645.645 0 0 1 .174-.143c.096-.047.134-.051.54-.051.478 0 .558.018.682.154.035.038 1.337 1.999 2.895 4.361a10760.433 10760.433 0 0 0 4.735 7.17l1.9 2.879.096-.063a12.317 12.317 0 0 0 2.466-2.163 11.944 11.944 0 0 0 2.824-6.134c.096-.66.108-.854.108-1.748 0-.893-.012-1.088-.108-1.747-.652-4.506-3.859-8.292-8.208-9.695a12.597 12.597 0 0 0-2.499-.523A33.119 33.119 0 0 0 11.573 0zm4.069 7.217c.347 0 .408.005.486.047a.473.473 0 0 1 .237.277c.018.06.023 1.365.018 4.304l-.006 4.218-.744-1.14-.746-1.14v-3.066c0-1.982.01-3.097.023-3.15a.478.478 0 0 1 .233-.296c.096-.05.13-.054.5-.054z"
      />
    </svg>
  ),
  gitHub: (props: LucideProps) => (
    <svg viewBox="0 0 438.549 438.549" {...props}>
      <path
        fill="currentColor"
        d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
      ></path>
    </svg>
  ),
  Languages,
}


================================================
FILE: src/components/language-toggle.tsx
================================================
'use client'

import * as React from 'react'
import { useRouter } from 'next/navigation'
import { usePathname } from 'next/navigation'

import { buttonVariants } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Icons } from '@/components/icons'
import { Locale, locales, languageNames } from '@/i18n'

interface LanguageToggleProps {
  locale: Locale
}

export function LanguageToggle({ locale }: LanguageToggleProps) {
  const router = useRouter()
  const pathname = usePathname()

  const switchLanguage = (newLocale: string) => {
    if (newLocale === locale) return
    const newPath = pathname.replace(`/${locale}`, `/${newLocale}`)
    router.push(newPath)
  }

  return (
    <DropdownMenu>
      <DropdownMenuTrigger>
        <div
          className={buttonVariants({
            size: 'icon',
            variant: 'ghost',
          })}
        >
          <Icons.Languages className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all" />
          <span className="sr-only">Toggle language</span>
        </div>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        {locales.map((lang) => (
          <DropdownMenuItem key={lang} onClick={() => switchLanguage(lang)}>
            {languageNames[lang]}
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  )
}


================================================
FILE: src/components/tailwind-indicator.tsx
================================================
export function TailwindIndicator() {
  if (process.env.NODE_ENV === "production") return null

  return (
    <div className="fixed bottom-1 left-1 z-50 flex h-6 w-6 items-center justify-center rounded-full bg-gray-800 p-3 font-mono text-xs text-white">
      <div className="block sm:hidden">xs</div>
      <div className="hidden sm:block md:hidden">sm</div>
      <div className="hidden md:block lg:hidden">md</div>
      <div className="hidden lg:block xl:hidden">lg</div>
      <div className="hidden xl:block 2xl:hidden">xl</div>
      <div className="hidden 2xl:block">2xl</div>
    </div>
  )
}


================================================
FILE: src/components/theme-provider.tsx
================================================
"use client"

import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}


================================================
FILE: src/components/theme-toggle.tsx
================================================
"use client"

import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"

import { Button } from "@/components/ui/button"

export function ThemeToggle() {
  const { setTheme, theme } = useTheme()

  return (
    <Button
      variant="ghost"
      size="icon"
      onClick={() => setTheme(theme === "light" ? "dark" : "light")}
    >
      <Sun className="h-[1.5rem] w-[1.3rem] dark:hidden" />
      <Moon className="hidden h-5 w-5 dark:block" />
      <span className="sr-only">Toggle theme</span>
    </Button>
  )
}


================================================
FILE: src/components/ui/button.tsx
================================================
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'

import { cn } from '@/lib/utils'

const buttonVariants = cva(
  'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default:
          'bg-primary text-primary-foreground shadow hover:bg-primary/90',
        destructive:
          'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
        outline:
          'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
        secondary:
          'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
        link: 'text-primary underline-offset-4 hover:underline',
      },
      size: {
        default: 'h-9 px-4 py-2',
        sm: 'h-8 rounded-md px-3 text-xs',
        lg: 'h-10 rounded-md px-8',
        icon: 'h-9 w-9',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  },
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : 'button'
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    )
  },
)
Button.displayName = 'Button'

export { Button, buttonVariants }


================================================
FILE: src/components/ui/card.tsx
================================================
import * as React from "react"

import { cn } from "@/lib/utils"

const Card = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn(
      "rounded-xl border bg-card text-card-foreground shadow",
      className
    )}
    {...props}
  />
))
Card.displayName = "Card"

const CardHeader = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("flex flex-col space-y-1.5 p-6", className)}
    {...props}
  />
))
CardHeader.displayName = "CardHeader"

const CardTitle = React.forwardRef<
  HTMLParagraphElement,
  React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
  <h3
    ref={ref}
    className={cn("font-semibold leading-none tracking-tight", className)}
    {...props}
  />
))
CardTitle.displayName = "CardTitle"

const CardDescription = React.forwardRef<
  HTMLParagraphElement,
  React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
  <p
    ref={ref}
    className={cn("text-sm text-muted-foreground", className)}
    {...props}
  />
))
CardDescription.displayName = "CardDescription"

const CardContent = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"

const CardFooter = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("flex items-center p-6 pt-0", className)}
    {...props}
  />
))
CardFooter.displayName = "CardFooter"

export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }


================================================
FILE: src/components/ui/carousel.tsx
================================================
"use client"

import * as React from "react"
import { ArrowLeftIcon, ArrowRightIcon } from "@radix-ui/react-icons"
import useEmblaCarousel, {
  type UseEmblaCarouselType,
} from "embla-carousel-react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"

type CarouselApi = UseEmblaCarouselType[1]
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
type CarouselOptions = UseCarouselParameters[0]
type CarouselPlugin = UseCarouselParameters[1]

type CarouselProps = {
  opts?: CarouselOptions
  plugins?: CarouselPlugin
  orientation?: "horizontal" | "vertical"
  setApi?: (api: CarouselApi) => void
}

type CarouselContextProps = {
  carouselRef: ReturnType<typeof useEmblaCarousel>[0]
  api: ReturnType<typeof useEmblaCarousel>[1]
  scrollPrev: () => void
  scrollNext: () => void
  canScrollPrev: boolean
  canScrollNext: boolean
} & CarouselProps

const CarouselContext = React.createContext<CarouselContextProps | null>(null)

function useCarousel() {
  const context = React.useContext(CarouselContext)

  if (!context) {
    throw new Error("useCarousel must be used within a <Carousel />")
  }

  return context
}

const Carousel = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement> & CarouselProps
>(
  (
    {
      orientation = "horizontal",
      opts,
      setApi,
      plugins,
      className,
      children,
      ...props
    },
    ref
  ) => {
    const [carouselRef, api] = useEmblaCarousel(
      {
        ...opts,
        axis: orientation === "horizontal" ? "x" : "y",
      },
      plugins
    )
    const [canScrollPrev, setCanScrollPrev] = React.useState(false)
    const [canScrollNext, setCanScrollNext] = React.useState(false)

    const onSelect = React.useCallback((api: CarouselApi) => {
      if (!api) {
        return
      }

      setCanScrollPrev(api.canScrollPrev())
      setCanScrollNext(api.canScrollNext())
    }, [])

    const scrollPrev = React.useCallback(() => {
      api?.scrollPrev()
    }, [api])

    const scrollNext = React.useCallback(() => {
      api?.scrollNext()
    }, [api])

    const handleKeyDown = React.useCallback(
      (event: React.KeyboardEvent<HTMLDivElement>) => {
        if (event.key === "ArrowLeft") {
          event.preventDefault()
          scrollPrev()
        } else if (event.key === "ArrowRight") {
          event.preventDefault()
          scrollNext()
        }
      },
      [scrollPrev, scrollNext]
    )

    React.useEffect(() => {
      if (!api || !setApi) {
        return
      }

      setApi(api)
    }, [api, setApi])

    React.useEffect(() => {
      if (!api) {
        return
      }

      onSelect(api)
      api.on("reInit", onSelect)
      api.on("select", onSelect)

      return () => {
        api?.off("select", onSelect)
      }
    }, [api, onSelect])

    return (
      <CarouselContext.Provider
        value={{
          carouselRef,
          api: api,
          opts,
          orientation:
            orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
          scrollPrev,
          scrollNext,
          canScrollPrev,
          canScrollNext,
        }}
      >
        <div
          ref={ref}
          onKeyDownCapture={handleKeyDown}
          className={cn("relative", className)}
          role="region"
          aria-roledescription="carousel"
          {...props}
        >
          {children}
        </div>
      </CarouselContext.Provider>
    )
  }
)
Carousel.displayName = "Carousel"

const CarouselContent = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
  const { carouselRef, orientation } = useCarousel()

  return (
    <div ref={carouselRef} className="overflow-hidden">
      <div
        ref={ref}
        className={cn(
          "flex",
          orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
          className
        )}
        {...props}
      />
    </div>
  )
})
CarouselContent.displayName = "CarouselContent"

const CarouselItem = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
  const { orientation } = useCarousel()

  return (
    <div
      ref={ref}
      role="group"
      aria-roledescription="slide"
      className={cn(
        "min-w-0 shrink-0 grow-0 basis-full",
        orientation === "horizontal" ? "pl-4" : "pt-4",
        className
      )}
      {...props}
    />
  )
})
CarouselItem.displayName = "CarouselItem"

const CarouselPrevious = React.forwardRef<
  HTMLButtonElement,
  React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
  const { orientation, scrollPrev, canScrollPrev } = useCarousel()

  return (
    <Button
      ref={ref}
      variant={variant}
      size={size}
      className={cn(
        "absolute  h-8 w-8 rounded-full",
        orientation === "horizontal"
          ? "-left-12 top-1/2 -translate-y-1/2"
          : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
        className
      )}
      disabled={!canScrollPrev}
      onClick={scrollPrev}
      {...props}
    >
      <ArrowLeftIcon className="h-4 w-4" />
      <span className="sr-only">Previous slide</span>
    </Button>
  )
})
CarouselPrevious.displayName = "CarouselPrevious"

const CarouselNext = React.forwardRef<
  HTMLButtonElement,
  React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
  const { orientation, scrollNext, canScrollNext } = useCarousel()

  return (
    <Button
      ref={ref}
      variant={variant}
      size={size}
      className={cn(
        "absolute h-8 w-8 rounded-full",
        orientation === "horizontal"
          ? "-right-12 top-1/2 -translate-y-1/2"
          : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
        className
      )}
      disabled={!canScrollNext}
      onClick={scrollNext}
      {...props}
    >
      <ArrowRightIcon className="h-4 w-4" />
      <span className="sr-only">Next slide</span>
    </Button>
  )
})
CarouselNext.displayName = "CarouselNext"

export {
  type CarouselApi,
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselPrevious,
  CarouselNext,
}


================================================
FILE: src/components/ui/dialog.tsx
================================================
"use client"

import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { Cross2Icon } from "@radix-ui/react-icons"

import { cn } from "@/lib/utils"

const Dialog = DialogPrimitive.Root

const DialogTrigger = DialogPrimitive.Trigger

const DialogPortal = DialogPrimitive.Portal

const DialogClose = DialogPrimitive.Close

const DialogOverlay = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Overlay
    ref={ref}
    className={cn(
      "fixed inset-0 z-50 bg-black/80  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
      className
    )}
    {...props}
  />
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName

const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
  <DialogPortal>
    <DialogOverlay />
    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
        className
      )}
      {...props}
    >
      {children}
      <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
        <Cross2Icon className="h-4 w-4" />
        <span className="sr-only">Close</span>
      </DialogPrimitive.Close>
    </DialogPrimitive.Content>
  </DialogPortal>
))
DialogContent.displayName = DialogPrimitive.Content.displayName

const DialogHeader = ({
  className,
  ...props
}: React.HTMLAttributes<HTMLDivElement>) => (
  <div
    className={cn(
      "flex flex-col space-y-1.5 text-center sm:text-left",
      className
    )}
    {...props}
  />
)
DialogHeader.displayName = "DialogHeader"

const DialogFooter = ({
  className,
  ...props
}: React.HTMLAttributes<HTMLDivElement>) => (
  <div
    className={cn(
      "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
      className
    )}
    {...props}
  />
)
DialogFooter.displayName = "DialogFooter"

const DialogTitle = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Title
    ref={ref}
    className={cn(
      "text-lg font-semibold leading-none tracking-tight",
      className
    )}
    {...props}
  />
))
DialogTitle.displayName = DialogPrimitive.Title.displayName

const DialogDescription = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Description
    ref={ref}
    className={cn("text-sm text-muted-foreground", className)}
    {...props}
  />
))
DialogDescription.displayName = DialogPrimitive.Description.displayName

export {
  Dialog,
  DialogPortal,
  DialogOverlay,
  DialogTrigger,
  DialogClose,
  DialogContent,
  DialogHeader,
  DialogFooter,
  DialogTitle,
  DialogDescription,
}


================================================
FILE: src/components/ui/dropdown-menu.tsx
================================================
"use client"

import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import {
  CheckIcon,
  ChevronRightIcon,
  DotFilledIcon,
} from "@radix-ui/react-icons"

import { cn } from "@/lib/utils"

const DropdownMenu = DropdownMenuPrimitive.Root

const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger

const DropdownMenuGroup = DropdownMenuPrimitive.Group

const DropdownMenuPortal = DropdownMenuPrimitive.Portal

const DropdownMenuSub = DropdownMenuPrimitive.Sub

const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup

const DropdownMenuSubTrigger = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
    inset?: boolean
  }
>(({ className, inset, children, ...props }, ref) => (
  <DropdownMenuPrimitive.SubTrigger
    ref={ref}
    className={cn(
      "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
      inset && "pl-8",
      className
    )}
    {...props}
  >
    {children}
    <ChevronRightIcon className="ml-auto h-4 w-4" />
  </DropdownMenuPrimitive.SubTrigger>
))
DropdownMenuSubTrigger.displayName =
  DropdownMenuPrimitive.SubTrigger.displayName

const DropdownMenuSubContent = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
  <DropdownMenuPrimitive.SubContent
    ref={ref}
    className={cn(
      "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
      className
    )}
    {...props}
  />
))
DropdownMenuSubContent.displayName =
  DropdownMenuPrimitive.SubContent.displayName

const DropdownMenuContent = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
  <DropdownMenuPrimitive.Portal>
    <DropdownMenuPrimitive.Content
      ref={ref}
      sideOffset={sideOffset}
      className={cn(
        "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
        "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
        className
      )}
      {...props}
    />
  </DropdownMenuPrimitive.Portal>
))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName

const DropdownMenuItem = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
    inset?: boolean
  }
>(({ className, inset, ...props }, ref) => (
  <DropdownMenuPrimitive.Item
    ref={ref}
    className={cn(
      "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      inset && "pl-8",
      className
    )}
    {...props}
  />
))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName

const DropdownMenuCheckboxItem = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
  <DropdownMenuPrimitive.CheckboxItem
    ref={ref}
    className={cn(
      "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      className
    )}
    checked={checked}
    {...props}
  >
    <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
      <DropdownMenuPrimitive.ItemIndicator>
        <CheckIcon className="h-4 w-4" />
      </DropdownMenuPrimitive.ItemIndicator>
    </span>
    {children}
  </DropdownMenuPrimitive.CheckboxItem>
))
DropdownMenuCheckboxItem.displayName =
  DropdownMenuPrimitive.CheckboxItem.displayName

const DropdownMenuRadioItem = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
  <DropdownMenuPrimitive.RadioItem
    ref={ref}
    className={cn(
      "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      className
    )}
    {...props}
  >
    <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
      <DropdownMenuPrimitive.ItemIndicator>
        <DotFilledIcon className="h-4 w-4 fill-current" />
      </DropdownMenuPrimitive.ItemIndicator>
    </span>
    {children}
  </DropdownMenuPrimitive.RadioItem>
))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName

const DropdownMenuLabel = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.Label>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
    inset?: boolean
  }
>(({ className, inset, ...props }, ref) => (
  <DropdownMenuPrimitive.Label
    ref={ref}
    className={cn(
      "px-2 py-1.5 text-sm font-semibold",
      inset && "pl-8",
      className
    )}
    {...props}
  />
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName

const DropdownMenuSeparator = React.forwardRef<
  React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
  <DropdownMenuPrimitive.Separator
    ref={ref}
    className={cn("-mx-1 my-1 h-px bg-muted", className)}
    {...props}
  />
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName

const DropdownMenuShortcut = ({
  className,
  ...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
  return (
    <span
      className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
      {...props}
    />
  )
}
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"

export {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuCheckboxItem,
  DropdownMenuRadioItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuGroup,
  DropdownMenuPortal,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuRadioGroup,
}


================================================
FILE: src/components/ui/input.tsx
================================================
import * as React from "react"

import { cn } from "@/lib/utils"

export interface InputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, type, ...props }, ref) => {
    return (
      <input
        type={type}
        className={cn(
          "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
          className
        )}
        ref={ref}
        {...props}
      />
    )
  }
)
Input.displayName = "Input"

export { Input }


================================================
FILE: src/components/ui/label.tsx
================================================
"use client"

import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const labelVariants = cva(
  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)

const Label = React.forwardRef<
  React.ElementRef<typeof LabelPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
    VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
  <LabelPrimitive.Root
    ref={ref}
    className={cn(labelVariants(), className)}
    {...props}
  />
))
Label.displayName = LabelPrimitive.Root.displayName

export { Label }


================================================
FILE: src/components/ui/radio-group.tsx
================================================
"use client"

import * as React from "react"
import { CheckIcon } from "@radix-ui/react-icons"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"

import { cn } from "@/lib/utils"

const RadioGroup = React.forwardRef<
  React.ElementRef<typeof RadioGroupPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
  return (
    <RadioGroupPrimitive.Root
      className={cn("grid gap-2", className)}
      {...props}
      ref={ref}
    />
  )
})
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName

const RadioGroupItem = React.forwardRef<
  React.ElementRef<typeof RadioGroupPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
  return (
    <RadioGroupPrimitive.Item
      ref={ref}
      className={cn(
        "aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
        className
      )}
      {...props}
    >
      <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
        <CheckIcon className="h-3.5 w-3.5 fill-primary" />
      </RadioGroupPrimitive.Indicator>
    </RadioGroupPrimitive.Item>
  )
})
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName

export { RadioGroup, RadioGroupItem }


================================================
FILE: src/components/ui/resizable.tsx
================================================
'use client'

import { DragHandleDots2Icon } from '@radix-ui/react-icons'
import * as ResizablePrimitive from 'react-resizable-panels'

import { cn } from '@/lib/utils'

const ResizablePanelGroup = ({
  className,
  ...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
  <ResizablePrimitive.PanelGroup
    className={cn(
      'flex h-full w-full data-[panel-group-direction=vertical]:flex-col',
      className,
    )}
    {...props}
  />
)

const ResizablePanel = ResizablePrimitive.Panel

const ResizableHandle = ({
  withHandle,
  className,
  ...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
  withHandle?: boolean
}) => (
  <ResizablePrimitive.PanelResizeHandle
    className={cn(
      'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
      className,
    )}
    {...props}
  >
    {withHandle && (
      <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
        <DragHandleDots2Icon className="h-2.5 w-2.5" />
      </div>
    )}
  </ResizablePrimitive.PanelResizeHandle>
)

export { ResizablePanelGroup, ResizablePanel, ResizableHandle }


================================================
FILE: src/components/ui/scroll-area.tsx
================================================
'use client'

import * as React from 'react'
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'

import { cn } from '@/lib/utils'

const ScrollArea = React.forwardRef<
  React.ElementRef<typeof ScrollAreaPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
  <ScrollAreaPrimitive.Root
    ref={ref}
    className={cn('relative overflow-hidden', className)}
    {...props}
  >
    <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
      {children}
    </ScrollAreaPrimitive.Viewport>
    <ScrollBar />
    <ScrollAreaPrimitive.Corner />
  </ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName

const ScrollBar = React.forwardRef<
  React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
  React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = 'vertical', ...props }, ref) => (
  <ScrollAreaPrimitive.ScrollAreaScrollbar
    ref={ref}
    orientation={orientation}
    className={cn(
      'flex touch-none select-none transition-colors',
      orientation === 'vertical' &&
        'h-full w-2.5 border-l border-l-transparent p-[1px]',
      orientation === 'horizontal' &&
        'h-2.5 flex-col border-t border-t-transparent p-[1px]',
      className,
    )}
    {...props}
  >
    <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
  </ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName

export { ScrollArea, ScrollBar }


================================================
FILE: src/components/ui/select.tsx
================================================
"use client"

import * as React from "react"
import {
  CaretSortIcon,
  CheckIcon,
  ChevronDownIcon,
  ChevronUpIcon,
} from "@radix-ui/react-icons"
import * as SelectPrimitive from "@radix-ui/react-select"

import { cn } from "@/lib/utils"

const Select = SelectPrimitive.Root

const SelectGroup = SelectPrimitive.Group

const SelectValue = SelectPrimitive.Value

const SelectTrigger = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Trigger>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
  <SelectPrimitive.Trigger
    ref={ref}
    className={cn(
      "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
      className
    )}
    {...props}
  >
    {children}
    <SelectPrimitive.Icon asChild>
      <CaretSortIcon className="h-4 w-4 opacity-50" />
    </SelectPrimitive.Icon>
  </SelectPrimitive.Trigger>
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName

const SelectScrollUpButton = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
  <SelectPrimitive.ScrollUpButton
    ref={ref}
    className={cn(
      "flex cursor-default items-center justify-center py-1",
      className
    )}
    {...props}
  >
    <ChevronUpIcon />
  </SelectPrimitive.ScrollUpButton>
))
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName

const SelectScrollDownButton = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
  <SelectPrimitive.ScrollDownButton
    ref={ref}
    className={cn(
      "flex cursor-default items-center justify-center py-1",
      className
    )}
    {...props}
  >
    <ChevronDownIcon />
  </SelectPrimitive.ScrollDownButton>
))
SelectScrollDownButton.displayName =
  SelectPrimitive.ScrollDownButton.displayName

const SelectContent = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => (
  <SelectPrimitive.Portal>
    <SelectPrimitive.Content
      ref={ref}
      className={cn(
        "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
        position === "popper" &&
          "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
        className
      )}
      position={position}
      {...props}
    >
      <SelectScrollUpButton />
      <SelectPrimitive.Viewport
        className={cn(
          "p-1",
          position === "popper" &&
            "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
        )}
      >
        {children}
      </SelectPrimitive.Viewport>
      <SelectScrollDownButton />
    </SelectPrimitive.Content>
  </SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName

const SelectLabel = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Label>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
  <SelectPrimitive.Label
    ref={ref}
    className={cn("px-2 py-1.5 text-sm font-semibold", className)}
    {...props}
  />
))
SelectLabel.displayName = SelectPrimitive.Label.displayName

const SelectItem = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
  <SelectPrimitive.Item
    ref={ref}
    className={cn(
      "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      className
    )}
    {...props}
  >
    <span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
      <SelectPrimitive.ItemIndicator>
        <CheckIcon className="h-4 w-4" />
      </SelectPrimitive.ItemIndicator>
    </span>
    <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
  </SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName

const SelectSeparator = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Separator>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
  <SelectPrimitive.Separator
    ref={ref}
    className={cn("-mx-1 my-1 h-px bg-muted", className)}
    {...props}
  />
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName

export {
  Select,
  SelectGroup,
  SelectValue,
  SelectTrigger,
  SelectContent,
  SelectLabel,
  SelectItem,
  SelectSeparator,
  SelectScrollUpButton,
  SelectScrollDownButton,
}


================================================
FILE: src/components/ui/separator.tsx
================================================
'use client'

import * as React from 'react'
import * as SeparatorPrimitive from '@radix-ui/react-separator'

import { cn } from '@/lib/utils'

const Separator = React.forwardRef<
  React.ElementRef<typeof SeparatorPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
  (
    { className, orientation = 'horizontal', decorative = true, ...props },
    ref,
  ) => (
    <SeparatorPrimitive.Root
      ref={ref}
      decorative={decorative}
      orientation={orientation}
      className={cn(
        'shrink-0 bg-border',
        orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
        className,
      )}
      {...props}
    />
  ),
)
Separator.displayName = SeparatorPrimitive.Root.displayName

export { Separator }


================================================
FILE: src/components/ui/sheet.tsx
================================================
"use client"

import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { Cross2Icon } from "@radix-ui/react-icons"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const Sheet = SheetPrimitive.Root

const SheetTrigger = SheetPrimitive.Trigger

const SheetClose = SheetPrimitive.Close

const SheetPortal = SheetPrimitive.Portal

const SheetOverlay = React.forwardRef<
  React.ElementRef<typeof SheetPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <SheetPrimitive.Overlay
    className={cn(
      "fixed inset-0 z-50 bg-black/80  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
      className
    )}
    {...props}
    ref={ref}
  />
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName

const sheetVariants = cva(
  "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
  {
    variants: {
      side: {
        top: "inset-x-0 top-0 bo
Download .txt
gitextract_ngu74d31/

├── .eslintrc.json
├── .gitignore
├── .husky/
│   └── pre-commit
├── .prettierrc
├── LICENSE
├── README.md
├── components.json
├── messages/
│   ├── de.json
│   ├── en.json
│   ├── es.json
│   ├── fr.json
│   ├── it.json
│   ├── ja.json
│   ├── ko.json
│   ├── nl.json
│   ├── ru.json
│   ├── sv.json
│   └── zh.json
├── next-sitemap.config.js
├── next.config.mjs
├── package.json
├── postcss.config.js
├── public/
│   ├── ads.txt
│   ├── robots.txt
│   ├── site.webmanifest
│   ├── sitemap-0.xml
│   └── sitemap.xml
├── src/
│   ├── app/
│   │   ├── [locale]/
│   │   │   ├── [barcodeType]/
│   │   │   │   └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   └── terms/
│   │   │       └── page.tsx
│   │   ├── api/
│   │   │   └── barcode/
│   │   │       └── [code]/
│   │   │           └── [data]/
│   │   │               └── route.ts
│   │   ├── error.tsx
│   │   ├── layout.tsx
│   │   └── not-found.tsx
│   ├── components/
│   │   ├── Header.tsx
│   │   ├── MarkdownContent.tsx
│   │   ├── barcode-generator/
│   │   │   ├── BarcodeCarousel.tsx
│   │   │   ├── BarcodeComponents.tsx
│   │   │   ├── BarcodeContext.tsx
│   │   │   ├── DownloadBarcodes.tsx
│   │   │   ├── ImportData.tsx
│   │   │   ├── ScrollControls.tsx
│   │   │   ├── index.tsx
│   │   │   ├── share-button.tsx
│   │   │   └── useBarcodeGenerator.tsx
│   │   ├── footer.tsx
│   │   ├── icons.tsx
│   │   ├── language-toggle.tsx
│   │   ├── tailwind-indicator.tsx
│   │   ├── theme-provider.tsx
│   │   ├── theme-toggle.tsx
│   │   └── ui/
│   │       ├── button.tsx
│   │       ├── card.tsx
│   │       ├── carousel.tsx
│   │       ├── dialog.tsx
│   │       ├── dropdown-menu.tsx
│   │       ├── input.tsx
│   │       ├── label.tsx
│   │       ├── radio-group.tsx
│   │       ├── resizable.tsx
│   │       ├── scroll-area.tsx
│   │       ├── select.tsx
│   │       ├── separator.tsx
│   │       ├── sheet.tsx
│   │       ├── slider.tsx
│   │       ├── switch.tsx
│   │       ├── tabs.tsx
│   │       ├── textarea.tsx
│   │       └── tooltip.tsx
│   ├── config/
│   │   ├── barcode-types.ts
│   │   └── site-i18n.ts
│   ├── i18n.ts
│   ├── lib/
│   │   ├── fonts.ts
│   │   ├── parseLine.ts
│   │   └── utils.ts
│   ├── middleware.ts
│   ├── navigation.ts
│   ├── styles/
│   │   └── globals.css
│   └── types/
│       ├── image.ts
│       └── nav.ts
├── tailwind.config.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (51 symbols across 31 files)

FILE: src/app/[locale]/[barcodeType]/page.tsx
  function BarcodePage (line 11) | function BarcodePage({
  function generateStaticParams (line 59) | function generateStaticParams() {

FILE: src/app/[locale]/layout.tsx
  function generateStaticParams (line 17) | function generateStaticParams() {
  function generateMetadata (line 21) | async function generateMetadata({
  type PageProps (line 34) | type PageProps = Readonly<{
  function RootLayout (line 39) | async function RootLayout({

FILE: src/app/[locale]/page.tsx
  function IndexPage (line 4) | function IndexPage({

FILE: src/app/[locale]/terms/page.tsx
  function generateMetadata (line 4) | async function generateMetadata({
  function TermsPage (line 16) | function TermsPage() {

FILE: src/app/api/barcode/[code]/[data]/route.ts
  function GET (line 7) | async function GET(

FILE: src/app/error.tsx
  type Props (line 5) | type Props = {
  function Error (line 10) | function Error({ error, reset }: Props) {

FILE: src/app/layout.tsx
  function RootLayout (line 16) | function RootLayout({

FILE: src/app/not-found.tsx
  function NotFound (line 7) | function NotFound() {

FILE: src/components/Header.tsx
  type SiteHeaderProps (line 10) | interface SiteHeaderProps {
  function SiteHeader (line 15) | function SiteHeader({ locale, codeFormat }: SiteHeaderProps) {

FILE: src/components/barcode-generator/BarcodeCarousel.tsx
  type BarcodeCarouselProps (line 16) | interface BarcodeCarouselProps {
  function BarcodeCarousel (line 20) | function BarcodeCarousel({ isCollapsed }: BarcodeCarouselProps) {

FILE: src/components/barcode-generator/BarcodeComponents.tsx
  type PrintButtonProps (line 93) | interface PrintButtonProps {

FILE: src/components/barcode-generator/BarcodeContext.tsx
  type BarcodeContextType (line 12) | interface BarcodeContextType {
  type FormatSettings (line 33) | interface FormatSettings {
  type SavedState (line 40) | interface SavedState {
  constant LOCAL_STORAGE_KEY (line 61) | const LOCAL_STORAGE_KEY = 'barcodeSettings'
  constant DEFAULT_SETTINGS (line 76) | const DEFAULT_SETTINGS: FormatSettings = {

FILE: src/components/barcode-generator/ImportData.tsx
  type ImportDataProps (line 7) | interface ImportDataProps {

FILE: src/components/barcode-generator/share-button.tsx
  type ShareButtonProps (line 16) | interface ShareButtonProps {

FILE: src/components/footer.tsx
  function Footer (line 4) | function Footer() {

FILE: src/components/icons.tsx
  type Icon (line 10) | type Icon = typeof LucideIcon

FILE: src/components/language-toggle.tsx
  type LanguageToggleProps (line 17) | interface LanguageToggleProps {
  function LanguageToggle (line 21) | function LanguageToggle({ locale }: LanguageToggleProps) {

FILE: src/components/tailwind-indicator.tsx
  function TailwindIndicator (line 1) | function TailwindIndicator() {

FILE: src/components/theme-provider.tsx
  function ThemeProvider (line 7) | function ThemeProvider({ children, ...props }: ThemeProviderProps) {

FILE: src/components/theme-toggle.tsx
  function ThemeToggle (line 9) | function ThemeToggle() {

FILE: src/components/ui/button.tsx
  type ButtonProps (line 37) | interface ButtonProps

FILE: src/components/ui/carousel.tsx
  type CarouselApi (line 12) | type CarouselApi = UseEmblaCarouselType[1]
  type UseCarouselParameters (line 13) | type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
  type CarouselOptions (line 14) | type CarouselOptions = UseCarouselParameters[0]
  type CarouselPlugin (line 15) | type CarouselPlugin = UseCarouselParameters[1]
  type CarouselProps (line 17) | type CarouselProps = {
  type CarouselContextProps (line 24) | type CarouselContextProps = {
  function useCarousel (line 35) | function useCarousel() {

FILE: src/components/ui/input.tsx
  type InputProps (line 5) | interface InputProps

FILE: src/components/ui/sheet.tsx
  type SheetContentProps (line 52) | interface SheetContentProps

FILE: src/components/ui/textarea.tsx
  type TextareaProps (line 5) | interface TextareaProps

FILE: src/config/barcode-types.ts
  function findBarcodeCategory (line 199) | function findBarcodeCategory(value: string): string | undefined {

FILE: src/config/site-i18n.ts
  type SiteConfig (line 3) | type SiteConfig = {
  function getSiteConfig (line 74) | function getSiteConfig(locale: Locale): SiteConfig {

FILE: src/i18n.ts
  type Locale (line 33) | type Locale = (typeof locales)[number]

FILE: src/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {

FILE: src/types/image.ts
  type ImageFormat (line 1) | type ImageFormat = 'png' | 'jpg' | 'gif' | 'svg'

FILE: src/types/nav.ts
  type NavItem (line 1) | interface NavItem {
Condensed preview — 83 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (250K chars).
[
  {
    "path": ".eslintrc.json",
    "chars": 40,
    "preview": "{\n  \"extends\": \"next/core-web-vitals\"\n}\n"
  },
  {
    "path": ".gitignore",
    "chars": 391,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 409,
    "preview": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nFILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| "
  },
  {
    "path": ".prettierrc",
    "chars": 126,
    "preview": "{\n  \"singleQuote\": true,\n  \"semi\": false,\n  \"plugins\": [\"prettier-plugin-tailwindcss\"],\n  \"tabWidth\": 2,\n  \"printWidth\":"
  },
  {
    "path": "LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2024 Leon Zeng\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "README.md",
    "chars": 3154,
    "preview": "# Barcode Generator\n\n![Barcode Generator Logo](https://barcode-maker.com/apple-touch-icon.png)\n\nBarcode Generator is a f"
  },
  {
    "path": "components.json",
    "chars": 346,
    "preview": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"new-york\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {"
  },
  {
    "path": "messages/de.json",
    "chars": 6634,
    "preview": "{\n  \"Index\": {\n    \"title\": \"Der kostenlose Barcode-Generator ist ein Online-Tool, mit dem Benutzer einfach verschiedene"
  },
  {
    "path": "messages/en.json",
    "chars": 5850,
    "preview": "{\n  \"Index\": {\n    \"title\": \"Free Barcode Generator is an online tool that allows users to easily create various formats"
  },
  {
    "path": "messages/es.json",
    "chars": 6990,
    "preview": "{\n  \"Index\": {\n    \"title\": \"El generador de códigos de barras gratuito es una herramienta en línea que permite a los us"
  },
  {
    "path": "messages/fr.json",
    "chars": 6944,
    "preview": "{\n  \"Index\": {\n    \"title\": \"Le générateur de codes-barres gratuit est un outil en ligne qui permet aux utilisateurs de "
  },
  {
    "path": "messages/it.json",
    "chars": 6671,
    "preview": "{\n  \"Index\": {\n    \"title\": \"Il generatore di codici a barre gratuito è uno strumento online che consente agli utenti di"
  },
  {
    "path": "messages/ja.json",
    "chars": 3689,
    "preview": "{\n  \"Index\": {\n    \"title\": \"無料バーコードジェネレーターは、ユーザーが様々な形式のバーコードやQRコードを簡単に作成できるオンラインツールです。複数のエンコーディングタイプをサポートし、リアルタイムで一括してバ"
  },
  {
    "path": "messages/ko.json",
    "chars": 3760,
    "preview": "{\n  \"Index\": {\n    \"title\": \"무료 바코드 생성기는 사용자가 쉽게 다양한 형식의 바코드와 QR 코드를 만들 수 있는 온라인 도구입니다. 여러 가지 인코딩 유형을 지원하며 사용자가 실시간으로 그리"
  },
  {
    "path": "messages/nl.json",
    "chars": 6403,
    "preview": "{\n  \"Index\": {\n    \"title\": \"De gratis barcodegenerator is een online tool waarmee gebruikers eenvoudig verschillende fo"
  },
  {
    "path": "messages/ru.json",
    "chars": 6483,
    "preview": "{\n  \"Index\": {\n    \"title\": \"Бесплатный генератор штрих-кодов - это онлайн-инструмент, который позволяет пользователям л"
  },
  {
    "path": "messages/sv.json",
    "chars": 6126,
    "preview": "{\n  \"Index\": {\n    \"title\": \"Den kostnadsfria streckkodsgeneratorn är ett onlineverktyg som gör det enkelt för användare"
  },
  {
    "path": "messages/zh.json",
    "chars": 2941,
    "preview": "{\n  \"Index\": {\n    \"title\": \"免费条码生成器是一个在线工具,可以让用户轻松创建各种格式的条码和二维码。它支持多种编码类型,并允许用户实时批量生成条码,完全免费使用\"\n  },\n  \"Barcode\": {\n   "
  },
  {
    "path": "next-sitemap.config.js",
    "chars": 194,
    "preview": "/** @type {import('next-sitemap').IConfig} */\nmodule.exports = {\n  siteUrl: process.env.SITE_URL || 'https://barcode-mak"
  },
  {
    "path": "next.config.mjs",
    "chars": 202,
    "preview": "import createNextIntlPlugin from 'next-intl/plugin'\n\nconst withNextIntl = createNextIntlPlugin()\n\n/** @type {import('nex"
  },
  {
    "path": "package.json",
    "chars": 2161,
    "preview": "{\n  \"name\": \"barcode-maker\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"postbuild\": \"next-sitemap\",\n  "
  },
  {
    "path": "postcss.config.js",
    "chars": 82,
    "preview": "module.exports = {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n}\n"
  },
  {
    "path": "public/ads.txt",
    "chars": 58,
    "preview": "google.com, pub-1038944396101874, DIRECT, f08c47fec0942fa0"
  },
  {
    "path": "public/robots.txt",
    "chars": 126,
    "preview": "# *\nUser-agent: *\nAllow: /\n\n# Host\nHost: https://barcode-maker.com\n\n# Sitemaps\nSitemap: https://barcode-maker.com/sitema"
  },
  {
    "path": "public/site.webmanifest",
    "chars": 263,
    "preview": "{\"name\":\"\",\"short_name\":\"\",\"icons\":[{\"src\":\"/android-chrome-192x192.png\",\"sizes\":\"192x192\",\"type\":\"image/png\"},{\"src\":\"/"
  },
  {
    "path": "public/sitemap-0.xml",
    "chars": 3722,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:news=\"http://ww"
  },
  {
    "path": "public/sitemap.xml",
    "chars": 191,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n<sitemap><loc>"
  },
  {
    "path": "src/app/[locale]/[barcodeType]/page.tsx",
    "chars": 1945,
    "preview": "import { useTranslations } from 'next-intl'\nimport { unstable_setRequestLocale } from 'next-intl/server'\nimport BarcodeG"
  },
  {
    "path": "src/app/[locale]/layout.tsx",
    "chars": 2183,
    "preview": "import '@/styles/globals.css'\nimport { Metadata } from 'next'\nimport { Inter } from 'next/font/google'\nimport { Locale, "
  },
  {
    "path": "src/app/[locale]/page.tsx",
    "chars": 326,
    "preview": "import { unstable_setRequestLocale } from 'next-intl/server'\nimport { redirect } from 'next/navigation'\n\nexport default "
  },
  {
    "path": "src/app/[locale]/terms/page.tsx",
    "chars": 7960,
    "preview": "import { Metadata } from 'next'\nimport { getSiteConfig } from '@/config/site-i18n'\n\nexport async function generateMetada"
  },
  {
    "path": "src/app/api/barcode/[code]/[data]/route.ts",
    "chars": 2375,
    "preview": "import { NextRequest, NextResponse } from 'next/server'\nimport JsBarcode from 'jsbarcode'\nimport { DOMImplementation, XM"
  },
  {
    "path": "src/app/error.tsx",
    "chars": 562,
    "preview": "'use client'\n\nimport { useEffect } from 'react'\n\ntype Props = {\n  error: Error\n  reset(): void\n}\n\nexport default functio"
  },
  {
    "path": "src/app/layout.tsx",
    "chars": 487,
    "preview": "import '@/styles/globals.css'\nimport type { Metadata } from 'next'\n\nexport const metadata: Metadata = {\n  icons: {\n    i"
  },
  {
    "path": "src/app/not-found.tsx",
    "chars": 1161,
    "preview": "import { buttonVariants } from '@/components/ui/button'\n\n// Render the default Next.js 404 page when a route\n// is reque"
  },
  {
    "path": "src/components/Header.tsx",
    "chars": 1476,
    "preview": "import Link from 'next/link'\n\nimport { getSiteConfig } from '@/config/site-i18n'\nimport { ThemeToggle } from '@/componen"
  },
  {
    "path": "src/components/MarkdownContent.tsx",
    "chars": 690,
    "preview": "import ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst MarkdownContent = ({ content }: { c"
  },
  {
    "path": "src/components/barcode-generator/BarcodeCarousel.tsx",
    "chars": 4359,
    "preview": "'use client'\n\nimport React, { useState, useMemo } from 'react'\nimport Link from 'next/link'\nimport Image from 'next/imag"
  },
  {
    "path": "src/components/barcode-generator/BarcodeComponents.tsx",
    "chars": 9311,
    "preview": "import React from 'react'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textar"
  },
  {
    "path": "src/components/barcode-generator/BarcodeContext.tsx",
    "chars": 6591,
    "preview": "'use client'\nimport { barcodeTypes, checkQRCode } from '@/config/barcode-types'\nimport { ImageFormat } from '@/types/ima"
  },
  {
    "path": "src/components/barcode-generator/DownloadBarcodes.tsx",
    "chars": 13837,
    "preview": "import React, { useCallback } from 'react'\nimport { Button } from '@/components/ui/button'\nimport {\n  Select,\n  SelectCo"
  },
  {
    "path": "src/components/barcode-generator/ImportData.tsx",
    "chars": 2243,
    "preview": "import React from 'react'\nimport { Button } from '@/components/ui/button'\nimport { Upload } from 'lucide-react'\nimport {"
  },
  {
    "path": "src/components/barcode-generator/ScrollControls.tsx",
    "chars": 4539,
    "preview": "'use client'\nimport React, { useState, useEffect, useCallback, useRef } from 'react'\nimport { Button } from '@/component"
  },
  {
    "path": "src/components/barcode-generator/index.tsx",
    "chars": 4372,
    "preview": "'use client'\nimport React, { useState } from 'react'\nimport { BarcodeProvider } from './BarcodeContext'\nimport { Barcode"
  },
  {
    "path": "src/components/barcode-generator/share-button.tsx",
    "chars": 2956,
    "preview": "import React, { useState } from 'react'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/compone"
  },
  {
    "path": "src/components/barcode-generator/useBarcodeGenerator.tsx",
    "chars": 6319,
    "preview": "import { useCallback, useEffect } from 'react'\nimport JsBarcode from 'jsbarcode'\nconst bwipjs = require('bwip-js') as an"
  },
  {
    "path": "src/components/footer.tsx",
    "chars": 559,
    "preview": "import { GoogleAnalytics } from '@next/third-parties/google'\nimport Link from 'next/link'\n\nexport default function Foote"
  },
  {
    "path": "src/components/icons.tsx",
    "chars": 3907,
    "preview": "import {\n  LucideProps,\n  Moon,\n  SunMedium,\n  Twitter,\n  Languages,\n  type Icon as LucideIcon,\n} from 'lucide-react'\n\ne"
  },
  {
    "path": "src/components/language-toggle.tsx",
    "chars": 1447,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { usePathname } from 'ne"
  },
  {
    "path": "src/components/tailwind-indicator.tsx",
    "chars": 603,
    "preview": "export function TailwindIndicator() {\n  if (process.env.NODE_ENV === \"production\") return null\n\n  return (\n    <div clas"
  },
  {
    "path": "src/components/theme-provider.tsx",
    "chars": 327,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\"\nimport { "
  },
  {
    "path": "src/components/theme-toggle.tsx",
    "chars": 572,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport { Moon, Sun } from \"lucide-react\"\nimport { useTheme } from \"next-the"
  },
  {
    "path": "src/components/ui/button.tsx",
    "chars": 1838,
    "preview": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class"
  },
  {
    "path": "src/components/ui/card.tsx",
    "chars": 1847,
    "preview": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Card = React.forwardRef<\n  HTMLDivElement,\n  Rea"
  },
  {
    "path": "src/components/ui/carousel.tsx",
    "chars": 6249,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport { ArrowLeftIcon, ArrowRightIcon } from \"@radix-ui/react-icons\"\nimpor"
  },
  {
    "path": "src/components/ui/dialog.tsx",
    "chars": 3876,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { Cross2Ic"
  },
  {
    "path": "src/components/ui/dropdown-menu.tsx",
    "chars": 7366,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimpo"
  },
  {
    "path": "src/components/ui/input.tsx",
    "chars": 801,
    "preview": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface InputProps\n  extends React.InputHTMLA"
  },
  {
    "path": "src/components/ui/label.tsx",
    "chars": 724,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { cva, type "
  },
  {
    "path": "src/components/ui/radio-group.tsx",
    "chars": 1439,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport { CheckIcon } from \"@radix-ui/react-icons\"\nimport * as RadioGroupPri"
  },
  {
    "path": "src/components/ui/resizable.tsx",
    "chars": 1748,
    "preview": "'use client'\n\nimport { DragHandleDots2Icon } from '@radix-ui/react-icons'\nimport * as ResizablePrimitive from 'react-res"
  },
  {
    "path": "src/components/ui/scroll-area.tsx",
    "chars": 1657,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'\n\nimport "
  },
  {
    "path": "src/components/ui/select.tsx",
    "chars": 5651,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n  CaretSortIcon,\n  CheckIcon,\n  ChevronDownIcon,\n  ChevronUpIcon,\n"
  },
  {
    "path": "src/components/ui/separator.tsx",
    "chars": 773,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\n\nimport { c"
  },
  {
    "path": "src/components/ui/sheet.tsx",
    "chars": 4307,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\"\nimport { Cross2Ico"
  },
  {
    "path": "src/components/ui/slider.tsx",
    "chars": 1036,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as SliderPrimitive from '@radix-ui/react-slider'\n\nimport { cn } fr"
  },
  {
    "path": "src/components/ui/switch.tsx",
    "chars": 1162,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as SwitchPrimitives from '@radix-ui/react-switch'\n\nimport { cn } f"
  },
  {
    "path": "src/components/ui/tabs.tsx",
    "chars": 1894,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\n\nimport { cn } from '"
  },
  {
    "path": "src/components/ui/textarea.tsx",
    "chars": 732,
    "preview": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface TextareaProps\n  extends React.Textare"
  },
  {
    "path": "src/components/ui/tooltip.tsx",
    "chars": 1142,
    "preview": "\"use client\"\n\nimport * as React from \"react\"\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\"\n\nimport { cn } "
  },
  {
    "path": "src/config/barcode-types.ts",
    "chars": 7799,
    "preview": "export const barcodeTypes = [\n  {\n    name: 'Code 128',\n    types: [\n      { name: 'Code 128', value: 'Code128', initDat"
  },
  {
    "path": "src/config/site-i18n.ts",
    "chars": 3896,
    "preview": "import { Locale } from '@/i18n'\n\ntype SiteConfig = {\n  name: string\n  description: string\n  // mainNav: { title: string;"
  },
  {
    "path": "src/i18n.ts",
    "chars": 912,
    "preview": "import { notFound } from 'next/navigation'\nimport { getRequestConfig } from 'next-intl/server'\n\n// Can be imported from "
  },
  {
    "path": "src/lib/fonts.ts",
    "chars": 257,
    "preview": "import { JetBrains_Mono as FontMono, Inter as FontSans } from \"next/font/google\"\n\nexport const fontSans = FontSans({\n  s"
  },
  {
    "path": "src/lib/parseLine.ts",
    "chars": 945,
    "preview": "/**\n * Parse a single input line into { barcodeValue, displayText }.\n *\n * Format:  \"value\\tcaption\"\n *   - If a tab cha"
  },
  {
    "path": "src/lib/utils.ts",
    "chars": 166,
    "preview": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: Cla"
  },
  {
    "path": "src/middleware.ts",
    "chars": 359,
    "preview": "import createMiddleware from 'next-intl/middleware'\nimport { locales, defaultLocale, localePrefix } from './i18n'\n\nexpor"
  },
  {
    "path": "src/navigation.ts",
    "chars": 238,
    "preview": "import { createSharedPathnamesNavigation } from 'next-intl/navigation'\nimport { locales, localePrefix } from './i18n'\n\ne"
  },
  {
    "path": "src/styles/globals.css",
    "chars": 2367,
    "preview": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  :root {\n    --background: linear-gradient(to"
  },
  {
    "path": "src/types/image.ts",
    "chars": 56,
    "preview": "export type ImageFormat = 'png' | 'jpg' | 'gif' | 'svg'\n"
  },
  {
    "path": "src/types/nav.ts",
    "chars": 103,
    "preview": "export interface NavItem {\n  title: string\n  href?: string\n  disabled?: boolean\n  external?: boolean\n}\n"
  },
  {
    "path": "tailwind.config.ts",
    "chars": 2218,
    "preview": "import type { Config } from 'tailwindcss'\n\nconst config = {\n  darkMode: ['class'],\n  content: [\n    './pages/**/*.{ts,ts"
  },
  {
    "path": "tsconfig.json",
    "chars": 583,
    "preview": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n  "
  }
]

About this extraction

This page contains the full source code of the LeonZeng919/barcode-generator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 83 files (215.1 KB), approximately 62.2k tokens, and a symbol index with 51 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!